diff options
Diffstat (limited to 'net/ifup.c')
-rw-r--r-- | net/ifup.c | 281 |
1 files changed, 196 insertions, 85 deletions
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") |