From f754335eb9b18a6c79098562246e1a0afe56529f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 28 Nov 2017 10:38:03 +0100 Subject: detect command: Drop -e option The -e option is not that useful. Normally, when a device cannot be detected, then there should be no reason to not try to detect other devices. When a user is interested in a particular detect result, detect can still be called with that (and only that) device. We could also argue that the user should not care about the result of the detect call, but instead check if the desired device is present afterwards. Drop handling of the -e option, but still ignore it for compatibility reasons. Signed-off-by: Sascha Hauer --- commands/detect.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/commands/detect.c b/commands/detect.c index 1586a6fb54..d68d738453 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,36 @@ 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; - } + for_each_device(dev) + device_detect(dev); + 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) -- cgit v1.2.3 From 3edbc17f1ab1a13b6ddd7fcb4dee596ab41ae0b1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 23 Nov 2017 20:37:47 +0100 Subject: driver: Add device_detect_all() function Add a device_detect_all function to detect all devices and use it in the detect command. This makes the functionality reusable in other code. Signed-off-by: Sascha Hauer --- commands/detect.c | 4 +--- drivers/base/driver.c | 8 ++++++++ include/driver.h | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/commands/detect.c b/commands/detect.c index d68d738453..48bab4d020 100644 --- a/commands/detect.c +++ b/commands/detect.c @@ -54,9 +54,7 @@ static int do_detect(int argc, char *argv[]) } if (option_all) { - for_each_device(dev) - device_detect(dev); - + device_detect_all(); return 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/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. -- cgit v1.2.3 From fa4c41ba60af6e8260307fadcd5fb68f8bdb7360 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 23 Nov 2017 21:47:13 +0100 Subject: nvvar: when setting a nvvar to NULL just free the content When a nvvar is about to be removed then it is set to NULL by barebox. This means for the variable to free it's memory. In this case also do not pass the value to the corresponding globalvar, since that would set the globalvar to NULL aswell, but we want to keep its current value. Signed-off-by: Sascha Hauer --- common/globalvar.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/globalvar.c b/common/globalvar.c index fdfaf76fae..5fa74a68cf 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) -- cgit v1.2.3 From 42ee615ff03a0631c5c742c2f739dca4f77ac6d1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 27 Nov 2017 16:16:09 +0100 Subject: net: use pr_* functions for messages Use pr_* functions in the networking code rather than printf() and debug(). Also Add a "net: " prefix to messages to give them some more context. Signed-off-by: Sascha Hauer --- net/net.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/net/net.c b/net/net.c index 19b081f6cf..12e63c664e 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 @@ -132,7 +135,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); @@ -187,10 +190,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; } @@ -269,7 +271,7 @@ static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler, 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); } @@ -386,7 +388,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 +425,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 +492,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 +508,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; } @@ -560,7 +562,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; } -- cgit v1.2.3 From ba61b249609d28a2a3e750b3602d1ba2a8d8b140 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 28 Nov 2017 08:48:12 +0100 Subject: net: Add and use IP_BROADCAST Rather than using the hardcoded value 0xffffffff in several places add a define for the broadcast IP. Signed-off-by: Sascha Hauer --- include/net.h | 2 ++ net/dhcp.c | 2 +- net/net.c | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/net.h b/include/net.h index 632b6d5410..4649947916 100644 --- a/include/net.h +++ b/include/net.h @@ -114,6 +114,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. */ diff --git a/net/dhcp.c b/net/dhcp.c index c5386fe942..4d74733d37 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -661,7 +661,7 @@ int dhcp(int retries, struct dhcp_req_param *param) if (!retries) retries = DHCP_DEFAULT_RETRY; - dhcp_con = net_udp_new(0xffffffff, PORT_BOOTPS, dhcp_handler, NULL); + dhcp_con = net_udp_new(IP_BROADCAST, PORT_BOOTPS, dhcp_handler, NULL); if (IS_ERR(dhcp_con)) { ret = PTR_ERR(dhcp_con); goto out; diff --git a/net/net.c b/net/net.c index 12e63c664e..205543a425 100644 --- a/net/net.c +++ b/net/net.c @@ -276,7 +276,7 @@ static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler, } /* 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)); @@ -291,7 +291,7 @@ 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); @@ -525,7 +525,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) { -- cgit v1.2.3 From d5d342d26368c1f6b1ba597eea5b471bf4b9c344 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 11 Dec 2015 15:46:26 +0100 Subject: net: Make domainname and nameserver globalvars Register domainname and nameserver as globalvars rather than attaching them to a dedicated net device. the global device already exists and already contains much of the barebox configuration, so no need to add an extra device for network config. Signed-off-by: Sascha Hauer --- net/dhcp.c | 4 ++-- net/dns.c | 4 ++-- net/net.c | 25 ++++++++++--------------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/net/dhcp.c b/net/dhcp.c index 4d74733d37..68696d69e8 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -242,7 +242,7 @@ struct dhcp_opt dhcp_options[] = { }, { .option = 6, .handle = env_ip_handle, - .barebox_var_name = "net.nameserver", + .barebox_var_name = "global.net.nameserver", }, { .option = DHCP_HOSTNAME, .copy_only_if_valid = 1, @@ -252,7 +252,7 @@ struct dhcp_opt dhcp_options[] = { }, { .option = 15, .handle = env_str_handle, - .barebox_var_name = "net.domainname", + .barebox_var_name = "global.net.domainname", }, { .option = 17, .handle = env_str_handle, diff --git a/net/dns.c b/net/dns.c index 700c6b0259..69b8a24861 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); @@ -211,7 +211,7 @@ IPaddr_t resolv(const char *host) dns_state = STATE_INIT; - ns = getenv("net.nameserver"); + ns = getenv("global.net.nameserver"); if (!ns || !*ns) { printk("%s: no nameserver specified in $net.nameserver\n", __func__); diff --git a/net/net.c b/net/net.c index 205543a425..30977321ff 100644 --- a/net/net.c +++ b/net/net.c @@ -36,12 +36,17 @@ #include #include #include +#include +#include #include #include unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */ static unsigned int net_ip_id; +static IPaddr_t net_nameserver; +static char *net_domainname; + int net_checksum_ok(unsigned char *ptr, int len) { return net_checksum(ptr, len) == 0xffff; @@ -570,14 +575,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; @@ -585,15 +582,13 @@ 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); 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"); -- cgit v1.2.3 From d8bc8a33d9a4d39c2ac84cc7d119054bf12e16d3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 20 Nov 2017 19:39:36 +0100 Subject: net: Add functions to get/set nameserver and domainname It's more convenient to have getter/setter functions for variables rather than using the detour around global vars which use string matching and all kinds of overhead in the background. Signed-off-by: Sascha Hauer --- include/net.h | 4 ++++ net/dns.c | 8 ++------ net/net.c | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/include/net.h b/include/net.h index 4649947916..817e29cd9b 100644 --- a/include/net.h +++ b/include/net.h @@ -220,8 +220,12 @@ void net_set_ip(IPaddr_t ip); void net_set_serverip(IPaddr_t ip); void net_set_netmask(IPaddr_t ip); void net_set_gateway(IPaddr_t ip); +void net_set_nameserver(IPaddr_t ip); +void net_set_domainname(const char *name); IPaddr_t net_get_ip(void); IPaddr_t net_get_serverip(void); +IPaddr_t net_get_nameserver(void); +const char *net_get_domainname(void); /* Do the work */ void net_poll(void); diff --git a/net/dns.c b/net/dns.c index 69b8a24861..a8ce7a4484 100644 --- a/net/dns.c +++ b/net/dns.c @@ -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("global.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/net.c b/net/net.c index 30977321ff..1ebf0008cb 100644 --- a/net/net.c +++ b/net/net.c @@ -47,6 +47,30 @@ static unsigned int net_ip_id; 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; -- cgit v1.2.3 From 8b72bac28459ab818b2a308690e61d683e511bba Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 11 Dec 2015 21:17:23 +0100 Subject: net: introduce global.net.server The server to use is independent of the network device, there is not much point to make the server specific to a network device. This introduces global.net.server as the serverip which is used as standard NFS/tftp server. The previously used eth device specific parameters still exist, but are only aliases for the global single variable. Signed-off-by: Sascha Hauer --- include/net.h | 1 - net/eth.c | 4 +++- net/ifup.c | 7 ++++++- net/net.c | 11 +++++------ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/net.h b/include/net.h index 817e29cd9b..37ddf2db18 100644 --- a/include/net.h +++ b/include/net.h @@ -58,7 +58,6 @@ struct eth_device { struct list_head list; IPaddr_t ipaddr; - IPaddr_t serverip; IPaddr_t netmask; IPaddr_t gateway; char ethaddr[6]; diff --git a/net/eth.c b/net/eth.c index dac2400b81..74666bbf22 100644 --- a/net/eth.c +++ b/net/eth.c @@ -348,6 +348,8 @@ static int eth_register_of_fixup(void) late_initcall(eth_register_of_fixup); #endif +extern IPaddr_t net_serverip; + int eth_register(struct eth_device *edev) { struct device_d *dev = &edev->dev; @@ -379,7 +381,7 @@ 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, "serverip", NULL, NULL, &net_serverip, edev); dev_add_param_ip(dev, "gateway", NULL, NULL, &edev->gateway, edev); dev_add_param_ip(dev, "netmask", NULL, NULL, &edev->netmask, edev); dev_add_param_mac(dev, "ethaddr", eth_param_set_ethaddr, NULL, diff --git a/net/ifup.c b/net/ifup.c index 5113d13832..2b13a9f140 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -109,14 +109,19 @@ int ifup(const char *name, unsigned flags) dev_set_param(dev, "linux.bootargs", "ip=dhcp"); } else if (!strcmp(ip, "static")) { char *bootarg; + IPaddr_t serverip; + for (i = 0; i < ARRAY_SIZE(vars); i++) { ret = eth_set_param(dev, vars[i]); if (ret) goto out; } + + serverip = net_get_serverip(); + bootarg = basprintf("ip=%pI4:%pI4:%pI4:%pI4:::", &edev->ipaddr, - &edev->serverip, + &serverip, &edev->gateway, &edev->netmask); dev_set_param(dev, "linux.bootargs", bootarg); diff --git a/net/net.c b/net/net.c index 1ebf0008cb..5e6e8f1940 100644 --- a/net/net.c +++ b/net/net.c @@ -44,6 +44,7 @@ unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */ static unsigned int net_ip_id; +IPaddr_t net_serverip; static IPaddr_t net_nameserver; static char *net_domainname; @@ -244,16 +245,12 @@ 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) @@ -608,6 +605,7 @@ static int net_init(void) globalvar_add_simple_ip("net.nameserver", &net_nameserver); globalvar_add_simple_string("net.domainname", &net_domainname); + globalvar_add_simple_ip("net.server", &net_serverip); return 0; } @@ -616,3 +614,4 @@ 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"); -- cgit v1.2.3 From 48a58879d18a21007cb7d6863c1bd569a54a5c03 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 21 Nov 2017 19:28:37 +0100 Subject: net: dhcp: Do not overwrite serverip if it is valid Some DHCP servers provide the wrong serverip in which case it is desired to specify it manually and won't let the dhcp command overwrite it. This has previously been done by setting the serverip again to the desired value after dhcp has been executed. With this patch we do not overwrite it in the first place if it is valid already. This is necessary when the serverip is not set via /env/network/eth* but via nv.net.server. Signed-off-by: Sascha Hauer --- include/net.h | 1 + net/dhcp.c | 4 ++-- net/ifup.c | 9 ++++++--- net/net.c | 8 ++++++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/include/net.h b/include/net.h index 37ddf2db18..06390732fb 100644 --- a/include/net.h +++ b/include/net.h @@ -217,6 +217,7 @@ extern unsigned char *NetRxPackets[PKTBUFSRX];/* Receive packets */ void net_set_ip(IPaddr_t ip); void net_set_serverip(IPaddr_t ip); +void net_set_serverip_empty(IPaddr_t ip); void net_set_netmask(IPaddr_t ip); void net_set_gateway(IPaddr_t ip); void net_set_nameserver(IPaddr_t ip); diff --git a/net/dhcp.c b/net/dhcp.c index 68696d69e8..37aad8f1ff 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -373,7 +373,7 @@ static void bootp_copy_net_params(struct bootp *bp) tmp_ip = net_read_ip(&bp->bp_siaddr); if (tmp_ip != 0) - net_set_serverip(tmp_ip); + net_set_serverip_empty(tmp_ip); if (strlen(bp->bp_file) > 0) { if (IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES)) @@ -702,7 +702,7 @@ int dhcp(int retries, struct dhcp_req_param *param) if (dhcp_tftpname[0] != 0) { IPaddr_t tftpserver = resolv(dhcp_tftpname); if (tftpserver) - net_set_serverip(tftpserver); + net_set_serverip_empty(tftpserver); } out1: diff --git a/net/ifup.c b/net/ifup.c index 2b13a9f140..2d1feeb74a 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -100,10 +100,13 @@ int ifup(const char *name, unsigned flags) ip = ""; if (!strcmp(ip, "dhcp")) { + IPaddr_t serverip; + + serverip = getenv_ip("serverip"); + if (serverip) + net_set_serverip_empty(serverip); + 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"); diff --git a/net/net.c b/net/net.c index 5e6e8f1940..10ddd61879 100644 --- a/net/net.c +++ b/net/net.c @@ -253,6 +253,14 @@ void net_set_serverip(IPaddr_t ip) net_serverip = ip; } +void net_set_serverip_empty(IPaddr_t ip) +{ + if (net_serverip) + return; + + net_set_serverip(ip); +} + void net_set_ip(IPaddr_t ip) { struct eth_device *edev = eth_get_current(); -- cgit v1.2.3 From 46f7781d361b2b4768c0a56c4fd6a9b11fe4157c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 17 Nov 2017 21:47:40 +0100 Subject: net: Use a single gateway There is not much point in having a network device specific gateway. If barebox really is part of such a complicated network in which it needs multiple gateways, then we probably need a real routing table. Until this happens, a single gateway should be enough. This introduces global.net.gateway which holds the gateway ip. The previously used device specific .gateway variables still exist, but are only aliases for the single gateway. Signed-off-by: Sascha Hauer --- include/net.h | 2 +- net/eth.c | 3 ++- net/ifup.c | 4 +++- net/net.c | 13 +++++++++---- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/net.h b/include/net.h index 06390732fb..95fa828e84 100644 --- a/include/net.h +++ b/include/net.h @@ -59,7 +59,6 @@ struct eth_device { IPaddr_t ipaddr; IPaddr_t netmask; - IPaddr_t gateway; char ethaddr[6]; char *bootarg; }; @@ -224,6 +223,7 @@ void net_set_nameserver(IPaddr_t ip); void net_set_domainname(const char *name); IPaddr_t net_get_ip(void); IPaddr_t net_get_serverip(void); +IPaddr_t net_get_gateway(void); IPaddr_t net_get_nameserver(void); const char *net_get_domainname(void); diff --git a/net/eth.c b/net/eth.c index 74666bbf22..6dae6b9feb 100644 --- a/net/eth.c +++ b/net/eth.c @@ -349,6 +349,7 @@ late_initcall(eth_register_of_fixup); #endif extern IPaddr_t net_serverip; +extern IPaddr_t net_gateway; int eth_register(struct eth_device *edev) { @@ -382,7 +383,7 @@ int eth_register(struct eth_device *edev) dev_add_param_ip(dev, "ipaddr", NULL, NULL, &edev->ipaddr, edev); dev_add_param_ip(dev, "serverip", NULL, NULL, &net_serverip, edev); - dev_add_param_ip(dev, "gateway", NULL, NULL, &edev->gateway, 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); diff --git a/net/ifup.c b/net/ifup.c index 2d1feeb74a..c3ea1b6a45 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -113,6 +113,7 @@ int ifup(const char *name, unsigned flags) } else if (!strcmp(ip, "static")) { char *bootarg; IPaddr_t serverip; + IPaddr_t gateway; for (i = 0; i < ARRAY_SIZE(vars); i++) { ret = eth_set_param(dev, vars[i]); @@ -121,11 +122,12 @@ int ifup(const char *name, unsigned flags) } serverip = net_get_serverip(); + gateway = net_get_gateway(); bootarg = basprintf("ip=%pI4:%pI4:%pI4:%pI4:::", &edev->ipaddr, &serverip, - &edev->gateway, + &gateway, &edev->netmask); dev_set_param(dev, "linux.bootargs", bootarg); free(bootarg); diff --git a/net/net.c b/net/net.c index 10ddd61879..f63d25531e 100644 --- a/net/net.c +++ b/net/net.c @@ -45,6 +45,7 @@ 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; @@ -184,10 +185,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; } @@ -284,9 +285,12 @@ void net_set_netmask(IPaddr_t 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); @@ -614,6 +618,7 @@ static int net_init(void) 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; } -- cgit v1.2.3 From 946bc95a4de8247ea884a3932470344e59618c3a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 20 Nov 2017 22:36:37 +0100 Subject: net: allow udp connections on specified network device This allows the DHCP code to configure specific network devices so that DHCP no longer depends on any "current" network device. Signed-off-by: Sascha Hauer --- include/net.h | 4 ++++ net/net.c | 32 ++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/net.h b/include/net.h index 95fa828e84..8e3b0aff5a 100644 --- a/include/net.h +++ b/include/net.h @@ -446,6 +446,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); diff --git a/net/net.c b/net/net.c index f63d25531e..6cdffa4b8d 100644 --- a/net/net.c +++ b/net/net.c @@ -144,9 +144,8 @@ static void arp_handler(struct arprequest *arp) } } -static int arp_request(IPaddr_t dest, unsigned char *ether) +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; @@ -295,15 +294,17 @@ IPaddr_t net_get_gateway(void) 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 = eth_get_current(); + if (!edev) + return ERR_PTR(-ENETDOWN); + } if (!is_valid_ether_addr(edev->ethaddr)) { char str[sizeof("xx:xx:xx:xx:xx:xx")]; @@ -332,7 +333,7 @@ static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler, 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; } @@ -356,10 +357,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; @@ -372,10 +374,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; -- cgit v1.2.3 From ab84733e570b889324f2594685f7f5d33b3c39be Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 20 Nov 2017 22:46:47 +0100 Subject: net: dhcp: Allow to specify network device Instead of allowing to DHCP only on the "current" network device, allow to specify the desired network device. This is a first step to get rid of the concept of a "current" network device. Signed-off-by: Sascha Hauer --- arch/arm/mach-omap/xload.c | 10 +++++++++- commands/dhcp.c | 20 +++++++++++++++++--- include/dhcp.h | 4 +++- include/net.h | 6 +++--- net/dhcp.c | 15 +++++++++------ net/ifup.c | 5 ++++- net/net.c | 12 +++--------- 7 files changed, 48 insertions(+), 24 deletions(-) diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c index 822389c38c..e83784ba4d 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, 20, &dhcp_param); if (err) { printf("dhcp failed\n"); return NULL; diff --git a/commands/dhcp.c b/commands/dhcp.c index 4f4f5490c5..ce4a78830d 100644 --- a/commands/dhcp.c +++ b/commands/dhcp.c @@ -15,12 +15,15 @@ #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; + struct eth_device *edev; + const char *edevname; memset(&dhcp_param, 0, sizeof(struct dhcp_req_param)); getenv_uint("global.dhcp.retries", &retries); @@ -50,12 +53,23 @@ static int do_dhcp(int argc, char *argv[]) } } + 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; + } + if (!retries) { printf("retries is set to zero, set it to %d\n", DHCP_DEFAULT_RETRY); retries = DHCP_DEFAULT_RETRY; } - ret = dhcp(retries, &dhcp_param); + ret = dhcp(edev, retries, &dhcp_param); return ret; } @@ -73,8 +87,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/include/dhcp.h b/include/dhcp.h index 0796b30cf1..20a523250f 100644 --- a/include/dhcp.h +++ b/include/dhcp.h @@ -20,6 +20,8 @@ struct dhcp_req_param { char *client_uuid; }; -int dhcp(int retries, struct dhcp_req_param *param); +struct eth_device; + +int dhcp(struct eth_device *edev, int retries, struct dhcp_req_param *param); #endif diff --git a/include/net.h b/include/net.h index 8e3b0aff5a..b7555c0de6 100644 --- a/include/net.h +++ b/include/net.h @@ -214,14 +214,14 @@ 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_serverip_empty(IPaddr_t ip); -void net_set_netmask(IPaddr_t ip); +void net_set_netmask(struct eth_device *edev, IPaddr_t ip); void net_set_gateway(IPaddr_t ip); void net_set_nameserver(IPaddr_t ip); void net_set_domainname(const char *name); -IPaddr_t net_get_ip(void); +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); diff --git a/net/dhcp.c b/net/dhcp.c index 37aad8f1ff..82f60f0535 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -79,6 +79,7 @@ static dhcp_state_t dhcp_state; static uint32_t dhcp_leasetime; static IPaddr_t net_dhcp_server_ip; static uint64_t dhcp_start; +static struct eth_device *dhcp_edev; static char dhcp_tftpname[256]; static const char* dhcp_get_barebox_global(const char * var) @@ -126,7 +127,7 @@ 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); + net_set_netmask(dhcp_edev, ip); } static void gateway_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen) @@ -369,7 +370,7 @@ 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); + net_set_ip(dhcp_edev, tmp_ip); tmp_ip = net_read_ip(&bp->bp_siaddr); if (tmp_ip != 0) @@ -618,7 +619,7 @@ static void dhcp_handler(void *ctx, char *packet, unsigned int len) dhcp_options_process((u8 *)&bp->bp_vend[4], bp); bootp_copy_net_params(bp); /* Store net params from reply */ dhcp_state = BOUND; - ip = net_get_ip(); + ip = net_get_ip(dhcp_edev); printf("DHCP client bound to address %pI4\n", &ip); return; } @@ -646,12 +647,14 @@ static void dhcp_reset_env(void) } } -int dhcp(int retries, struct dhcp_req_param *param) +int dhcp(struct eth_device *edev, int retries, struct dhcp_req_param *param) { int ret = 0; dhcp_reset_env(); + dhcp_edev = edev; + 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); @@ -661,7 +664,7 @@ int dhcp(int retries, struct dhcp_req_param *param) if (!retries) retries = DHCP_DEFAULT_RETRY; - dhcp_con = net_udp_new(IP_BROADCAST, 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 +674,7 @@ int dhcp(int retries, struct dhcp_req_param *param) if (ret) goto out1; - net_set_ip(0); + net_set_ip(dhcp_edev, 0); dhcp_start = get_time_ns(); ret = bootp_request(); /* Basically same as BOOTP */ diff --git a/net/ifup.c b/net/ifup.c index c3ea1b6a45..2160e3ae46 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -101,12 +101,15 @@ int ifup(const char *name, unsigned flags) if (!strcmp(ip, "dhcp")) { IPaddr_t serverip; + char *dhcp_cmd; serverip = getenv_ip("serverip"); if (serverip) net_set_serverip_empty(serverip); - ret = run_command("dhcp"); + dhcp_cmd = basprintf("dhcp %s", name); + ret = run_command(dhcp_cmd); + free(dhcp_cmd); if (ret) goto out; dev_set_param(dev, "linux.bootargs", "ip=dhcp"); diff --git a/net/net.c b/net/net.c index 6cdffa4b8d..33d6e2c5b0 100644 --- a/net/net.c +++ b/net/net.c @@ -261,24 +261,18 @@ void net_set_serverip_empty(IPaddr_t ip) net_set_serverip(ip); } -void net_set_ip(IPaddr_t ip) +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(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; } -- cgit v1.2.3 From 170060110e58238d49f5e59da7b23a77ac2e48e1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 20 Nov 2017 22:56:24 +0100 Subject: net: dhcp: avoid unnecessary casts Drop explicit casts to/from void pointers. Signed-off-by: Sascha Hauer --- net/dhcp.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/net/dhcp.c b/net/dhcp.c index 82f60f0535..ffb3842882 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -447,14 +447,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; @@ -471,7 +470,7 @@ static int bootp_request(void) 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); @@ -483,7 +482,7 @@ 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; @@ -537,11 +536,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; @@ -566,7 +564,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"); @@ -601,7 +599,7 @@ static void dhcp_handler(void *ctx, char *packet, unsigned int len) 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 */ @@ -615,8 +613,8 @@ static void dhcp_handler(void *ctx, char *packet, unsigned int len) 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(dhcp_edev); -- cgit v1.2.3 From 6b4a38d00255149c63277100ed1a3f5f95ab2e75 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 20 Nov 2017 23:05:06 +0100 Subject: net: dhcp: Coding style fixes Fix some spaces-before-function-opening-brackets and duplicate empty lines. Signed-off-by: Sascha Hauer --- net/dhcp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/dhcp.c b/net/dhcp.c index ffb3842882..08eb407d22 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -389,7 +389,7 @@ static void bootp_copy_net_params(struct bootp *bp) /* * 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; @@ -411,7 +411,6 @@ 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); @@ -467,7 +466,7 @@ 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(bp->bp_vend, DHCP_DISCOVER, 0, 0); @@ -523,8 +522,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 */ } @@ -596,7 +595,7 @@ 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(&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC)) @@ -609,7 +608,7 @@ 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; -- cgit v1.2.3 From 528298b702a0ad238dd01b3497f7c0bb671bf7c9 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 20 Nov 2017 23:06:13 +0100 Subject: net: dhcp: rework The DHCP code is a mess. It is not clear which options are sent to the server and which options are returned from the server. Also environment variables are read from and written to all over the place. This patch cleans this up. There now is struct dhcp_req_param which is used for options sent to the server and struct dhcp_result which contains the values sent from the server. The values from the server are written to the barebox variables in a single place. Also it's now possible to call the dhcp code without modifying barebox variables at all, storing the result only in the dhcp result struct. Signed-off-by: Sascha Hauer --- arch/arm/mach-omap/xload.c | 2 +- commands/dhcp.c | 15 +- include/dhcp.h | 22 +- net/dhcp.c | 532 ++++++++++++++++++--------------------------- 4 files changed, 235 insertions(+), 336 deletions(-) diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c index e83784ba4d..d8b1c9ee1c 100644 --- a/arch/arm/mach-omap/xload.c +++ b/arch/arm/mach-omap/xload.c @@ -248,7 +248,7 @@ static void *am33xx_net_boot(void) return NULL; } - err = dhcp(edev, 20, &dhcp_param); + err = dhcp(edev, &dhcp_param); if (err) { printf("dhcp failed\n"); return NULL; diff --git a/commands/dhcp.c b/commands/dhcp.c index ce4a78830d..1f07b2f2ce 100644 --- a/commands/dhcp.c +++ b/commands/dhcp.c @@ -20,14 +20,10 @@ static int do_dhcp(int argc, char *argv[]) { int ret, opt; - int retries = DHCP_DEFAULT_RETRY; - struct dhcp_req_param dhcp_param; + struct dhcp_req_param dhcp_param = {}; struct eth_device *edev; const char *edevname; - memset(&dhcp_param, 0, sizeof(struct dhcp_req_param)); - getenv_uint("global.dhcp.retries", &retries); - while ((opt = getopt(argc, argv, "H:v:c:u:U:r:")) > 0) { switch (opt) { case 'H': @@ -46,7 +42,7 @@ 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; @@ -64,12 +60,7 @@ static int do_dhcp(int argc, char *argv[]) return 1; } - if (!retries) { - printf("retries is set to zero, set it to %d\n", DHCP_DEFAULT_RETRY); - retries = DHCP_DEFAULT_RETRY; - } - - ret = dhcp(edev, retries, &dhcp_param); + ret = dhcp(edev, &dhcp_param); return ret; } diff --git a/include/dhcp.h b/include/dhcp.h index 20a523250f..0977ff42da 100644 --- a/include/dhcp.h +++ b/include/dhcp.h @@ -18,10 +18,30 @@ struct dhcp_req_param { char *client_id; char *user_class; char *client_uuid; + int retries; +}; + +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(struct eth_device *edev, 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 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/net/dhcp.c b/net/dhcp.c index 08eb407d22..18f347d2f8 100644 --- a/net/dhcp.c +++ b/net/dhcp.c @@ -76,244 +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 struct eth_device *dhcp_edev; -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; +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(dhcp_edev, 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 = "global.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 = "global.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; @@ -367,23 +153,30 @@ 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(dhcp_edev, tmp_ip); + dhcp_result->ip = net_read_ip(&bp->bp_yiaddr); + dhcp_result->serverip = net_read_ip(&bp->bp_siaddr); + + if (strlen(bp->bp_file) > 0) + dhcp_result->bootfile = xstrdup(bp->bp_file); +} - tmp_ip = net_read_ip(&bp->bp_siaddr); - if (tmp_ip != 0) - net_set_serverip_empty(tmp_ip); +static int dhcp_set_string_options(int option, const char *str, u8 *e) +{ + int str_len; - 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); - } + if (!str) + return 0; - debug("bootfile: %s\n", bp->bp_file); + str_len = strlen(str); + if (!str_len) + return 0; + + *e++ = option; + *e++ = str_len; + memcpy(e, str, str_len); + + return str_len + 2; } /* @@ -392,10 +185,11 @@ static void bootp_copy_net_params(struct bootp *bp) 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; @@ -414,22 +208,20 @@ static int dhcp_extended(u8 *e, int message_type, IPaddr_t ServerID, 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 */ @@ -484,20 +276,44 @@ static int bootp_request(void) 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) @@ -611,13 +427,11 @@ static void dhcp_handler(void *ctx, char *packet, unsigned int len) debug("%s: State REQUESTING\n", __func__); if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK ) { - IPaddr_t ip; 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(dhcp_edev); - 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; @@ -627,39 +441,48 @@ 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(struct eth_device *edev, 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; - - 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; + 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)) { @@ -671,7 +494,7 @@ int dhcp(struct eth_device *edev, int retries, struct dhcp_req_param *param) if (ret) goto out1; - net_set_ip(dhcp_edev, 0); + net_set_ip(edev, 0); dhcp_start = get_time_ns(); ret = bootp_request(); /* Basically same as BOOTP */ @@ -683,7 +506,7 @@ int dhcp(struct eth_device *edev, 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(struct eth_device *edev, 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_empty(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 -- cgit v1.2.3 From 4362c73ac768ad7218982fc1ccf8ae04285c27d1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 3 Feb 2011 14:37:18 +0100 Subject: net: Pick network device based on IP settings The IP/netmask/gateway settings contain all informations needed to pick the correct network device. This patch adds support for that and makes specifying the "current" network interface using the ethact command unnecessary. Signed-off-by: Sascha Hauer --- include/net.h | 1 + net/net.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/net.h b/include/net.h index b7555c0de6..3faecff5d7 100644 --- a/include/net.h +++ b/include/net.h @@ -226,6 +226,7 @@ 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); diff --git a/net/net.c b/net/net.c index 33d6e2c5b0..94954677c5 100644 --- a/net/net.c +++ b/net/net.c @@ -144,6 +144,27 @@ static void arp_handler(struct arprequest *arp) } } +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) { char *pkt; @@ -154,6 +175,9 @@ static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *et unsigned retries = 0; int ret; + if (!edev) + return -EHOSTUNREACH; + if (!arp_packet) { arp_packet = net_alloc_packet(); if (!arp_packet) @@ -295,9 +319,11 @@ static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest, int ret; if (!edev) { - edev = eth_get_current(); + edev = net_route(dest); + if (!edev && net_gateway) + edev = net_route(net_gateway); if (!edev) - return ERR_PTR(-ENETDOWN); + return ERR_PTR(-EHOSTUNREACH); } if (!is_valid_ether_addr(edev->ethaddr)) { -- cgit v1.2.3 From 2319503ed22a6daea00de1c6f0965fcc4e649dd2 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 20 Nov 2017 23:43:21 +0100 Subject: net: remove "current" network device Now that we can do routing we no longer need a "current" network device. Remove it. Signed-off-by: Sascha Hauer --- commands/Makefile | 1 - commands/net.c | 66 ------------------------------------------------------- include/net.h | 2 -- net/eth.c | 17 -------------- net/ifup.c | 2 -- 5 files changed, 88 deletions(-) delete mode 100644 commands/net.c diff --git a/commands/Makefile b/commands/Makefile index 37486dceb1..582175f631 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 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 -#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/include/net.h b/include/net.h index 3faecff5d7..9f98b6f4df 100644 --- a/include/net.h +++ b/include/net.h @@ -413,8 +413,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); /** diff --git a/net/eth.c b/net/eth.c index 6dae6b9feb..a8f21b2277 100644 --- a/net/eth.c +++ b/net/eth.c @@ -28,7 +28,6 @@ #include #include -static struct eth_device *eth_current; static uint64_t last_link_check; LIST_HEAD(netdev_list); @@ -149,16 +148,6 @@ void of_eth_register_ethaddr(struct device_node *node, const char *ethaddr) 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; @@ -412,17 +401,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 2160e3ae46..423712e19c 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -58,8 +58,6 @@ int ifup(const char *name, unsigned flags) if (edev && edev->ipaddr && !(flags & IFUP_FLAG_FORCE)) return 0; - eth_set_current(edev); - env_push_context(); setenv("ip", ""); -- cgit v1.2.3 From 7457f45528d486daebc8d7392416f547dbd2a828 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 17 Nov 2017 16:14:41 +0100 Subject: net: ifup: Factor out a eth_discover function Signed-off-by: Sascha Hauer --- net/ifup.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/net/ifup.c b/net/ifup.c index 423712e19c..f6ccd70378 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -26,6 +26,30 @@ #include #include +static int eth_discover(const char *name) +{ + char *cmd_discover; + struct stat s; + int ret; + + cmd_discover = basprintf("/env/network/%s-discover", name); + + ret = stat(cmd_discover, &s); + if (ret) + goto out; + + ret = run_command(cmd_discover); + if (ret) { + pr_err("Running '%s' failed with %d\n", cmd_discover, ret); + goto out; + } + +out: + free(cmd_discover); + + return ret; +} + static char *vars[] = { "ipaddr", "netmask", @@ -48,9 +72,8 @@ static int eth_set_param(struct device_d *dev, const char *param) int ifup(const char *name, unsigned flags) { int ret; - char *cmd, *cmd_discover; + char *cmd; const char *ip; - struct stat s; int i; struct device_d *dev; struct eth_device *edev = eth_get_byname(name); @@ -66,7 +89,6 @@ int ifup(const char *name, unsigned flags) setenv(vars[i], ""); cmd = basprintf("source /env/network/%s", name); - cmd_discover = basprintf("/env/network/%s-discover", name); ret = run_command(cmd); if (ret) { @@ -74,14 +96,7 @@ int ifup(const char *name, unsigned flags) goto out; } - ret = stat(cmd_discover, &s); - if (!ret) { - ret = run_command(cmd_discover); - if (ret) { - pr_err("Running '%s' failed with %d\n", cmd, ret); - goto out; - } - } + eth_discover(name); dev = get_device_by_name(name); if (!dev) { @@ -142,7 +157,6 @@ int ifup(const char *name, unsigned flags) out: env_pop_context(); free(cmd); - free(cmd_discover); return ret; } -- cgit v1.2.3 From e612a5ca7aa8207efb119105a594e81a011ec7ce Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 21 Nov 2017 20:15:30 +0100 Subject: ifup: Use dhcp C API rather than running command DHCP has a C API, so use it instead of running as command. Signed-off-by: Sascha Hauer --- net/ifup.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/ifup.c b/net/ifup.c index f6ccd70378..0f5d2772e8 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -114,15 +115,12 @@ int ifup(const char *name, unsigned flags) if (!strcmp(ip, "dhcp")) { IPaddr_t serverip; - char *dhcp_cmd; serverip = getenv_ip("serverip"); if (serverip) net_set_serverip_empty(serverip); - dhcp_cmd = basprintf("dhcp %s", name); - ret = run_command(dhcp_cmd); - free(dhcp_cmd); + ret = dhcp(edev, NULL); if (ret) goto out; dev_set_param(dev, "linux.bootargs", "ip=dhcp"); -- cgit v1.2.3 From dfe2d162f3fc693bb95d3b67c674f2f264dc47e8 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 23 Nov 2017 19:15:31 +0100 Subject: net: Provide new way to configure network devices This provides a new way to configure network interfaces based on nvvars. A network interface can now be configured with variables in the nv.dev..* namespace. There is a new network device parameter "mode" which specifies the mode used to obtain IP settings. The mode can be "dhcp", "static" or "disabled": nv.dev.eth0.mode=dhcp (ipaddr, netmask are ignored in this setting) nv.dev.eth0.mode=static nv.dev.eth0.ipaddr=192.168.0.17 nv.dev.eth0.netmask=255.255.0.0 nv.dev.eth0.mode=disabled Signed-off-by: Sascha Hauer --- include/net.h | 7 ++ net/eth.c | 15 ++++ net/ifup.c | 256 ++++++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 190 insertions(+), 88 deletions(-) diff --git a/include/net.h b/include/net.h index 9f98b6f4df..926d817802 100644 --- a/include/net.h +++ b/include/net.h @@ -61,6 +61,12 @@ struct eth_device { IPaddr_t netmask; char ethaddr[6]; char *bootarg; + + 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) @@ -473,6 +479,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/eth.c b/net/eth.c index a8f21b2277..a9869f7d9d 100644 --- a/net/eth.c +++ b/net/eth.c @@ -21,12 +21,18 @@ #include #include #include +#include #include +#include #include #include #include #include #include +#include +#include +#include +#include static uint64_t last_link_check; @@ -340,6 +346,12 @@ late_initcall(eth_register_of_fixup); 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; @@ -378,6 +390,9 @@ int eth_register(struct eth_device *edev) edev->ethaddr, edev); edev->bootarg = xstrdup(""); dev_add_param_string(dev, "linux.bootargs", NULL, NULL, &edev->bootarg, 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); diff --git a/net/ifup.c b/net/ifup.c index 0f5d2772e8..dc41c47f24 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -25,116 +25,147 @@ #include #include #include +#include +#include +#include #include -static int eth_discover(const char *name) +static int eth_discover(char *file) { - char *cmd_discover; struct stat s; int ret; - cmd_discover = basprintf("/env/network/%s-discover", name); - - ret = stat(cmd_discover, &s); - if (ret) + ret = stat(file, &s); + if (ret) { + ret = 0; goto out; + } - ret = run_command(cmd_discover); + ret = run_command(file); if (ret) { - pr_err("Running '%s' failed with %d\n", cmd_discover, ret); + pr_err("Running '%s' failed with %d\n", file, ret); goto out; } out: - free(cmd_discover); + free(file); return ret; } -static char *vars[] = { - "ipaddr", - "netmask", - "gateway", - "serverip", -}; - -static int eth_set_param(struct device_d *dev, const char *param) +static int eth_discover_ethname(const char *ethname) { - const char *value = getenv(param); - - if (!value) - return 0; - if (!*value) - return 0; + return eth_discover(basprintf("/env/network/%s-discover", ethname)); +} - return dev_set_param(dev, param, value); +static int eth_discover_file(const char *filename) +{ + return eth_discover(basprintf("/env/network/%s", filename)); } -int ifup(const char *name, unsigned flags) +static int source_env_network(struct eth_device *edev) { - int ret; - char *cmd; - const char *ip; - int i; - struct device_d *dev; - struct eth_device *edev = eth_get_byname(name); + char *vars[] = { + "ipaddr", + "netmask", + "gateway", + "serverip", + "ethaddr", + "ip", + }; + IPaddr_t ipaddr, netmask, gateway, serverip; + unsigned char ethaddr[6]; + char *file, *cmd; + const char *ethaddrstr, *modestr; + int ret, mode, ethaddr_valid = 0, i; + struct stat s; - 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; + } - env_push_context(); + 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); - setenv("ip", ""); + env_push_context(); for (i = 0; i < ARRAY_SIZE(vars); i++) setenv(vars[i], ""); - cmd = basprintf("source /env/network/%s", 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; } - eth_discover(name); + ipaddr = getenv_ip("ipaddr"); + netmask = getenv_ip("netmask"); + gateway = getenv_ip("gateway"); + serverip = getenv_ip("serverip"); + ethaddrstr = getenv("ethaddr"); + if (ethaddrstr && *ethaddrstr) { + ret = string_to_ethaddr(ethaddrstr, ethaddr); + if (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) + 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; + } - ip = getenv("ip"); - if (!ip) - ip = ""; + edev->global_mode = mode; - if (!strcmp(ip, "dhcp")) { - IPaddr_t serverip; + if (ethaddr_valid) + memcpy(edev->ethaddr, ethaddr, 6); - serverip = getenv_ip("serverip"); + if (mode == ETH_MODE_STATIC) { + edev->ipaddr = ipaddr; + edev->netmask = netmask; + if (gateway) + net_set_gateway(gateway); if (serverip) - net_set_serverip_empty(serverip); + net_set_serverip(serverip); + } - ret = dhcp(edev, NULL); - if (ret) - goto out; - dev_set_param(dev, "linux.bootargs", "ip=dhcp"); - } else if (!strcmp(ip, "static")) { + ret = 0; + +out: + env_pop_context(); + free(cmd); + 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; - for (i = 0; i < ARRAY_SIZE(vars); i++) { - ret = eth_set_param(dev, vars[i]); - if (ret) - goto out; - } - serverip = net_get_serverip(); gateway = net_get_gateway(); @@ -143,46 +174,95 @@ int ifup(const char *name, unsigned flags) &serverip, &gateway, &edev->netmask); - dev_set_param(dev, "linux.bootargs", bootarg); + dev_set_param(&edev->dev, "linux.bootargs", bootarg); free(bootarg); - } else { - pr_err("unknown ip type: %s\n", ip); - ret = -EINVAL; - goto out; + } else if (edev->global_mode == ETH_MODE_DHCP) { + dev_set_param(&edev->dev, "linux.bootargs", "ip=dhcp"); } +} - ret = 0; -out: - env_pop_context(); - free(cmd); +int ifup_edev(struct eth_device *edev, unsigned flags) +{ + int ret; - return 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; } @@ -214,11 +294,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/ file. See Documentation/user/networking.rst") BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT ("-a", "bring up all interfaces") -- cgit v1.2.3 From 78425235a7dc69233d21477ebb9a42d996948176 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 7 Jun 2016 16:26:00 +0200 Subject: net: update network docs The network configuration has changed in the previous patches. Update the documentation accordingly. Signed-off-by: Sascha Hauer --- Documentation/user/booting-linux.rst | 40 ++++---------- Documentation/user/networking.rst | 101 +++++++++++++++++++++++++++++++++-- 2 files changed, 105 insertions(+), 36 deletions(-) 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:::`` 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 @@ 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 | | ++===================+==============+====================================================+ +| .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 @@ 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 ` 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 ------------------- -- cgit v1.2.3 From eb995e0e09523cc1128563199340dab327dafabe Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 24 Nov 2017 08:43:02 +0100 Subject: net: environment: remove ethx setup files Network configuration is now done with nvvars, so /env/network/eth* files are no longer needed. Remove them. Signed-off-by: Sascha Hauer --- arch/arm/boards/afi-gf/defaultenv-gf/network/eth1 | 18 ------------------ .../defaultenv-pico-hobbit/network/eth1 | 18 ------------------ .../boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth1 | 18 ------------------ defaultenv/defaultenv-2-base/network/eth0 | 18 ------------------ 4 files changed, 72 deletions(-) delete mode 100644 arch/arm/boards/afi-gf/defaultenv-gf/network/eth1 delete mode 100644 arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/network/eth1 delete mode 100644 arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth1 delete mode 100644 defaultenv/defaultenv-2-base/network/eth0 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/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/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/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 -- cgit v1.2.3 From acc3a3ef900ad92ccca57aeb5f7e446f8bd4745d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 24 Nov 2017 08:44:24 +0100 Subject: net: environment: update automounts Instead of using "ifup ethx" use "ifup -a" which works with all network interfaces. Also replace "$ethx.serverip" with "$global.net.server". This makes the automount independent of the actual network interface. Remove all board specific /env/init/automount files which were only there to use eth1 instead of the previously hardcoded eth0. Signed-off-by: Sascha Hauer --- Documentation/user/automount.rst | 2 +- arch/arm/boards/afi-gf/defaultenv-gf/init/automount | 10 ---------- arch/arm/boards/technexion-pico-hobbit/Makefile | 1 - arch/arm/boards/technexion-pico-hobbit/board.c | 2 -- .../defaultenv-pico-hobbit/init/automount | 11 ----------- .../zii-imx6q-rdu2/defaultenv-rdu2/init/automount | 17 ----------------- defaultenv/defaultenv-2-base/init/automount | 4 ++-- 7 files changed, 3 insertions(+), 44 deletions(-) delete mode 100644 arch/arm/boards/afi-gf/defaultenv-gf/init/automount delete mode 100644 arch/arm/boards/technexion-pico-hobbit/defaultenv-pico-hobbit/init/automount delete mode 100644 arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/init/automount 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/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/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/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/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 -- cgit v1.2.3 From dd36203979331fdcfc8196cf671cfff8ce71cd15 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 24 Nov 2017 08:48:24 +0100 Subject: defaultenv: Add README for new network config Network configuration has changed. In case somebody looks to the old /env/network/ directoy place a README there to add a pointer how the new configuration is done. Signed-off-by: Sascha Hauer --- defaultenv/defaultenv-2-base/network/README | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 defaultenv/defaultenv-2-base/network/README 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. -- cgit v1.2.3 From ac7b6bcb7ef5abe5d5f6b2a64453080b7994a6eb Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 28 Nov 2017 10:56:30 +0100 Subject: net: Add linuxdevname property When you have a static network environment but more than one network device on your machine it is necessary to provide the parameter to the ip parameter at kernel cmd line. The device name assigned by Linux cannot in general be predicted as it depends on driver bind order. This patch introduces a new property linux.devname to eth devices. The value is added to bootargs per interface and can be changed in env/network/INTF Based on patch by Gavin Schenk . Signed-off-by: Sascha Hauer --- include/net.h | 1 + net/eth.c | 2 ++ net/ifup.c | 14 +++++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/net.h b/include/net.h index 926d817802..a09cb155a8 100644 --- a/include/net.h +++ b/include/net.h @@ -61,6 +61,7 @@ struct eth_device { IPaddr_t netmask; char ethaddr[6]; char *bootarg; + char *linuxdevname; bool ifup; #define ETH_MODE_DHCP 0 diff --git a/net/eth.c b/net/eth.c index a9869f7d9d..5d45a04612 100644 --- a/net/eth.c +++ b/net/eth.c @@ -390,6 +390,8 @@ int eth_register(struct eth_device *edev) 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); diff --git a/net/ifup.c b/net/ifup.c index dc41c47f24..827c5c03d1 100644 --- a/net/ifup.c +++ b/net/ifup.c @@ -72,11 +72,12 @@ static int source_env_network(struct eth_device *edev) "serverip", "ethaddr", "ip", + "linuxdevname", }; IPaddr_t ipaddr, netmask, gateway, serverip; unsigned char ethaddr[6]; char *file, *cmd; - const char *ethaddrstr, *modestr; + const char *ethaddrstr, *modestr, *linuxdevname; int ret, mode, ethaddr_valid = 0, i; struct stat s; @@ -107,6 +108,7 @@ static int source_env_network(struct eth_device *edev) 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); @@ -149,6 +151,11 @@ static int source_env_network(struct eth_device *edev) net_set_serverip(serverip); } + if (linuxdevname) { + free(edev->linuxdevname); + edev->linuxdevname = xstrdup(linuxdevname); + } + ret = 0; out: @@ -169,11 +176,12 @@ static void set_linux_bootarg(struct eth_device *edev) serverip = net_get_serverip(); gateway = net_get_gateway(); - bootarg = basprintf("ip=%pI4:%pI4:%pI4:%pI4:::", + bootarg = basprintf("ip=%pI4:%pI4:%pI4:%pI4::%s:", &edev->ipaddr, &serverip, &gateway, - &edev->netmask); + &edev->netmask, + edev->linuxdevname ? edev->linuxdevname : ""); dev_set_param(&edev->dev, "linux.bootargs", bootarg); free(bootarg); } else if (edev->global_mode == ETH_MODE_DHCP) { -- cgit v1.2.3 From 183515b67a757d51f538af3dc6dcd2c889ddd3af Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 28 Nov 2017 12:31:50 +0100 Subject: commands: Add ip_route_add command The ip_route_get command is used to retrieve the network device used to reach a given IP address. This is useful for informational purposes and also for the network boot which wants to get the linux.bootargs parameter of the network device used for nfsroot. Signed-off-by: Sascha Hauer --- commands/Kconfig | 10 ++++++ commands/Makefile | 1 + commands/ip-route-get.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 commands/ip-route-get.c 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 582175f631..eb4796389e 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -122,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/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 +#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 -- cgit v1.2.3 From 8201a940e313cd9c2f989a7af5d6a4fb3f8ab31c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 28 Nov 2017 12:55:42 +0100 Subject: defaultenv-2: set bootargs correctly for network boot The defaultenv-2 network boot script uses bootargs-ip which hardcodes eth0 as network device. To make this work with other nwetork devices use the "ip_route_get" command to determine the network device used to reach the server. Signed-off-by: Sascha Hauer --- defaultenv/defaultenv-2-base/bin/bootargs-ip | 11 ----------- defaultenv/defaultenv-2-base/boot/net | 3 ++- 2 files changed, 2 insertions(+), 12 deletions(-) delete mode 100644 defaultenv/defaultenv-2-base/bin/bootargs-ip 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 -- cgit v1.2.3