diff --git a/Documentation/user/automount.rst b/Documentation/user/automount.rst index a5e4313..7de8261 100644 --- a/Documentation/user/automount.rst +++ b/Documentation/user/automount.rst @@ -13,7 +13,7 @@ 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 66f64ec..b5e4320 100644 --- a/Documentation/user/booting-linux.rst +++ b/Documentation/user/booting-linux.rst @@ -232,43 +232,20 @@ 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:::`` for a static IP setup +and ``ip=dhcp`` for a dynamic DHCP setup. ```` is a configurable value. +set ``nv.dev..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 @@ 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 8afb433..5822165 100644 --- a/Documentation/user/networking.rst +++ b/Documentation/user/networking.rst @@ -1,3 +1,5 @@ +.. _networking: + Networking ========== @@ -7,6 +9,49 @@ Network configuration --------------------- +Lowlevel network device configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Network devices are configured with a set of device specific variables: + ++-------------------+--------------+----------------------------------------------------+ +| name | type | | ++===================+==============+====================================================+ +| .mode | enum | "dhcp": DHCP is used to get IP address and netmask | +| | | "static": Static IP setup described by variables | +| | | below | +| | | "disabled": Interface unused | ++-------------------+--------------+----------------------------------------------------+ +| .ipaddr | ipv4 address | The IP address when using static configuration | ++-------------------+--------------+----------------------------------------------------+ +| .netmask | ipv4 address | The netmask when using static configuration | ++-------------------+--------------+----------------------------------------------------+ +| .gateway | ipv4 address | Alias for global.net.gateway. For | +| | | compatibility, do not use. | ++-------------------+--------------+----------------------------------------------------+ +| .serverip| ipv4 address | Alias for global.net.server. For | +| | | compatibility, do not use. | ++-------------------+--------------+----------------------------------------------------+ +| .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: @@ -16,10 +61,9 @@ 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 :ref:`dhcp command ` 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 `. +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..mode + nv.dev..ipaddr + nv.dev..netmask + nv.dev..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 `: + +.. 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 560bdb7..0000000 --- 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 1ed3017..0000000 --- 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 02e1703..01c7a25 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 d3109fc..f52f827 100644 --- a/arch/arm/boards/technexion-pico-hobbit/board.c +++ b/arch/arm/boards/technexion-pico-hobbit/board.c @@ -56,8 +56,6 @@ 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 fdcfa36..0000000 --- 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 dfe6397..0000000 --- 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 6c04eb4..0000000 --- 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 33fe7c1..0000000 --- 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 822389c..d8b1c9e 100644 --- a/arch/arm/mach-omap/xload.c +++ b/arch/arm/mach-omap/xload.c @@ -235,12 +235,20 @@ 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 ae2dc4b..eee4b6a 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -1200,6 +1200,16 @@ 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 37486dc..eb47963 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -22,7 +22,6 @@ 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_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 1586a6f..48bab4d 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 @@ option_list = 1; break; case 'e': - option_error = 1; break; case 'a': option_all = 1; @@ -56,37 +54,34 @@ } 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 4f4f549..1f07b2f 100644 --- a/commands/dhcp.c +++ b/commands/dhcp.c @@ -15,15 +15,14 @@ #include #include #include +#include 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 @@ 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_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 0000000..d393218 --- /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 +#include +#include +#include +#include +#include + +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] [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 219c7ef..0000000 --- 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 -#include -#include -#include -#include -#include -#include -#include -#include - -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 1471d84..b9bfce7 100644 --- a/common/globalvar.c +++ b/common/globalvar.c @@ -167,8 +167,10 @@ { 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 2d4486c..0000000 --- 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 af09641..aaa5394 100644 --- a/defaultenv/defaultenv-2-base/boot/net +++ b/defaultenv/defaultenv-2-base/boot/net @@ -10,7 +10,8 @@ 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 959b2c1..5e0cb4d 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 0000000..4b47807 --- /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 33fe7c1..0000000 --- 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 8326099..c43a4bd 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -140,6 +140,14 @@ 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 0796b30..0977ff4 100644 --- a/include/dhcp.h +++ b/include/dhcp.h @@ -18,8 +18,30 @@ 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 8617872..e571fbb 100644 --- a/include/driver.h +++ b/include/driver.h @@ -134,6 +134,7 @@ /* 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 632b6d5..a09cb15 100644 --- a/include/net.h +++ b/include/net.h @@ -58,11 +58,16 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ #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 c5386fe..18f347d 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -76,243 +76,30 @@ 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 struct eth_device *dhcp_edev; +struct dhcp_req_param dhcp_param; +struct dhcp_result *dhcp_result; -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; +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 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 @@ *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; + cnt = e++; /* Pointer to count of requested items */ - for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) { - if (dhcp_options[i].optional) - continue; - *e++ = dhcp_options[i].option; - *cnt += 1; - } + 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ * 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 @@ 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_reset_env(void) +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; + +static void set_res(char **var, const char *res) { - struct dhcp_opt *opt; - int i; + free(*var); - for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) { - opt = &dhcp_options[i]; - if (!opt->barebox_var_name || opt->copy_only_if_valid) - continue; - - 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_edev = edev; + if (param) + dhcp_param = *param; + else + memset(&dhcp_param, 0, sizeof(dhcp_param)); - 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); + dhcp_result = xzalloc(sizeof(*dhcp_result)); - if (!retries) - retries = DHCP_DEFAULT_RETRY; + 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_new(0xffffffff, PORT_BOOTPS, dhcp_handler, NULL); + 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 @@ 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 @@ ret = -EINTR; goto out1; } - if (!retries) { + if (!dhcp_param.retries) { ret = -ETIMEDOUT; goto out1; } @@ -693,56 +516,122 @@ 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; +} + +int dhcp_set_result(struct eth_device *edev, struct dhcp_result *res) +{ + 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); + } + + return 0; +} + +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); +} + +int dhcp(struct eth_device *edev, const struct dhcp_req_param *param) +{ + struct dhcp_result *res; + int ret; + + ret = dhcp_request(edev, param, &res); + if (ret) + return ret; + + ret = dhcp_set_result(edev, res); + + dhcp_result_free(res); return ret; } #ifdef CONFIG_GLOBALVAR -static void dhcp_global_add(const char *var) -{ - char *var_global = basprintf("dhcp.%s", var); - - if (!var_global) - return; - - globalvar_add_simple(var_global, NULL); - free(var_global); -} static int dhcp_global_init(void) { - struct dhcp_opt *opt; - int i; - - for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) { - opt = &dhcp_options[i]; - - if (!opt->barebox_dhcp_global) - continue; - - dhcp_global_add(opt->barebox_dhcp_global); - } + 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_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 700c6b0..a8ce7a4 100644 --- a/net/dns.c +++ b/net/dns.c @@ -77,7 +77,7 @@ 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 @@ IPaddr_t resolv(const char *host) { IPaddr_t ip; - const char *ns; if (!string_to_ip(host, &ip)) return ip; @@ -211,16 +210,13 @@ 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 dac2400..5d45a04 100644 --- a/net/eth.c +++ b/net/eth.c @@ -21,14 +21,19 @@ #include #include #include +#include #include +#include #include #include #include #include #include +#include +#include +#include +#include -static struct eth_device *eth_current; static uint64_t last_link_check; LIST_HEAD(netdev_list); @@ -149,16 +154,6 @@ list_add_tail(&addr->list, ðaddr_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 @@ 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 @@ 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 @@ 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 5113d13..827c5c0 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -22,144 +22,255 @@ #include #include #include +#include #include #include +#include +#include +#include #include -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; + } - return dev_set_param(dev, param, value); + ret = run_command(file); + if (ret) { + pr_err("Running '%s' failed with %d\n", file, ret); + goto out; + } + +out: + free(file); + + 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); - 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); - } else { - pr_err("unknown ip type: %s\n", ip); + modestr = getenv("ip"); + if (!modestr) { + dev_err(&edev->dev, "No mode specified in \"ip\" variable\n"); ret = -EINVAL; goto out; } + if (!strcmp(modestr, "static")) { + mode = ETH_MODE_STATIC; + } else if (!strcmp(modestr, "dhcp")) { + mode = ETH_MODE_DHCP; + } else { + 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; + if (dir) { - 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); + 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 @@ 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/ 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 19b081f..9495467 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 #include #include @@ -33,12 +36,43 @@ #include #include #include +#include +#include #include #include 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 int arp_request(IPaddr_t dest, unsigned char *ether) +struct eth_device *net_route(IPaddr_t dest) { - struct eth_device *edev = eth_get_current(); + 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) +{ char *pkt; struct arprequest *arp; uint64_t arp_start; @@ -121,6 +175,9 @@ unsigned retries = 0; int ret; + if (!edev) + return -EHOSTUNREACH; + if (!arp_packet) { arp_packet = net_alloc_packet(); if (!arp_packet) @@ -132,7 +189,7 @@ 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 @@ 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 @@ 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 @@ 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; + net_set_serverip(ip); +} + +void net_set_ip(struct eth_device *edev, IPaddr_t ip) +{ edev->ipaddr = ip; } -IPaddr_t net_get_ip(void) +IPaddr_t net_get_ip(struct eth_device *edev) { - struct eth_device *edev = eth_get_current(); - 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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");