summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-01-05 12:08:20 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2018-01-05 12:08:20 +0100
commit3dbe78ab5c0be677b142a6c111942557ba761f1c (patch)
tree034e6a794e756c9b48f1c5938b381d00e5c5fb37
parent052d1c9e0756db2b02da98c97a6c50d26b8c28ce (diff)
parent8201a940e313cd9c2f989a7af5d6a4fb3f8ab31c (diff)
downloadbarebox-3dbe78ab5c0be677b142a6c111942557ba761f1c.tar.gz
barebox-3dbe78ab5c0be677b142a6c111942557ba761f1c.tar.xz
Merge branch 'for-next/net'
-rw-r--r--Documentation/user/automount.rst2
-rw-r--r--Documentation/user/booting-linux.rst40
-rw-r--r--Documentation/user/networking.rst101
-rw-r--r--arch/arm/boards/afi-gf/defaultenv-gf/init/automount10
-rw-r--r--arch/arm/boards/afi-gf/defaultenv-gf/network/eth118
-rw-r--r--arch/arm/boards/technexion-pico-hobbit/Makefile1
-rw-r--r--arch/arm/boards/technexion-pico-hobbit/board.c2
-rw-r--r--arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/init/automount11
-rw-r--r--arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/network/eth118
-rw-r--r--arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/init/automount17
-rw-r--r--arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth118
-rw-r--r--arch/arm/mach-omap/xload.c10
-rw-r--r--commands/Kconfig10
-rw-r--r--commands/Makefile2
-rw-r--r--commands/detect.c21
-rw-r--r--commands/dhcp.c29
-rw-r--r--commands/ip-route-get.c96
-rw-r--r--commands/net.c66
-rw-r--r--common/globalvar.c6
-rw-r--r--defaultenv/defaultenv-2-base/bin/bootargs-ip11
-rw-r--r--defaultenv/defaultenv-2-base/boot/net3
-rw-r--r--defaultenv/defaultenv-2-base/init/automount4
-rw-r--r--defaultenv/defaultenv-2-base/network/README3
-rw-r--r--defaultenv/defaultenv-2-base/network/eth018
-rw-r--r--drivers/base/driver.c8
-rw-r--r--include/dhcp.h24
-rw-r--r--include/driver.h1
-rw-r--r--include/net.h31
-rw-r--r--net/dhcp.c568
-rw-r--r--net/dns.c10
-rw-r--r--net/eth.c41
-rw-r--r--net/ifup.c281
-rw-r--r--net/net.c181
33 files changed, 884 insertions, 778 deletions
diff --git a/Documentation/user/automount.rst b/Documentation/user/automount.rst
index a5e4313576..7de8261354 100644
--- a/Documentation/user/automount.rst
+++ b/Documentation/user/automount.rst
@@ -13,7 +13,7 @@ Typical usage is for accessing the TFTP server. To set up an automount for a
TFTP server, the following is required::
mkdir -p /mnt/tftp
- automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
+ automount /mnt/tftp 'ifup -a && mount -t tftp $global.net.server /mnt/tftp'
This creates an automountpoint on ``/mnt/tftp``. Whenever this directory is accessed,
the command ``ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp`` is executed.
diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index 66f64ece08..b5e4320ef6 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -232,43 +232,20 @@ Network boot
With the following steps, barebox can start the kernel and root filesystem
over the network, a standard development case.
-Configure network: edit ``/env/network/eth0``. For a standard DHCP setup
-the following is enough:
-
-.. code-block:: sh
-
- #!/bin/sh
-
- ip=dhcp
- serverip=192.168.23.45
-
-The optional setting ``serverip`` specifies the IP address of your TFTP and NFS
-server, and is only necessary if it differs from the server IP offered by the
-DHCP server (i.e., the field ``siaddr`` in the DHCP ACK Reply).
-
-A static IP setup can look like this:
-
-.. code-block:: sh
-
- #!/bin/sh
-
- ip=static
- ipaddr=192.168.2.10
- netmask=255.255.0.0
- gateway=192.168.2.1
- serverip=192.168.2.1
+See :ref:`networking` for informations how to configure your network interfaces.
Note that barebox will pass the same IP settings to the kernel, i.e. it passes
-``ip=$ipaddr:$serverip:$gateway:$netmask::eth0:`` for a static IP setup and
-``ip=dhcp`` for a dynamic DHCP setup.
+``ip=$ipaddr:$serverip:$gateway:$netmask::<linuxdevname>:`` for a static IP setup
+and ``ip=dhcp`` for a dynamic DHCP setup. ``<linuxdevname>`` is a configurable value.
+set ``nv.dev.<ethdev>.linuxdevname`` to the name the device has in Linux.
By default, barebox uses the variables ``global.user`` and ``global.hostname``
to retrieve its kernel image over TFTP, which makes it possible to use multiple
boards for multiple users with one single server.
-You can adjust those variables in ``/env/config``::
+You can adjust those variables using nvvars with these commands::
- global.user=sha
- global.hostname=efikasb
+ nv user=sha
+ nv hostname=efikasb
Copy the kernel (and devicetree if needed) to the root directory of your TFTP
server, and name them accordingly; for example::
@@ -311,7 +288,8 @@ If the preconfigured paths or names are not suitable, they can be adjusted in
fi
nfsroot="/home/${global.user}/nfsroot/${global.hostname}"
- bootargs-ip
+ ip_route_get -b ${global.net.server} global.linux.bootargs.dyn.ip
+
global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
``boot net`` will then retrieve the kernel (and also the device tree and
diff --git a/Documentation/user/networking.rst b/Documentation/user/networking.rst
index 8afb433837..5822165281 100644
--- a/Documentation/user/networking.rst
+++ b/Documentation/user/networking.rst
@@ -1,3 +1,5 @@
+.. _networking:
+
Networking
==========
@@ -7,6 +9,49 @@ barebox has IPv4 networking support. Several protocols such as :ref:`DHCP
Network configuration
---------------------
+Lowlevel network device configuration
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Network devices are configured with a set of device specific variables:
+
++-------------------+--------------+----------------------------------------------------+
+| name | type | |
++===================+==============+====================================================+
+| <devname>.mode | enum | "dhcp": DHCP is used to get IP address and netmask |
+| | | "static": Static IP setup described by variables |
+| | | below |
+| | | "disabled": Interface unused |
++-------------------+--------------+----------------------------------------------------+
+| <devname>.ipaddr | ipv4 address | The IP address when using static configuration |
++-------------------+--------------+----------------------------------------------------+
+| <devname>.netmask | ipv4 address | The netmask when using static configuration |
++-------------------+--------------+----------------------------------------------------+
+| <devname>.gateway | ipv4 address | Alias for global.net.gateway. For |
+| | | compatibility, do not use. |
++-------------------+--------------+----------------------------------------------------+
+| <devname>.serverip| ipv4 address | Alias for global.net.server. For |
+| | | compatibility, do not use. |
++-------------------+--------------+----------------------------------------------------+
+| <devname>.ethaddr | MAC address | The MAC address of this device |
++-------------------+--------------+----------------------------------------------------+
+
+Additionally there are some more variables that are not specific to a
+device:
+
++------------------------------+--------------+------------------------------------------------+
+| name | type | |
++==============================+==============+================================================+
+| global.net.gateway | ipv4 host | The network gateway used when a host is not in |
+| | | any directly visible subnet. May be set |
+| | | automatically by DHCP. |
++------------------------------+--------------+------------------------------------------------+
+| global.net.server | ipv4 host | The default server address. If unspecified, may|
+| | | be set by DHCP |
++------------------------------+--------------+------------------------------------------------+
+| global.net.nameserver | ipv4 address | The DNS server used for resolving host names. |
+| | | May be set by DHCP |
++------------------------------+--------------+------------------------------------------------+
+
The first step for networking is configuring the network device. The network
device is usually ``eth0``. The current configuration can be viewed with the
:ref:`devinfo <command_devinfo>` command:
@@ -16,10 +61,9 @@ device is usually ``eth0``. The current configuration can be viewed with the
barebox:/ devinfo eth0
Parameters:
ethaddr: 00:1c:49:01:03:4b
- gateway: 192.168.23.1
ipaddr: 192.168.23.197
netmask: 255.255.0.0
- serverip: 192.168.23.1
+ [...]
The configuration can be changed on the command line with:
@@ -30,9 +74,56 @@ The configuration can be changed on the command line with:
The :ref:`dhcp command <command_dhcp>` will change the settings based on the answer
from the DHCP server.
-This low-level configuration of the network interface is often not necessary. Normally
-the network settings should be edited in ``/env/network/eth0``, then the network interface
-can be brought up using the :ref:`ifup command <command_ifup>`.
+To make the network device settings persistent across reboots there is a nonvolatile
+variable (nvvar) for each of the varariables above. The network device specific variables
+are:
+
+.. code-block:: sh
+
+ nv.dev.<devname>.mode
+ nv.dev.<devname>.ipaddr
+ nv.dev.<devname>.netmask
+ nv.dev.<devname>.ethaddr
+
+The others are:
+
+.. code-block:: sh
+
+ nv.net.gateway
+ nv.net.server
+ nv.net.nameserver
+
+A typical simple network setting is to use DHCP. Provided the network interface is eth0
+then this would configure the network device for DHCP:
+
+.. code-block:: sh
+
+ nv dev.eth0.mode=dhcp
+
+(In fact DHCP is the default, so the above is not necessary)
+
+A static setup would look like:
+
+.. code-block:: sh
+
+ nv dev.eth0.mode=static
+ nv dev.eth0.ipaddr=192.168.0.17
+ nv dev.eth0.netmask=255.255.0.0
+ nv net.server=192.168.0.1
+
+The settings can be activated with the :ref:`ifup command <command_ifup>`:
+
+.. code-block:: sh
+
+ ifup eth0
+
+or:
+
+.. code-block:: sh
+
+ ifup -a
+
+'ifup -a' will activate all ethernet interfaces, also the ones on USB.
Network filesystems
-------------------
diff --git a/arch/arm/boards/afi-gf/defaultenv-gf/init/automount b/arch/arm/boards/afi-gf/defaultenv-gf/init/automount
deleted file mode 100644
index 560bdb7975..0000000000
--- a/arch/arm/boards/afi-gf/defaultenv-gf/init/automount
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-# automount tftp server based on $eth1.serverip
-
-mkdir -p /mnt/tftp
-automount /mnt/tftp 'ifup eth1 && mount -t tftp $eth1.serverip /mnt/tftp'
-
-# eth0 is on the mezzanine board
-mkdir -p /mnt/tftp-eth0
-automount /mnt/tftp-eth0 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
diff --git a/arch/arm/boards/afi-gf/defaultenv-gf/network/eth1 b/arch/arm/boards/afi-gf/defaultenv-gf/network/eth1
deleted file mode 100644
index 1ed3017e96..0000000000
--- a/arch/arm/boards/afi-gf/defaultenv-gf/network/eth1
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-# ip setting (static/dhcp)
-ip=dhcp
-global.dhcp.vendor_id=barebox-${global.hostname}
-
-# static setup used if ip=static
-ipaddr=
-netmask=
-gateway=
-serverip=
-
-# MAC address if needed
-#ethaddr=xx:xx:xx:xx:xx:xx
-
-# put code to discover eth1 (i.e. 'usb') to /env/network/eth0-discover
-
-exit 0
diff --git a/arch/arm/boards/technexion-pico-hobbit/Makefile b/arch/arm/boards/technexion-pico-hobbit/Makefile
index 02e17035a0..01c7a259e9 100644
--- a/arch/arm/boards/technexion-pico-hobbit/Makefile
+++ b/arch/arm/boards/technexion-pico-hobbit/Makefile
@@ -1,3 +1,2 @@
obj-y += board.o
lwl-y += lowlevel.o
-bbenv-y += defaultenv-pico-hobbit
diff --git a/arch/arm/boards/technexion-pico-hobbit/board.c b/arch/arm/boards/technexion-pico-hobbit/board.c
index d3109fc390..f52f827f46 100644
--- a/arch/arm/boards/technexion-pico-hobbit/board.c
+++ b/arch/arm/boards/technexion-pico-hobbit/board.c
@@ -56,8 +56,6 @@ static int pico_hobbit_device_init(void)
barebox_set_hostname("pico-hobbit");
- defaultenv_append_directory(defaultenv_pico_hobbit);
-
return 0;
}
device_initcall(pico_hobbit_device_init);
diff --git a/arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/init/automount b/arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/init/automount
deleted file mode 100644
index fdcfa36045..0000000000
--- a/arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/init/automount
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-# automount tftp server based on $eth1.serverip
-
-mkdir -p /mnt/tftp
-automount /mnt/tftp 'ifup eth1 && mount -t tftp $eth1.serverip /mnt/tftp'
-
-# automount nfs server's nfsroot
-
-mkdir -p /mnt/nfs
-automount /mnt/nfs 'ifup eth1 && mount -t nfs ${eth1.serverip}:/home/${global.user}/nfsroot/${global.hostname} /mnt/nfs'
diff --git a/arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/network/eth1 b/arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/network/eth1
deleted file mode 100644
index dfe63971df..0000000000
--- a/arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/network/eth1
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-# ip setting (static/dhcp)
-ip=dhcp
-global.dhcp.vendor_id=barebox-${global.hostname}
-
-# static setup used if ip=static
-ipaddr=
-netmask=
-gateway=
-serverip=
-
-# MAC address if needed
-#ethaddr=xx:xx:xx:xx:xx:xx
-
-# put code to discover eth1 (i.e. 'usb') to /env/network/eth1-discover
-
-exit 0
diff --git a/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/init/automount b/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/init/automount
deleted file mode 100644
index 6c04eb48a1..0000000000
--- a/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/init/automount
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-# automount tftp server based on $eth0.serverip
-
-mkdir -p /mnt/tftp
-automount /mnt/tftp 'ifup eth1 && mount -t tftp $eth1.serverip /mnt/tftp'
-
-# automount nfs server's nfsroot
-
-mkdir -p /mnt/nfs
-automount /mnt/nfs 'ifup eth1 && mount -t nfs ${eth1.serverip}:/home/${global.user}/nfsroot/${global.hostname} /mnt/nfs'
-
-
-# FAT on usb disk example
-
-#mkdir -p /mnt/fat
-#automount -d /mnt/fat 'usb && [ -e /dev/disk0.0 ] && mount /dev/disk0.0 /mnt/fat'
diff --git a/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth1 b/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth1
deleted file mode 100644
index 33fe7c1b2b..0000000000
--- a/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth1
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-# ip setting (static/dhcp)
-ip=dhcp
-global.dhcp.vendor_id=barebox-${global.hostname}
-
-# static setup used if ip=static
-ipaddr=
-netmask=
-gateway=
-serverip=
-
-# MAC address if needed
-#ethaddr=xx:xx:xx:xx:xx:xx
-
-# put code to discover eth0 (i.e. 'usb') to /env/network/eth0-discover
-
-exit 0
diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c
index 822389c38c..d8b1c9ee1c 100644
--- a/arch/arm/mach-omap/xload.c
+++ b/arch/arm/mach-omap/xload.c
@@ -235,12 +235,20 @@ static void *am33xx_net_boot(void)
IPaddr_t ip;
char *file;
char ip4_str[sizeof("255.255.255.255")];
+ struct eth_device *edev;
am33xx_register_ethaddr(0, 0);
memset(&dhcp_param, 0, sizeof(struct dhcp_req_param));
dhcp_param.vendor_id = "am335x barebox-mlo";
- err = dhcp(20, &dhcp_param);
+
+ edev = eth_get_byname("eth0");
+ if (!edev) {
+ printf("eth0 not found\n");
+ return NULL;
+ }
+
+ err = dhcp(edev, &dhcp_param);
if (err) {
printf("dhcp failed\n");
return NULL;
diff --git a/commands/Kconfig b/commands/Kconfig
index ae2dc4b094..eee4b6aee8 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -1200,6 +1200,16 @@ config CMD_TFTP
Options:
-p push to TFTP server
+config CMD_IP_ROUTE_GET
+ tristate
+ prompt "ip-route-get"
+ default y
+ help
+ The ip-route-get command is used to retrieve the network interface
+ which is used to reach the specified IP address. Information can
+ be shown on the command line or alternatively a variable is set to
+ the result.
+
# end Network commands
endmenu
diff --git a/commands/Makefile b/commands/Makefile
index 37486dceb1..eb4796389e 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -22,7 +22,6 @@ obj-$(CONFIG_CMD_MSLEEP) += msleep.o
obj-$(CONFIG_CMD_RESET) += reset.o
obj-$(CONFIG_CMD_POWEROFF) += poweroff.o
obj-$(CONFIG_CMD_GO) += go.o
-obj-$(CONFIG_NET) += net.o
obj-$(CONFIG_CMD_PARTITION) += partition.o
obj-$(CONFIG_CMD_LS) += ls.o
obj-$(CONFIG_CMD_CD) += cd.o
@@ -123,3 +122,4 @@ obj-$(CONFIG_CMD_SPD_DECODE) += spd_decode.o
obj-$(CONFIG_CMD_MMC_EXTCSD) += mmc_extcsd.o
obj-$(CONFIG_CMD_NAND_BITFLIP) += nand-bitflip.o
obj-$(CONFIG_CMD_SEED) += seed.o
+obj-$(CONFIG_CMD_IP_ROUTE_GET) += ip-route-get.o
diff --git a/commands/detect.c b/commands/detect.c
index 1586a6fb54..48bab4d020 100644
--- a/commands/detect.c
+++ b/commands/detect.c
@@ -26,9 +26,8 @@
static int do_detect(int argc, char *argv[])
{
struct device_d *dev;
- int opt, i, ret;
+ int opt, i, ret, err;
int option_list = 0;
- int option_error = 0;
int option_all = 0;
while ((opt = getopt(argc, argv, "ela")) > 0) {
@@ -37,7 +36,6 @@ static int do_detect(int argc, char *argv[])
option_list = 1;
break;
case 'e':
- option_error = 1;
break;
case 'a':
option_all = 1;
@@ -56,37 +54,34 @@ static int do_detect(int argc, char *argv[])
}
if (option_all) {
- for_each_device(dev) {
- ret = device_detect(dev);
- if (ret && ret != -ENOSYS && option_error)
- return ret;
- }
+ device_detect_all();
return 0;
}
if (argc == optind)
return COMMAND_ERROR_USAGE;
+ err = 0;
+
for (i = optind; i < argc; i++) {
ret = device_detect_by_name(argv[i]);
- if (ret && option_error)
- return ret;
+ if (!err && ret)
+ err = ret;
}
- return 0;
+ return err;
}
BAREBOX_CMD_HELP_START(detect)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-l", "list detectable devices")
-BAREBOX_CMD_HELP_OPT ("-e", "bail out if one device fails to detect")
BAREBOX_CMD_HELP_OPT ("-a", "detect all devices")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(detect)
.cmd = do_detect,
BAREBOX_CMD_DESC("detect devices")
- BAREBOX_CMD_OPTS("[-lea] [devices]")
+ BAREBOX_CMD_OPTS("[-la] [devices]")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_COMPLETE(device_complete)
BAREBOX_CMD_HELP(cmd_detect_help)
diff --git a/commands/dhcp.c b/commands/dhcp.c
index 4f4f5490c5..1f07b2f2ce 100644
--- a/commands/dhcp.c
+++ b/commands/dhcp.c
@@ -15,15 +15,14 @@
#include <environment.h>
#include <getopt.h>
#include <dhcp.h>
+#include <net.h>
static int do_dhcp(int argc, char *argv[])
{
int ret, opt;
- int retries = DHCP_DEFAULT_RETRY;
- struct dhcp_req_param dhcp_param;
-
- memset(&dhcp_param, 0, sizeof(struct dhcp_req_param));
- getenv_uint("global.dhcp.retries", &retries);
+ struct dhcp_req_param dhcp_param = {};
+ struct eth_device *edev;
+ const char *edevname;
while ((opt = getopt(argc, argv, "H:v:c:u:U:r:")) > 0) {
switch (opt) {
@@ -43,19 +42,25 @@ static int do_dhcp(int argc, char *argv[])
dhcp_param.user_class = optarg;
break;
case 'r':
- retries = simple_strtoul(optarg, NULL, 10);
+ dhcp_param.retries = simple_strtoul(optarg, NULL, 10);
break;
default:
return COMMAND_ERROR_USAGE;
}
}
- if (!retries) {
- printf("retries is set to zero, set it to %d\n", DHCP_DEFAULT_RETRY);
- retries = DHCP_DEFAULT_RETRY;
+ if (optind == argc)
+ edevname = "eth0";
+ else
+ edevname = argv[optind];
+
+ edev = eth_get_byname(edevname);
+ if (!edev) {
+ printf("No such network device: %s\n", edevname);
+ return 1;
}
- ret = dhcp(retries, &dhcp_param);
+ ret = dhcp(edev, &dhcp_param);
return ret;
}
@@ -73,8 +78,8 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(dhcp)
.cmd = do_dhcp,
BAREBOX_CMD_DESC("DHCP client to obtain IP or boot params")
- BAREBOX_CMD_OPTS("[-HvcuUr]")
+ BAREBOX_CMD_OPTS("[-HvcuUr] [device]")
BAREBOX_CMD_GROUP(CMD_GRP_NET)
BAREBOX_CMD_HELP(cmd_dhcp_help)
- BAREBOX_CMD_COMPLETE(empty_complete)
+ BAREBOX_CMD_COMPLETE(eth_complete)
BAREBOX_CMD_END
diff --git a/commands/ip-route-get.c b/commands/ip-route-get.c
new file mode 100644
index 0000000000..d393218188
--- /dev/null
+++ b/commands/ip-route-get.c
@@ -0,0 +1,96 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <command.h>
+#include <common.h>
+#include <getopt.h>
+#include <complete.h>
+#include <environment.h>
+#include <net.h>
+
+static int do_ip_route_get(int argc, char *argv[])
+{
+ struct eth_device *edev;
+ IPaddr_t ip, gw = 0;
+ const char *variable = NULL;
+ int opt, ret;
+ bool bootarg = false;
+
+ while ((opt = getopt(argc, argv, "b")) > 0) {
+ switch (opt) {
+ case 'b':
+ bootarg = true;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (argc == optind)
+ return COMMAND_ERROR_USAGE;
+
+ if (argc == optind + 2)
+ variable = argv[optind + 1];
+
+ ret = string_to_ip(argv[optind], &ip);
+ if (ret) {
+ printf("Cannot convert %s into a IP address: %s\n",
+ argv[1], strerror(-ret));
+ return 1;
+ }
+
+ edev = net_route(ip);
+ if (!edev) {
+ gw = net_get_gateway();
+ if (gw)
+ edev = net_route(gw);
+ }
+
+ if (!edev) {
+ printf("IP %pI4 is not reachable\n", &ip);
+ return 1;
+ }
+
+ if (variable) {
+ if (bootarg)
+ setenv(variable, edev->bootarg);
+ else
+ setenv(variable, edev->devname);
+ return 0;
+ }
+
+ if (bootarg) {
+ printf("%s\n", edev->bootarg);
+ } else {
+ if (gw)
+ printf("%pI4 via %pI4 dev %s\n", &ip, &gw,
+ edev->devname);
+ else
+ printf("%pI4 dev %s\n", &ip, edev->devname);
+ }
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(ip_route_get)
+BAREBOX_CMD_HELP_TEXT("get ethernet device used to reach given IP address")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-b", "Instead of ethernet device, show linux bootargs for that device")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(ip_route_get)
+ .cmd = do_ip_route_get,
+ BAREBOX_CMD_DESC("get ethernet device name for an IP address")
+ BAREBOX_CMD_OPTS("[-b] <IP> [variable]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+BAREBOX_CMD_END
diff --git a/commands/net.c b/commands/net.c
deleted file mode 100644
index 219c7efcda..0000000000
--- a/commands/net.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * (C) Copyright 2000
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-/**
- * @file
- * @brief tftp, rarpboot, dhcp, nfs, cdp - Boot support
- */
-
-#include <common.h>
-#include <command.h>
-#include <complete.h>
-#include <environment.h>
-#include <driver.h>
-#include <net.h>
-#include <fs.h>
-#include <errno.h>
-#include <libbb.h>
-
-static int do_ethact(int argc, char *argv[])
-{
- struct eth_device *edev;
-
- if (argc == 1) {
- edev = eth_get_current();
- if (edev)
- printf("%s%d\n", edev->dev.name, edev->dev.id);
- return 0;
- }
-
- if (argc != 2)
- return COMMAND_ERROR_USAGE;
-
- edev = eth_get_byname(argv[1]);
- if (edev)
- eth_set_current(edev);
- else {
- printf("no such net device: %s\n", argv[1]);
- return 1;
- }
-
- return 0;
-}
-
-BAREBOX_CMD_START(ethact)
- .cmd = do_ethact,
- BAREBOX_CMD_DESC("get or set current ethernet device")
- BAREBOX_CMD_OPTS("[ETHX]")
- BAREBOX_CMD_GROUP(CMD_GRP_NET)
- BAREBOX_CMD_COMPLETE(eth_complete)
-BAREBOX_CMD_END
diff --git a/common/globalvar.c b/common/globalvar.c
index 1471d849ec..b9bfce7dac 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -167,8 +167,10 @@ static int nv_set(struct device_d *dev, struct param_d *p, const char *val)
{
int ret;
- if (!val)
- val = "";
+ if (!val) {
+ free(p->value);
+ return 0;
+ }
ret = dev_set_param(&global_device, p->name, val);
if (ret)
diff --git a/defaultenv/defaultenv-2-base/bin/bootargs-ip b/defaultenv/defaultenv-2-base/bin/bootargs-ip
deleted file mode 100644
index 2d4486caf8..0000000000
--- a/defaultenv/defaultenv-2-base/bin/bootargs-ip
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-# pass either static ip or dhcp to kernel based on barebox settings
-
-. /env/network/eth0
-
-if [ $ip = dhcp ]; then
- global.linux.bootargs.dyn.ip="ip=dhcp"
-else
- global.linux.bootargs.dyn.ip="ip=$ipaddr:$serverip:$gateway:$netmask::eth0:"
-fi
diff --git a/defaultenv/defaultenv-2-base/boot/net b/defaultenv/defaultenv-2-base/boot/net
index af096410b7..aaa5394f27 100644
--- a/defaultenv/defaultenv-2-base/boot/net
+++ b/defaultenv/defaultenv-2-base/boot/net
@@ -10,7 +10,8 @@ if [ -f "${oftree}" ]; then
fi
nfsroot="/home/${global.user}/nfsroot/${global.hostname}"
-bootargs-ip
+
+ip_route_get -b ${global.net.server} global.linux.bootargs.dyn.ip
initramfs="${path}/${global.user}-initramfs-${global.hostname}"
if [ -f "${initramfs}" ]; then
diff --git a/defaultenv/defaultenv-2-base/init/automount b/defaultenv/defaultenv-2-base/init/automount
index 959b2c148e..5e0cb4d938 100644
--- a/defaultenv/defaultenv-2-base/init/automount
+++ b/defaultenv/defaultenv-2-base/init/automount
@@ -3,12 +3,12 @@
# automount tftp server based on $eth0.serverip
mkdir -p /mnt/tftp
-automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
+automount /mnt/tftp 'ifup -a && mount -t tftp $global.net.server /mnt/tftp'
# automount nfs server's nfsroot
mkdir -p /mnt/nfs
-automount /mnt/nfs 'ifup eth0 && mount -t nfs ${eth0.serverip}:/home/${global.user}/nfsroot/${global.hostname} /mnt/nfs'
+automount /mnt/nfs 'ifup -a && mount -t nfs ${global.net.server}:/home/${global.user}/nfsroot/${global.hostname} /mnt/nfs'
# FAT on usb disk example
diff --git a/defaultenv/defaultenv-2-base/network/README b/defaultenv/defaultenv-2-base/network/README
new file mode 100644
index 0000000000..4b47807a1a
--- /dev/null
+++ b/defaultenv/defaultenv-2-base/network/README
@@ -0,0 +1,3 @@
+Network configuration is now done with nvvars, see
+Documentation/user/networking.rst. Files in this directory are not needed
+anymore.
diff --git a/defaultenv/defaultenv-2-base/network/eth0 b/defaultenv/defaultenv-2-base/network/eth0
deleted file mode 100644
index 33fe7c1b2b..0000000000
--- a/defaultenv/defaultenv-2-base/network/eth0
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-# ip setting (static/dhcp)
-ip=dhcp
-global.dhcp.vendor_id=barebox-${global.hostname}
-
-# static setup used if ip=static
-ipaddr=
-netmask=
-gateway=
-serverip=
-
-# MAC address if needed
-#ethaddr=xx:xx:xx:xx:xx:xx
-
-# put code to discover eth0 (i.e. 'usb') to /env/network/eth0-discover
-
-exit 0
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 83260990af..c43a4bde2a 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -140,6 +140,14 @@ int device_detect_by_name(const char *__devname)
return ret;
}
+void device_detect_all(void)
+{
+ struct device_d *dev;
+
+ for_each_device(dev)
+ device_detect(dev);
+}
+
static int match(struct driver_d *drv, struct device_d *dev)
{
int ret;
diff --git a/include/dhcp.h b/include/dhcp.h
index 0796b30cf1..0977ff42da 100644
--- a/include/dhcp.h
+++ b/include/dhcp.h
@@ -18,8 +18,30 @@ struct dhcp_req_param {
char *client_id;
char *user_class;
char *client_uuid;
+ int retries;
};
-int dhcp(int retries, struct dhcp_req_param *param);
+struct dhcp_result {
+ IPaddr_t ip;
+ IPaddr_t netmask;
+ IPaddr_t gateway;
+ IPaddr_t nameserver;
+ IPaddr_t serverip;
+ char *hostname;
+ char *domainname;
+ char *rootpath;
+ char *devicetree;
+ char *bootfile;
+ char *tftp_server_name;
+ uint32_t leasetime;
+};
+
+struct eth_device;
+
+int dhcp_request(struct eth_device *edev, const struct dhcp_req_param *param,
+ struct dhcp_result **res);
+int dhcp_set_result(struct eth_device *edev, struct dhcp_result *res);
+void dhcp_result_free(struct dhcp_result *res);
+int dhcp(struct eth_device *edev, const struct dhcp_req_param *param);
#endif
diff --git a/include/driver.h b/include/driver.h
index 8617872053..e571fbbec5 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -134,6 +134,7 @@ int device_probe(struct device_d *dev);
/* detect devices attached to this device (cards, disks,...) */
int device_detect(struct device_d *dev);
int device_detect_by_name(const char *devname);
+void device_detect_all(void);
/* Unregister a device. This function can fail, e.g. when the device
* has children.
diff --git a/include/net.h b/include/net.h
index 632b6d5410..a09cb155a8 100644
--- a/include/net.h
+++ b/include/net.h
@@ -58,11 +58,16 @@ struct eth_device {
struct list_head list;
IPaddr_t ipaddr;
- IPaddr_t serverip;
IPaddr_t netmask;
- IPaddr_t gateway;
char ethaddr[6];
char *bootarg;
+ char *linuxdevname;
+
+ bool ifup;
+#define ETH_MODE_DHCP 0
+#define ETH_MODE_STATIC 1
+#define ETH_MODE_DISABLED 2
+ unsigned int global_mode;
};
#define dev_to_edev(d) container_of(d, struct eth_device, dev)
@@ -114,6 +119,8 @@ struct ethernet {
#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */
#define IPPROTO_UDP 17 /* User Datagram Protocol */
+#define IP_BROADCAST 0xffffffff /* Broadcast IP aka 255.255.255.255 */
+
/*
* Internet Protocol (IP) header.
*/
@@ -214,12 +221,19 @@ struct icmphdr {
extern unsigned char *NetRxPackets[PKTBUFSRX];/* Receive packets */
-void net_set_ip(IPaddr_t ip);
+void net_set_ip(struct eth_device *edev, IPaddr_t ip);
void net_set_serverip(IPaddr_t ip);
-void net_set_netmask(IPaddr_t ip);
+void net_set_serverip_empty(IPaddr_t ip);
+void net_set_netmask(struct eth_device *edev, IPaddr_t ip);
void net_set_gateway(IPaddr_t ip);
-IPaddr_t net_get_ip(void);
+void net_set_nameserver(IPaddr_t ip);
+void net_set_domainname(const char *name);
+IPaddr_t net_get_ip(struct eth_device *edev);
IPaddr_t net_get_serverip(void);
+IPaddr_t net_get_gateway(void);
+IPaddr_t net_get_nameserver(void);
+const char *net_get_domainname(void);
+struct eth_device *net_route(IPaddr_t ip);
/* Do the work */
void net_poll(void);
@@ -406,8 +420,6 @@ static inline int is_valid_ether_addr(const u8 *addr)
typedef void rx_handler_f(void *ctx, char *packet, unsigned int len);
-void eth_set_current(struct eth_device *eth);
-struct eth_device *eth_get_current(void);
struct eth_device *eth_get_byname(const char *name);
/**
@@ -440,6 +452,10 @@ static inline char *net_alloc_packet(void)
struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
rx_handler_f *handler, void *ctx);
+struct net_connection *net_udp_eth_new(struct eth_device *edev, IPaddr_t dest,
+ uint16_t dport, rx_handler_f *handler,
+ void *ctx);
+
struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler,
void *ctx);
@@ -464,6 +480,7 @@ void led_trigger_network(enum led_trigger trigger);
#define IFUP_FLAG_FORCE (1 << 0)
+int ifup_edev(struct eth_device *edev, unsigned flags);
int ifup(const char *name, unsigned flags);
int ifup_all(unsigned flags);
diff --git a/net/dhcp.c b/net/dhcp.c
index c5386fe942..18f347d2f8 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -76,243 +76,30 @@ typedef enum {
static uint32_t Bootp_id;
static dhcp_state_t dhcp_state;
-static uint32_t dhcp_leasetime;
static IPaddr_t net_dhcp_server_ip;
static uint64_t dhcp_start;
-static char dhcp_tftpname[256];
-
-static const char* dhcp_get_barebox_global(const char * var)
-{
- char * var_global = basprintf("global.dhcp.%s", var);
- const char *val;
-
- if (!var_global)
- return NULL;
-
- val = getenv(var_global);
- free(var_global);
- return val;
-}
-
-static int dhcp_set_barebox_global(const char * var, char *val)
-{
- char * var_global = basprintf("global.dhcp.%s", var);
- int ret;
-
- if (!var_global)
- return -ENOMEM;
-
- ret = setenv(var_global, val);
- free(var_global);
- return ret;
-}
-
-struct dhcp_opt {
- unsigned char option;
- /* request automatically the option when creating the DHCP request */
- bool optional;
- bool copy_only_if_valid;
- const char *barebox_var_name;
- const char *barebox_dhcp_global;
- void (*handle)(struct dhcp_opt *opt, unsigned char *data, int tlen);
- int (*handle_param)(struct dhcp_opt *dhcp_opt, u8 *e);
- void *data;
-
- struct bootp *bp;
+static struct eth_device *dhcp_edev;
+struct dhcp_req_param dhcp_param;
+struct dhcp_result *dhcp_result;
+
+struct dhcp_receivce_opts {
+ IPaddr_t netmask;
+ IPaddr_t gateway;
+ IPaddr_t nameserver;
+ IPaddr_t serverip;
+ char *hostname;
+ char *domainname;
+ char *rootpath;
+ char *devicetree;
+ char *bootfile;
};
-static void netmask_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
-{
- IPaddr_t ip;
-
- ip = net_read_ip(popt);
- net_set_netmask(ip);
-}
-
-static void gateway_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
-{
- IPaddr_t ip;
-
- ip = net_read_ip(popt);
- net_set_gateway(ip);
-}
-
-static void env_ip_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
-{
- IPaddr_t ip;
-
- ip = net_read_ip(popt);
- if (IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
- setenv_ip(opt->barebox_var_name, ip);
-}
-
-static void env_str_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
-{
- char str[256];
- char *tmp = str;
-
- if (opt->data)
- tmp = opt->data;
-
- memcpy(tmp, popt, optlen);
- tmp[optlen] = 0;
-
- if (opt->copy_only_if_valid && !strlen(tmp))
- return;
- if (opt->barebox_var_name && IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
- setenv(opt->barebox_var_name, tmp);
- if (opt->barebox_dhcp_global && IS_ENABLED(CONFIG_GLOBALVAR))
- dhcp_set_barebox_global(opt->barebox_dhcp_global, tmp);
-
-}
-
-static void copy_uint32_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
-{
- net_copy_uint32(opt->data, (uint32_t *)popt);
-};
-
-static void copy_ip_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
-{
- net_copy_ip(opt->data, popt);
-};
-
-static void bootfile_vendorex_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
-{
- if (opt->bp->bp_file[0] != '\0')
- return;
-
- /*
- * only use vendor boot file if we didn't
- * receive a boot file in the main non-vendor
- * part of the packet - god only knows why
- * some vendors chose not to use this perfectly
- * good spot to store the boot file (join on
- * Tru64 Unix) it seems mind bogglingly crazy
- * to me
- */
- pr_warn("*** WARNING: using vendor optional boot file\n");
-
- /*
- * I can't use dhcp_vendorex_proc here because I need
- * to write into the bootp packet - even then I had to
- * pass the bootp packet pointer into here as the
- * second arg
- */
- env_str_handle(opt, popt, optlen);
-}
-
-static int dhcp_set_string_options(struct dhcp_opt *param, u8 *e)
-{
- int str_len;
- const char *str = param->data;
-
- if (!str && param->barebox_var_name && IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
- str = getenv(param->barebox_var_name);
-
- if (!str && param->barebox_dhcp_global && IS_ENABLED(CONFIG_GLOBALVAR))
- str = dhcp_get_barebox_global(param->barebox_dhcp_global);
-
- if (!str)
- return 0;
-
- str_len = strlen(str);
- if (!str_len)
- return 0;
-
- *e++ = param->option;
- *e++ = str_len;
- memcpy(e, str, str_len);
-
- return str_len + 2;
-}
-
#define DHCP_HOSTNAME 12
#define DHCP_VENDOR_ID 60
#define DHCP_CLIENT_ID 61
#define DHCP_USER_CLASS 77
#define DHCP_CLIENT_UUID 97
-struct dhcp_opt dhcp_options[] = {
- {
- .option = 1,
- .handle = netmask_handle,
- }, {
- .option = 3,
- .handle = gateway_handle,
- }, {
- .option = 6,
- .handle = env_ip_handle,
- .barebox_var_name = "net.nameserver",
- }, {
- .option = DHCP_HOSTNAME,
- .copy_only_if_valid = 1,
- .handle = env_str_handle,
- .handle_param = dhcp_set_string_options,
- .barebox_var_name = "global.hostname",
- }, {
- .option = 15,
- .handle = env_str_handle,
- .barebox_var_name = "net.domainname",
- }, {
- .option = 17,
- .handle = env_str_handle,
- .barebox_dhcp_global = "rootpath",
- }, {
- .option = 51,
- .handle = copy_uint32_handle,
- .data = &dhcp_leasetime,
- }, {
- .option = 54,
- .handle = copy_ip_handle,
- .data = &net_dhcp_server_ip,
- .optional = true,
- }, {
- .option = DHCP_VENDOR_ID,
- .handle_param = dhcp_set_string_options,
- .barebox_dhcp_global = "vendor_id",
- },{
- .option = 66,
- .handle = env_str_handle,
- .barebox_dhcp_global = "tftp_server_name",
- .data = dhcp_tftpname,
- }, {
- .option = 67,
- .handle = bootfile_vendorex_handle,
- .barebox_dhcp_global = "bootfile",
- }, {
- .option = DHCP_CLIENT_ID,
- .handle_param = dhcp_set_string_options,
- .barebox_dhcp_global = "client_id",
- }, {
- .option = DHCP_USER_CLASS,
- .handle_param = dhcp_set_string_options,
- .barebox_dhcp_global = "user_class",
- }, {
- .option = DHCP_CLIENT_UUID,
- .handle_param = dhcp_set_string_options,
- .barebox_dhcp_global = "client_uuid",
- }, {
- .option = 224,
- .handle = env_str_handle,
- .barebox_dhcp_global = "oftree_file",
- },
-};
-
-static void dhcp_set_param_data(int option, void* data)
-{
- struct dhcp_opt *opt;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) {
- opt = &dhcp_options[i];
-
- if (opt->option == option) {
- opt->data = data;
- return;
- }
- }
-}
-
static int dhcp_set_ip_options(int option, u8 *e, IPaddr_t ip)
{
int tmp;
@@ -366,35 +153,43 @@ static int bootp_check_packet(unsigned char *pkt, unsigned src, unsigned len)
*/
static void bootp_copy_net_params(struct bootp *bp)
{
- IPaddr_t tmp_ip;
- tmp_ip = net_read_ip(&bp->bp_yiaddr);
- net_set_ip(tmp_ip);
+ dhcp_result->ip = net_read_ip(&bp->bp_yiaddr);
+ dhcp_result->serverip = net_read_ip(&bp->bp_siaddr);
- tmp_ip = net_read_ip(&bp->bp_siaddr);
- if (tmp_ip != 0)
- net_set_serverip(tmp_ip);
+ if (strlen(bp->bp_file) > 0)
+ dhcp_result->bootfile = xstrdup(bp->bp_file);
+}
- if (strlen(bp->bp_file) > 0) {
- if (IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
- setenv("bootfile", bp->bp_file);
- if (IS_ENABLED(CONFIG_GLOBALVAR))
- dhcp_set_barebox_global("bootfile", bp->bp_file);
- }
+static int dhcp_set_string_options(int option, const char *str, u8 *e)
+{
+ int str_len;
- debug("bootfile: %s\n", bp->bp_file);
+ if (!str)
+ return 0;
+
+ str_len = strlen(str);
+ if (!str_len)
+ return 0;
+
+ *e++ = option;
+ *e++ = str_len;
+ memcpy(e, str, str_len);
+
+ return str_len + 2;
}
/*
* Initialize BOOTP extension fields in the request.
*/
-static int dhcp_extended (u8 *e, int message_type, IPaddr_t ServerID,
+static int dhcp_extended(u8 *e, int message_type, IPaddr_t ServerID,
IPaddr_t RequestedIP)
{
- struct dhcp_opt *opt;
int i;
u8 *start = e;
u8 *cnt;
+ u8 dhcp_options[] = {1, 3, 6, DHCP_HOSTNAME, 15, 17, 51, DHCP_VENDOR_ID, 66, 67, DHCP_CLIENT_ID,
+ DHCP_USER_CLASS, DHCP_CLIENT_UUID, 224};
*e++ = 99; /* RFC1048 Magic Cookie */
*e++ = 130;
@@ -410,26 +205,23 @@ static int dhcp_extended (u8 *e, int message_type, IPaddr_t ServerID,
*e++ = (576 - 312 + OPT_SIZE) >> 8;
*e++ = (576 - 312 + OPT_SIZE) & 0xff;
-
e += dhcp_set_ip_options(50, e, RequestedIP);
e += dhcp_set_ip_options(54, e, ServerID);
- for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) {
- opt = &dhcp_options[i];
- if (opt->handle_param)
- e += opt->handle_param(opt, e);
- }
+ e += dhcp_set_string_options(DHCP_HOSTNAME, dhcp_param.hostname, e);
+ e += dhcp_set_string_options(DHCP_VENDOR_ID, dhcp_param.vendor_id, e);
+ e += dhcp_set_string_options(DHCP_CLIENT_ID, dhcp_param.client_id, e);
+ e += dhcp_set_string_options(DHCP_USER_CLASS, dhcp_param.user_class, e);
+ e += dhcp_set_string_options(DHCP_CLIENT_UUID, dhcp_param.client_uuid, e);
*e++ = 55; /* Parameter Request List */
- cnt = e++; /* Pointer to count of requested items */
- *cnt = 0;
-
- for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) {
- if (dhcp_options[i].optional)
- continue;
- *e++ = dhcp_options[i].option;
- *cnt += 1;
- }
+ cnt = e++; /* Pointer to count of requested items */
+
+ for (i = 0; i < ARRAY_SIZE(dhcp_options); i++)
+ *e++ = dhcp_options[i];
+
+ *cnt = ARRAY_SIZE(dhcp_options);
+
*e++ = 255; /* End of the list */
/* Pad to minimal length */
@@ -446,14 +238,13 @@ static int bootp_request(void)
struct bootp *bp;
int ext_len;
int ret;
- unsigned char *payload = net_udp_get_payload(dhcp_con);
const char *bfile;
dhcp_state = INIT;
debug("BOOTP broadcast\n");
- bp = (struct bootp *)payload;
+ bp = net_udp_get_payload(dhcp_con);;
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
@@ -467,10 +258,10 @@ static int bootp_request(void)
bfile = getenv("bootfile");
if (bfile)
- safe_strncpy (bp->bp_file, bfile, sizeof(bp->bp_file));
+ safe_strncpy(bp->bp_file, bfile, sizeof(bp->bp_file));
/* Request additional information from the BOOTP/DHCP server */
- ext_len = dhcp_extended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);
+ ext_len = dhcp_extended(bp->bp_vend, DHCP_DISCOVER, 0, 0);
Bootp_id = (uint32_t)get_time_ns();
net_copy_uint32(&bp->bp_id, &Bootp_id);
@@ -482,23 +273,47 @@ static int bootp_request(void)
return ret;
}
-static void dhcp_options_handle(unsigned char option, unsigned char *popt,
+static void dhcp_options_handle(unsigned char option, void *popt,
int optlen, struct bootp *bp)
{
- int i;
- struct dhcp_opt *opt;
-
- for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) {
- opt = &dhcp_options[i];
- if (opt->option == option) {
- opt->bp = bp;
- if (opt->handle)
- opt->handle(opt, popt, optlen);
- return;
- }
+ switch (option) {
+ case 1:
+ dhcp_result->netmask = net_read_ip(popt);
+ break;
+ case 3:
+ dhcp_result->gateway = net_read_ip(popt);
+ break;
+ case 6:
+ dhcp_result->nameserver = net_read_ip(popt);
+ break;
+ case DHCP_HOSTNAME:
+ dhcp_result->hostname = xstrndup(popt, optlen);
+ break;
+ case 15:
+ dhcp_result->domainname = xstrndup(popt, optlen);
+ break;
+ case 17:
+ dhcp_result->rootpath = xstrndup(popt, optlen);
+ break;
+ case 51:
+ net_copy_uint32(&dhcp_result->leasetime, popt);
+ break;
+ case 54:
+ dhcp_result->serverip = net_read_ip(popt);
+ break;
+ case 66:
+ dhcp_result->tftp_server_name = xstrndup(popt, optlen);
+ break;
+ case 67:
+ if (!dhcp_result->bootfile)
+ dhcp_result->bootfile = xstrndup(popt, optlen);
+ break;
+ case 224:
+ dhcp_result->devicetree = xstrndup(popt, optlen);
+ break;
+ default:
+ debug("*** Unhandled DHCP Option in OFFER/ACK: %d\n", option);
}
-
- debug("*** Unhandled DHCP Option in OFFER/ACK: %d\n", option);
}
static void dhcp_options_process(unsigned char *popt, struct bootp *bp)
@@ -523,8 +338,8 @@ static int dhcp_message_type(unsigned char *popt)
return -1;
popt += 4;
- while ( *popt != 0xff ) {
- if ( *popt == 53 ) /* DHCP Message Type */
+ while (*popt != 0xff) {
+ if (*popt == 53) /* DHCP Message Type */
return *(popt + 2);
popt += *(popt + 1) + 2; /* Scan through all options */
}
@@ -536,11 +351,10 @@ static void dhcp_send_request_packet(struct bootp *bp_offer)
struct bootp *bp;
int extlen;
IPaddr_t OfferedIP;
- unsigned char *payload = net_udp_get_payload(dhcp_con);
debug("%s: Sending DHCPREQUEST\n", __func__);
- bp = (struct bootp *)payload;
+ bp = net_udp_get_payload(dhcp_con);
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
@@ -565,7 +379,7 @@ static void dhcp_send_request_packet(struct bootp *bp_offer)
* Copy options from OFFER packet if present
*/
net_copy_ip(&OfferedIP, &bp_offer->bp_yiaddr);
- extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_REQUEST, net_dhcp_server_ip,
+ extlen = dhcp_extended(bp->bp_vend, DHCP_REQUEST, net_dhcp_server_ip,
OfferedIP);
debug("Transmitting DHCPREQUEST packet\n");
@@ -597,10 +411,10 @@ static void dhcp_handler(void *ctx, char *packet, unsigned int len)
* If filename is in format we recognize, assume it is a valid
* OFFER from a server we want.
*/
- debug ("%s: state SELECTING, bp_file: \"%s\"\n", __func__, bp->bp_file);
+ debug("%s: state SELECTING, bp_file: \"%s\"\n", __func__, bp->bp_file);
dhcp_state = REQUESTING;
- if (net_read_uint32((uint32_t *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
+ if (net_read_uint32(&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
dhcp_options_process((u8 *)&bp->bp_vend[4], bp);
bootp_copy_net_params(bp); /* Store net params from reply */
@@ -610,16 +424,14 @@ static void dhcp_handler(void *ctx, char *packet, unsigned int len)
break;
case REQUESTING:
- debug ("%s: State REQUESTING\n", __func__);
+ debug("%s: State REQUESTING\n", __func__);
if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK ) {
- IPaddr_t ip;
- if (net_read_uint32((uint32_t *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
- dhcp_options_process((u8 *)&bp->bp_vend[4], bp);
+ if (net_read_uint32(&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
+ dhcp_options_process(&bp->bp_vend[4], bp);
bootp_copy_net_params(bp); /* Store net params from reply */
dhcp_state = BOUND;
- ip = net_get_ip();
- printf("DHCP client bound to address %pI4\n", &ip);
+ dev_info(&dhcp_edev->dev, "DHCP client bound to address %pI4\n", &dhcp_result->ip);
return;
}
break;
@@ -629,39 +441,50 @@ static void dhcp_handler(void *ctx, char *packet, unsigned int len)
}
}
-static void dhcp_reset_env(void)
-{
- struct dhcp_opt *opt;
- int i;
+static char *global_dhcp_user_class;
+static char *global_dhcp_vendor_id;
+static char *global_dhcp_client_uuid;
+static char *global_dhcp_client_id;
+static char *global_dhcp_bootfile;
+static char *global_dhcp_oftree_file;
+static char *global_dhcp_rootpath;
+static char *global_dhcp_tftp_server_name;
- for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) {
- opt = &dhcp_options[i];
- if (!opt->barebox_var_name || opt->copy_only_if_valid)
- continue;
+static void set_res(char **var, const char *res)
+{
+ free(*var);
- if (IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
- setenv(opt->barebox_var_name, "");
- if (opt->barebox_dhcp_global && IS_ENABLED(CONFIG_GLOBALVAR))
- dhcp_set_barebox_global(opt->barebox_dhcp_global, "");
- }
+ if (res)
+ *var = xstrdup(res);
+ else
+ *var = xstrdup("");
}
-int dhcp(int retries, struct dhcp_req_param *param)
+int dhcp_request(struct eth_device *edev, const struct dhcp_req_param *param,
+ struct dhcp_result **res)
{
int ret = 0;
- dhcp_reset_env();
-
- dhcp_set_param_data(DHCP_HOSTNAME, param->hostname);
- dhcp_set_param_data(DHCP_VENDOR_ID, param->vendor_id);
- dhcp_set_param_data(DHCP_CLIENT_ID, param->client_id);
- dhcp_set_param_data(DHCP_USER_CLASS, param->user_class);
- dhcp_set_param_data(DHCP_CLIENT_UUID, param->client_uuid);
-
- if (!retries)
- retries = DHCP_DEFAULT_RETRY;
-
- dhcp_con = net_udp_new(0xffffffff, PORT_BOOTPS, dhcp_handler, NULL);
+ dhcp_edev = edev;
+ if (param)
+ dhcp_param = *param;
+ else
+ memset(&dhcp_param, 0, sizeof(dhcp_param));
+
+ dhcp_result = xzalloc(sizeof(*dhcp_result));
+
+ if (!dhcp_param.user_class)
+ dhcp_param.user_class = global_dhcp_user_class;
+ if (!dhcp_param.vendor_id)
+ dhcp_param.vendor_id = global_dhcp_vendor_id;
+ if (!dhcp_param.client_uuid)
+ dhcp_param.client_uuid = global_dhcp_client_uuid;
+ if (!dhcp_param.client_id)
+ dhcp_param.client_id = global_dhcp_client_id;
+ if (!dhcp_param.retries)
+ dhcp_param.retries = DHCP_DEFAULT_RETRY;
+
+ dhcp_con = net_udp_eth_new(edev, IP_BROADCAST, PORT_BOOTPS, dhcp_handler, NULL);
if (IS_ERR(dhcp_con)) {
ret = PTR_ERR(dhcp_con);
goto out;
@@ -671,7 +494,7 @@ int dhcp(int retries, struct dhcp_req_param *param)
if (ret)
goto out1;
- net_set_ip(0);
+ net_set_ip(edev, 0);
dhcp_start = get_time_ns();
ret = bootp_request(); /* Basically same as BOOTP */
@@ -683,7 +506,7 @@ int dhcp(int retries, struct dhcp_req_param *param)
ret = -EINTR;
goto out1;
}
- if (!retries) {
+ if (!dhcp_param.retries) {
ret = -ETIMEDOUT;
goto out1;
}
@@ -693,56 +516,122 @@ int dhcp(int retries, struct dhcp_req_param *param)
printf("T ");
ret = bootp_request();
/* no need to check if retries > 0 as we check if != 0 */
- retries--;
+ dhcp_param.retries--;
if (ret)
goto out1;
}
}
- if (dhcp_tftpname[0] != 0) {
- IPaddr_t tftpserver = resolv(dhcp_tftpname);
- if (tftpserver)
- net_set_serverip(tftpserver);
- }
+ pr_debug("DHCP result:\n"
+ " ip: %pI4\n"
+ " netmask: %pI4\n"
+ " gateway: %pI4\n"
+ " serverip: %pI4\n"
+ " nameserver: %pI4\n"
+ " hostname: %s\n"
+ " domainname: %s\n"
+ " rootpath: %s\n"
+ " devicetree: %s\n"
+ " tftp_server_name: %s\n",
+ &dhcp_result->ip,
+ &dhcp_result->netmask,
+ &dhcp_result->gateway,
+ &dhcp_result->serverip,
+ &dhcp_result->nameserver,
+ dhcp_result->hostname ? dhcp_result->hostname : "",
+ dhcp_result->domainname ? dhcp_result->domainname : "",
+ dhcp_result->rootpath ? dhcp_result->rootpath : "",
+ dhcp_result->devicetree ? dhcp_result->devicetree : "",
+ dhcp_result->tftp_server_name ? dhcp_result->tftp_server_name : "");
out1:
net_unregister(dhcp_con);
out:
- if (ret)
+ if (ret) {
debug("dhcp failed: %s\n", strerror(-ret));
+ free(dhcp_result);
+ } else {
+ *res = dhcp_result;
+ }
return ret;
}
-#ifdef CONFIG_GLOBALVAR
-static void dhcp_global_add(const char *var)
+int dhcp_set_result(struct eth_device *edev, struct dhcp_result *res)
{
- char *var_global = basprintf("dhcp.%s", var);
+ net_set_ip(edev, res->ip);
+ net_set_netmask(edev, res->netmask);
+ net_set_gateway(res->gateway);
+ net_set_nameserver(res->nameserver);
+
+ set_res(&global_dhcp_bootfile, res->bootfile);
+ set_res(&global_dhcp_oftree_file, res->devicetree);
+ set_res(&global_dhcp_rootpath, res->rootpath);
+ set_res(&global_dhcp_tftp_server_name, res->tftp_server_name);
+
+ if (res->hostname)
+ barebox_set_hostname(res->hostname);
+ if (res->domainname)
+ net_set_domainname(res->domainname);
+
+ if (res->tftp_server_name) {
+ IPaddr_t ip;
+
+ ip = resolv(res->tftp_server_name);
+ if (ip)
+ net_set_serverip_empty(ip);
+ } else if (res->serverip) {
+ net_set_serverip_empty(res->serverip);
+ }
- if (!var_global)
- return;
+ return 0;
+}
- globalvar_add_simple(var_global, NULL);
- free(var_global);
+void dhcp_result_free(struct dhcp_result *res)
+{
+ free(res->hostname);
+ free(res->domainname);
+ free(res->rootpath);
+ free(res->devicetree);
+ free(res->bootfile);
+ free(res->tftp_server_name);
+
+ free(res);
}
-static int dhcp_global_init(void)
+int dhcp(struct eth_device *edev, const struct dhcp_req_param *param)
{
- struct dhcp_opt *opt;
- int i;
+ struct dhcp_result *res;
+ int ret;
- for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) {
- opt = &dhcp_options[i];
+ ret = dhcp_request(edev, param, &res);
+ if (ret)
+ return ret;
- if (!opt->barebox_dhcp_global)
- continue;
+ ret = dhcp_set_result(edev, res);
- dhcp_global_add(opt->barebox_dhcp_global);
- }
+ dhcp_result_free(res);
+
+ return ret;
+}
+
+#ifdef CONFIG_GLOBALVAR
+
+static int dhcp_global_init(void)
+{
+ globalvar_add_simple_string("dhcp.bootfile", &global_dhcp_bootfile);
+ globalvar_add_simple_string("dhcp.rootpath", &global_dhcp_rootpath);
+ globalvar_add_simple_string("dhcp.vendor_id", &global_dhcp_vendor_id);
+ globalvar_add_simple_string("dhcp.client_uuid", &global_dhcp_client_uuid);
+ globalvar_add_simple_string("dhcp.client_id", &global_dhcp_client_id);
+ globalvar_add_simple_string("dhcp.user_class", &global_dhcp_user_class);
+ globalvar_add_simple_string("dhcp.oftree_file", &global_dhcp_oftree_file);
+ globalvar_add_simple_string("dhcp.tftp_server_name", &global_dhcp_tftp_server_name);
return 0;
}
late_initcall(dhcp_global_init);
+#endif
BAREBOX_MAGICVAR_NAMED(global_dhcp_bootfile, global.dhcp.bootfile, "bootfile returned from DHCP request");
BAREBOX_MAGICVAR_NAMED(global_dhcp_rootpath, global.dhcp.rootpath, "rootpath returned from DHCP request");
@@ -753,4 +642,3 @@ BAREBOX_MAGICVAR_NAMED(global_dhcp_user_class, global.dhcp.user_class, "user cla
BAREBOX_MAGICVAR_NAMED(global_dhcp_tftp_server_name, global.dhcp.tftp_server_name, "TFTP server Name returned from DHCP request");
BAREBOX_MAGICVAR_NAMED(global_dhcp_oftree_file, global.dhcp.oftree_file, "OF tree returned from DHCP request (option 224)");
BAREBOX_MAGICVAR_NAMED(global_dhcp_retries, global.dhcp.retries, "retry limit");
-#endif
diff --git a/net/dns.c b/net/dns.c
index 700c6b0259..a8ce7a4484 100644
--- a/net/dns.c
+++ b/net/dns.c
@@ -77,7 +77,7 @@ static int dns_send(const char *name)
header->nauth = 0;
header->nother = 0;
- domain = getenv("net.domainname");
+ domain = getenv("global.net.domainname");
if (!strchr(name, '.') && domain && *domain)
fullname = basprintf(".%s.%s.", name, domain);
@@ -202,7 +202,6 @@ static void dns_handler(void *ctx, char *packet, unsigned len)
IPaddr_t resolv(const char *host)
{
IPaddr_t ip;
- const char *ns;
if (!string_to_ip(host, &ip))
return ip;
@@ -211,16 +210,13 @@ IPaddr_t resolv(const char *host)
dns_state = STATE_INIT;
- ns = getenv("net.nameserver");
- if (!ns || !*ns) {
+ ip = net_get_nameserver();
+ if (!ip) {
printk("%s: no nameserver specified in $net.nameserver\n",
__func__);
return 0;
}
- if (string_to_ip(ns, &ip))
- return 0;
-
debug("resolving host %s via nameserver %pI4\n", host, &ip);
dns_con = net_udp_new(ip, DNS_PORT, dns_handler, NULL);
diff --git a/net/eth.c b/net/eth.c
index dac2400b81..5d45a04612 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -21,14 +21,19 @@
#include <command.h>
#include <complete.h>
#include <driver.h>
+#include <unistd.h>
#include <init.h>
+#include <dhcp.h>
#include <net.h>
#include <of.h>
#include <linux/phy.h>
#include <errno.h>
#include <malloc.h>
+#include <globalvar.h>
+#include <environment.h>
+#include <linux/ctype.h>
+#include <linux/stat.h>
-static struct eth_device *eth_current;
static uint64_t last_link_check;
LIST_HEAD(netdev_list);
@@ -149,16 +154,6 @@ void of_eth_register_ethaddr(struct device_node *node, const char *ethaddr)
list_add_tail(&addr->list, &ethaddr_list);
}
-void eth_set_current(struct eth_device *eth)
-{
- eth_current = eth;
-}
-
-struct eth_device * eth_get_current(void)
-{
- return eth_current;
-}
-
struct eth_device *eth_get_byname(const char *ethname)
{
struct eth_device *edev;
@@ -348,6 +343,15 @@ static int eth_register_of_fixup(void)
late_initcall(eth_register_of_fixup);
#endif
+extern IPaddr_t net_serverip;
+extern IPaddr_t net_gateway;
+
+static const char * const eth_mode_names[] = {
+ [ETH_MODE_DHCP] = "dhcp",
+ [ETH_MODE_STATIC] = "static",
+ [ETH_MODE_DISABLED] = "disabled",
+};
+
int eth_register(struct eth_device *edev)
{
struct device_d *dev = &edev->dev;
@@ -379,13 +383,18 @@ int eth_register(struct eth_device *edev)
edev->devname = xstrdup(dev_name(&edev->dev));
dev_add_param_ip(dev, "ipaddr", NULL, NULL, &edev->ipaddr, edev);
- dev_add_param_ip(dev, "serverip", NULL, NULL, &edev->serverip, edev);
- dev_add_param_ip(dev, "gateway", NULL, NULL, &edev->gateway, edev);
+ dev_add_param_ip(dev, "serverip", NULL, NULL, &net_serverip, edev);
+ dev_add_param_ip(dev, "gateway", NULL, NULL, &net_gateway, edev);
dev_add_param_ip(dev, "netmask", NULL, NULL, &edev->netmask, edev);
dev_add_param_mac(dev, "ethaddr", eth_param_set_ethaddr, NULL,
edev->ethaddr, edev);
edev->bootarg = xstrdup("");
dev_add_param_string(dev, "linux.bootargs", NULL, NULL, &edev->bootarg, NULL);
+ edev->linuxdevname = xstrdup("");
+ dev_add_param_string(dev, "linux.devname", NULL, NULL, &edev->linuxdevname, NULL);
+ dev_add_param_enum(dev, "mode", NULL, NULL, &edev->global_mode,
+ eth_mode_names, ARRAY_SIZE(eth_mode_names),
+ NULL);
if (edev->init)
edev->init(edev);
@@ -409,17 +418,11 @@ int eth_register(struct eth_device *edev)
edev->parent->device_node)
edev->nodepath = xstrdup(edev->parent->device_node->full_name);
- if (!eth_current)
- eth_current = edev;
-
return 0;
}
void eth_unregister(struct eth_device *edev)
{
- if (edev == eth_current)
- eth_current = NULL;
-
if (edev->active)
edev->halt(edev);
diff --git a/net/ifup.c b/net/ifup.c
index 5113d13832..827c5c03d1 100644
--- a/net/ifup.c
+++ b/net/ifup.c
@@ -22,144 +22,255 @@
#include <command.h>
#include <common.h>
#include <getopt.h>
+#include <dhcp.h>
#include <net.h>
#include <fs.h>
+#include <globalvar.h>
+#include <string.h>
+#include <driver.h>
#include <linux/stat.h>
-static char *vars[] = {
- "ipaddr",
- "netmask",
- "gateway",
- "serverip",
-};
-
-static int eth_set_param(struct device_d *dev, const char *param)
+static int eth_discover(char *file)
{
- const char *value = getenv(param);
+ struct stat s;
+ int ret;
- if (!value)
- return 0;
- if (!*value)
- return 0;
+ ret = stat(file, &s);
+ if (ret) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = run_command(file);
+ if (ret) {
+ pr_err("Running '%s' failed with %d\n", file, ret);
+ goto out;
+ }
+
+out:
+ free(file);
- return dev_set_param(dev, param, value);
+ return ret;
}
-int ifup(const char *name, unsigned flags)
+static int eth_discover_ethname(const char *ethname)
{
- int ret;
- char *cmd, *cmd_discover;
- const char *ip;
+ return eth_discover(basprintf("/env/network/%s-discover", ethname));
+}
+
+static int eth_discover_file(const char *filename)
+{
+ return eth_discover(basprintf("/env/network/%s", filename));
+}
+
+static int source_env_network(struct eth_device *edev)
+{
+ char *vars[] = {
+ "ipaddr",
+ "netmask",
+ "gateway",
+ "serverip",
+ "ethaddr",
+ "ip",
+ "linuxdevname",
+ };
+ IPaddr_t ipaddr, netmask, gateway, serverip;
+ unsigned char ethaddr[6];
+ char *file, *cmd;
+ const char *ethaddrstr, *modestr, *linuxdevname;
+ int ret, mode, ethaddr_valid = 0, i;
struct stat s;
- int i;
- struct device_d *dev;
- struct eth_device *edev = eth_get_byname(name);
- if (edev && edev->ipaddr && !(flags & IFUP_FLAG_FORCE))
+ file = basprintf("/env/network/%s", edev->devname);
+ ret = stat(file, &s);
+ if (ret) {
+ free(file);
return 0;
+ }
- eth_set_current(edev);
+ dev_info(&edev->dev, "/env/network/%s is deprecated.\n"
+ "Use nv.dev.%s.* nvvars to configure your network device instead\n",
+ edev->devname, edev->devname);
env_push_context();
- setenv("ip", "");
-
for (i = 0; i < ARRAY_SIZE(vars); i++)
setenv(vars[i], "");
- cmd = basprintf("source /env/network/%s", name);
- cmd_discover = basprintf("/env/network/%s-discover", name);
-
+ cmd = basprintf("source /env/network/%s", edev->devname);
ret = run_command(cmd);
if (ret) {
pr_err("Running '%s' failed with %d\n", cmd, ret);
goto out;
}
- ret = stat(cmd_discover, &s);
- if (!ret) {
- ret = run_command(cmd_discover);
+ ipaddr = getenv_ip("ipaddr");
+ netmask = getenv_ip("netmask");
+ gateway = getenv_ip("gateway");
+ serverip = getenv_ip("serverip");
+ linuxdevname = getenv("linuxdevname");
+ ethaddrstr = getenv("ethaddr");
+ if (ethaddrstr && *ethaddrstr) {
+ ret = string_to_ethaddr(ethaddrstr, ethaddr);
if (ret) {
- pr_err("Running '%s' failed with %d\n", cmd, ret);
+ dev_err(&edev->dev, "Cannot parse ethaddr \"%s\"\n", ethaddrstr);
+ ret = -EINVAL;
goto out;
}
+ ethaddr_valid = 1;
}
- dev = get_device_by_name(name);
- if (!dev) {
- pr_err("Cannot find device %s\n", name);
+ modestr = getenv("ip");
+ if (!modestr) {
+ dev_err(&edev->dev, "No mode specified in \"ip\" variable\n");
+ ret = -EINVAL;
goto out;
}
- ret = eth_set_param(dev, "ethaddr");
- if (ret)
- goto out;
-
- ip = getenv("ip");
- if (!ip)
- ip = "";
-
- if (!strcmp(ip, "dhcp")) {
- ret = run_command("dhcp");
- if (ret)
- goto out;
- ret = eth_set_param(dev, "serverip");
- if (ret)
- goto out;
- dev_set_param(dev, "linux.bootargs", "ip=dhcp");
- } else if (!strcmp(ip, "static")) {
- char *bootarg;
- for (i = 0; i < ARRAY_SIZE(vars); i++) {
- ret = eth_set_param(dev, vars[i]);
- if (ret)
- goto out;
- }
- bootarg = basprintf("ip=%pI4:%pI4:%pI4:%pI4:::",
- &edev->ipaddr,
- &edev->serverip,
- &edev->gateway,
- &edev->netmask);
- dev_set_param(dev, "linux.bootargs", bootarg);
- free(bootarg);
+ if (!strcmp(modestr, "static")) {
+ mode = ETH_MODE_STATIC;
+ } else if (!strcmp(modestr, "dhcp")) {
+ mode = ETH_MODE_DHCP;
} else {
- pr_err("unknown ip type: %s\n", ip);
+ dev_err(&edev->dev, "Invalid ip mode \"%s\" found\n", modestr);
ret = -EINVAL;
goto out;
}
+ edev->global_mode = mode;
+
+ if (ethaddr_valid)
+ memcpy(edev->ethaddr, ethaddr, 6);
+
+ if (mode == ETH_MODE_STATIC) {
+ edev->ipaddr = ipaddr;
+ edev->netmask = netmask;
+ if (gateway)
+ net_set_gateway(gateway);
+ if (serverip)
+ net_set_serverip(serverip);
+ }
+
+ if (linuxdevname) {
+ free(edev->linuxdevname);
+ edev->linuxdevname = xstrdup(linuxdevname);
+ }
+
ret = 0;
+
out:
env_pop_context();
free(cmd);
- free(cmd_discover);
+ free(file);
return ret;
}
+static void set_linux_bootarg(struct eth_device *edev)
+{
+ if (edev->global_mode == ETH_MODE_STATIC) {
+ char *bootarg;
+ IPaddr_t serverip;
+ IPaddr_t gateway;
+
+ serverip = net_get_serverip();
+ gateway = net_get_gateway();
+
+ bootarg = basprintf("ip=%pI4:%pI4:%pI4:%pI4::%s:",
+ &edev->ipaddr,
+ &serverip,
+ &gateway,
+ &edev->netmask,
+ edev->linuxdevname ? edev->linuxdevname : "");
+ dev_set_param(&edev->dev, "linux.bootargs", bootarg);
+ free(bootarg);
+ } else if (edev->global_mode == ETH_MODE_DHCP) {
+ dev_set_param(&edev->dev, "linux.bootargs", "ip=dhcp");
+ }
+}
+
+int ifup_edev(struct eth_device *edev, unsigned flags)
+{
+ int ret;
+
+ if (edev->global_mode == ETH_MODE_DISABLED) {
+ edev->ipaddr = 0;
+ edev->netmask = 0;
+ edev->ifup = false;
+ return 0;
+ }
+
+ if (edev->ifup) {
+ if (flags & IFUP_FLAG_FORCE)
+ edev->ifup = false;
+ else
+ return 0;
+ }
+
+ ret = source_env_network(edev);
+ if (ret)
+ return ret;
+
+ if (edev->global_mode == ETH_MODE_DHCP) {
+ if (IS_ENABLED(CONFIG_NET_DHCP)) {
+ ret = dhcp(edev, NULL);
+ } else {
+ dev_err(&edev->dev, "DHCP support not available\n");
+ ret = -ENOSYS;
+ }
+ if (ret)
+ return ret;
+ }
+
+ set_linux_bootarg(edev);
+
+ edev->ifup = true;
+
+ return 0;
+}
+
+int ifup(const char *ethname, unsigned flags)
+{
+ struct eth_device *edev;
+ int ret;
+
+ ret = eth_discover_ethname(ethname);
+ if (ret)
+ return ret;
+
+ edev = eth_get_byname(ethname);
+ if (!edev)
+ return -ENODEV;
+
+ return ifup_edev(edev, flags);
+}
+
int ifup_all(unsigned flags)
{
+ struct eth_device *edev;
DIR *dir;
struct dirent *d;
dir = opendir("/env/network");
- if (!dir)
- return -ENOENT;
-
- while ((d = readdir(dir))) {
- if (*d->d_name == '.')
- continue;
- /*
- * Skip xxx-discover files since these are no
- * network configuration files, but scripts to bring
- * up network interface xxx.
- */
- if (strstr(d->d_name, "-discover"))
- continue;
- ifup(d->d_name, flags);
+ if (dir) {
+
+ while ((d = readdir(dir))) {
+ if (*d->d_name == '.')
+ continue;
+ if (!strstr(d->d_name, "-discover"))
+ continue;
+
+ eth_discover_file(d->d_name);
+ }
}
closedir(dir);
+ device_detect_all();
+
+ for_each_netdev(edev)
+ ifup_edev(edev, flags);
+
return 0;
}
@@ -191,11 +302,11 @@ static int do_ifup(int argc, char *argv[])
return ifup(argv[optind], flags);
}
+
+
BAREBOX_CMD_HELP_START(ifup)
-BAREBOX_CMD_HELP_TEXT("Each INTF must have a script /env/network/INTF that set the variables")
-BAREBOX_CMD_HELP_TEXT("ip (to 'static' or 'dynamic'), ipaddr, netmask, gateway, serverip and/or")
-BAREBOX_CMD_HELP_TEXT("ethaddr. A script /env/network/INTF-discover can contains for discovering")
-BAREBOX_CMD_HELP_TEXT("the ethernet device, e.g. 'usb'.")
+BAREBOX_CMD_HELP_TEXT("Network interfaces are configured with a NV variables or a")
+BAREBOX_CMD_HELP_TEXT("/env/network/<intf> file. See Documentation/user/networking.rst")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-a", "bring up all interfaces")
diff --git a/net/net.c b/net/net.c
index 19b081f6cf..94954677c5 100644
--- a/net/net.c
+++ b/net/net.c
@@ -23,6 +23,9 @@
* GNU General Public License for more details.
*
*/
+
+#define pr_fmt(fmt) "net: " fmt
+
#include <common.h>
#include <clock.h>
#include <command.h>
@@ -33,12 +36,43 @@
#include <errno.h>
#include <malloc.h>
#include <init.h>
+#include <globalvar.h>
+#include <magicvar.h>
#include <linux/ctype.h>
#include <linux/err.h>
unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */
static unsigned int net_ip_id;
+IPaddr_t net_serverip;
+IPaddr_t net_gateway;
+static IPaddr_t net_nameserver;
+static char *net_domainname;
+
+void net_set_nameserver(IPaddr_t nameserver)
+{
+ net_nameserver = nameserver;
+}
+
+IPaddr_t net_get_nameserver(void)
+{
+ return net_nameserver;
+}
+
+void net_set_domainname(const char *name)
+{
+ free(net_domainname);
+ if (name)
+ net_domainname = xstrdup(name);
+ else
+ net_domainname = xstrdup("");
+};
+
+const char *net_get_domainname(void)
+{
+ return net_domainname;
+}
+
int net_checksum_ok(unsigned char *ptr, int len)
{
return net_checksum(ptr, len) == 0xffff;
@@ -110,9 +144,29 @@ static void arp_handler(struct arprequest *arp)
}
}
-static int arp_request(IPaddr_t dest, unsigned char *ether)
+struct eth_device *net_route(IPaddr_t dest)
+{
+ struct eth_device *edev;
+
+ for_each_netdev(edev) {
+ if (!edev->ipaddr)
+ continue;
+
+ if ((dest & edev->netmask) == (edev->ipaddr & edev->netmask)) {
+ pr_debug("Route: Using %s (ip=%pI4, nm=%pI4) to reach %pI4\n",
+ dev_name(&edev->dev), &edev->ipaddr, &edev->netmask,
+ &dest);
+ return edev;
+ }
+ }
+
+ pr_debug("Route: No device found for %pI4\n", &dest);
+
+ return NULL;
+}
+
+static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *ether)
{
- struct eth_device *edev = eth_get_current();
char *pkt;
struct arprequest *arp;
uint64_t arp_start;
@@ -121,6 +175,9 @@ static int arp_request(IPaddr_t dest, unsigned char *ether)
unsigned retries = 0;
int ret;
+ if (!edev)
+ return -EHOSTUNREACH;
+
if (!arp_packet) {
arp_packet = net_alloc_packet();
if (!arp_packet)
@@ -132,7 +189,7 @@ static int arp_request(IPaddr_t dest, unsigned char *ether)
arp_wait_ip = dest;
- pr_debug("ARP broadcast\n");
+ pr_debug("send ARP broadcast for %pI4\n", &dest);
memset(et->et_dest, 0xff, 6);
memcpy(et->et_src, edev->ethaddr, 6);
@@ -151,10 +208,10 @@ static int arp_request(IPaddr_t dest, unsigned char *ether)
memset(arp->ar_data + 10, 0, 6); /* dest ET addr = 0 */
if ((dest & edev->netmask) != (edev->ipaddr & edev->netmask)) {
- if (!edev->gateway)
+ if (!net_gateway)
arp_wait_ip = dest;
else
- arp_wait_ip = edev->gateway;
+ arp_wait_ip = net_gateway;
} else {
arp_wait_ip = dest;
}
@@ -187,10 +244,9 @@ static int arp_request(IPaddr_t dest, unsigned char *ether)
net_poll();
}
- pr_debug("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
- ether[0], ether[1],
- ether[2], ether[3],
- ether[4], ether[5]);
+ pr_debug("Got ARP REPLY for %pI4: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ &dest, ether[0], ether[1], ether[2], ether[3], ether[4],
+ ether[5]);
return 0;
}
@@ -213,68 +269,73 @@ static uint16_t net_udp_new_localport(void)
IPaddr_t net_get_serverip(void)
{
- struct eth_device *edev = eth_get_current();
-
- return edev->serverip;
+ return net_serverip;
}
void net_set_serverip(IPaddr_t ip)
{
- struct eth_device *edev = eth_get_current();
-
- edev->serverip = ip;
+ net_serverip = ip;
}
-void net_set_ip(IPaddr_t ip)
+void net_set_serverip_empty(IPaddr_t ip)
{
- struct eth_device *edev = eth_get_current();
+ if (net_serverip)
+ return;
- edev->ipaddr = ip;
+ net_set_serverip(ip);
}
-IPaddr_t net_get_ip(void)
+void net_set_ip(struct eth_device *edev, IPaddr_t ip)
{
- struct eth_device *edev = eth_get_current();
+ edev->ipaddr = ip;
+}
+IPaddr_t net_get_ip(struct eth_device *edev)
+{
return edev->ipaddr;
}
-void net_set_netmask(IPaddr_t nm)
+void net_set_netmask(struct eth_device *edev, IPaddr_t nm)
{
- struct eth_device *edev = eth_get_current();
-
edev->netmask = nm;
}
void net_set_gateway(IPaddr_t gw)
{
- struct eth_device *edev = eth_get_current();
+ net_gateway = gw;
+}
- edev->gateway = gw;
+IPaddr_t net_get_gateway(void)
+{
+ return net_gateway;
}
static LIST_HEAD(connection_list);
-static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler,
- void *ctx)
+static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest,
+ rx_handler_f *handler, void *ctx)
{
- struct eth_device *edev = eth_get_current();
struct net_connection *con;
int ret;
- if (!edev)
- return ERR_PTR(-ENETDOWN);
+ if (!edev) {
+ edev = net_route(dest);
+ if (!edev && net_gateway)
+ edev = net_route(net_gateway);
+ if (!edev)
+ return ERR_PTR(-EHOSTUNREACH);
+ }
if (!is_valid_ether_addr(edev->ethaddr)) {
char str[sizeof("xx:xx:xx:xx:xx:xx")];
random_ether_addr(edev->ethaddr);
ethaddr_to_string(edev->ethaddr, str);
- printf("warning: No MAC address set. Using random address %s\n", str);
+ pr_warn("warning: No MAC address set. Using random address %s\n", str);
eth_set_ethaddr(edev, edev->ethaddr);
}
/* If we don't have an ip only broadcast is allowed */
- if (!edev->ipaddr && dest != 0xffffffff)
+ if (!edev->ipaddr && dest != IP_BROADCAST)
return ERR_PTR(-ENETDOWN);
con = xzalloc(sizeof(*con));
@@ -289,10 +350,10 @@ static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler,
con->icmp = (struct icmphdr *)(con->packet + ETHER_HDR_SIZE + sizeof(struct iphdr));
con->handler = handler;
- if (dest == 0xffffffff) {
+ if (dest == IP_BROADCAST) {
memset(con->et->et_dest, 0xff, 6);
} else {
- ret = arp_request(dest, con->et->et_dest);
+ ret = arp_request(edev, dest, con->et->et_dest);
if (ret)
goto out;
}
@@ -316,10 +377,11 @@ out:
return ERR_PTR(ret);
}
-struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
- rx_handler_f *handler, void *ctx)
+struct net_connection *net_udp_eth_new(struct eth_device *edev, IPaddr_t dest,
+ uint16_t dport, rx_handler_f *handler,
+ void *ctx)
{
- struct net_connection *con = net_new(dest, handler, ctx);
+ struct net_connection *con = net_new(edev, dest, handler, ctx);
if (IS_ERR(con))
return con;
@@ -332,10 +394,16 @@ struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
return con;
}
+struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
+ rx_handler_f *handler, void *ctx)
+{
+ return net_udp_eth_new(NULL, dest, dport, handler, ctx);
+}
+
struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler,
void *ctx)
{
- struct net_connection *con = net_new(dest, handler, ctx);
+ struct net_connection *con = net_new(NULL, dest, handler, ctx);
if (IS_ERR(con))
return con;
@@ -386,7 +454,7 @@ static int net_answer_arp(struct eth_device *edev, unsigned char *pkt, int len)
unsigned char *packet;
int ret;
- debug("%s\n", __func__);
+ pr_debug("%s\n", __func__);
memcpy (et->et_dest, et->et_src, 6);
memcpy (et->et_src, edev->ethaddr, 6);
@@ -423,7 +491,7 @@ static int net_handle_arp(struct eth_device *edev, unsigned char *pkt, int len)
{
struct arprequest *arp;
- debug("%s: got arp\n", __func__);
+ pr_debug("%s: got arp\n", __func__);
/*
* We have to deal with two types of ARP packets:
@@ -490,7 +558,7 @@ static int net_handle_icmp(unsigned char *pkt, int len)
{
struct net_connection *con;
- debug("%s\n", __func__);
+ pr_debug("%s\n", __func__);
list_for_each_entry(con, &connection_list, list) {
if (con->proto == IPPROTO_ICMP) {
@@ -506,11 +574,11 @@ static int net_handle_ip(struct eth_device *edev, unsigned char *pkt, int len)
struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE);
IPaddr_t tmp;
- debug("%s\n", __func__);
+ pr_debug("%s\n", __func__);
if (len < sizeof(struct ethernet) + sizeof(struct iphdr) ||
len < ETHER_HDR_SIZE + ntohs(ip->tot_len)) {
- debug("%s: bad len\n", __func__);
+ pr_debug("%s: bad len\n", __func__);
goto bad;
}
@@ -523,7 +591,7 @@ static int net_handle_ip(struct eth_device *edev, unsigned char *pkt, int len)
goto bad;
tmp = net_read_ip(&ip->daddr);
- if (edev->ipaddr && tmp != edev->ipaddr && tmp != 0xffffffff)
+ if (edev->ipaddr && tmp != edev->ipaddr && tmp != IP_BROADCAST)
return 0;
switch (ip->protocol) {
@@ -560,7 +628,7 @@ int net_receive(struct eth_device *edev, unsigned char *pkt, int len)
ret = net_handle_ip(edev, pkt, len);
break;
default:
- debug("%s: got unknown protocol type: %d\n", __func__, et_protlen);
+ pr_debug("%s: got unknown protocol type: %d\n", __func__, et_protlen);
ret = 1;
break;
}
@@ -568,14 +636,6 @@ out:
return ret;
}
-static struct device_d net_device = {
- .name = "net",
- .id = DEVICE_ID_SINGLE,
-};
-
-static char *net_nameserver;
-static char *net_domainname;
-
static int net_init(void)
{
int i;
@@ -583,15 +643,16 @@ static int net_init(void)
for (i = 0; i < PKTBUFSRX; i++)
NetRxPackets[i] = net_alloc_packet();
- register_device(&net_device);
- net_nameserver = xstrdup("");
- dev_add_param_string(&net_device, "nameserver", NULL, NULL,
- &net_nameserver, NULL);
- net_domainname = xstrdup("");
- dev_add_param_string(&net_device, "domainname", NULL, NULL,
- &net_domainname, NULL);
+ globalvar_add_simple_ip("net.nameserver", &net_nameserver);
+ globalvar_add_simple_string("net.domainname", &net_domainname);
+ globalvar_add_simple_ip("net.server", &net_serverip);
+ globalvar_add_simple_ip("net.gateway", &net_gateway);
return 0;
}
postcore_initcall(net_init);
+
+BAREBOX_MAGICVAR_NAMED(global_net_nameserver, global.net.nameserver, "The DNS server used for resolving host names");
+BAREBOX_MAGICVAR_NAMED(global_net_domainname, global.net.domainname, "Domain name used for DNS requests");
+BAREBOX_MAGICVAR_NAMED(global_net_server, global.net.server, "Standard server used for NFS/TFTP");