Commit 2647cffb authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by David S. Miller

net: ipconfig: Support using "delayed" DHCP replies

The dhcp code only waits 1s between sending DHCP requests on different
devices and only accepts an answer for the device that sent out the last
request. Only the timeout at the end of a loop is increased iteratively
which favours only the last device. This makes it impossible to work
with a dhcp server that takes little more than 1s connected to a device
that is not the last one.

Instead of also increasing the inter-device timeout, teach the code to
handle delayed replies.

To accomplish that, make *ic_dev track the current ic_device instead of
the current net_device and adapt all users accordingly. The relevant
change then is to reset d to ic_dev on a reply to assert that the
followup request goes through the right device.
Signed-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 22fc5388
...@@ -188,7 +188,7 @@ struct ic_device { ...@@ -188,7 +188,7 @@ struct ic_device {
}; };
static struct ic_device *ic_first_dev __initdata; /* List of open device */ static struct ic_device *ic_first_dev __initdata; /* List of open device */
static struct net_device *ic_dev __initdata; /* Selected device */ static struct ic_device *ic_dev __initdata; /* Selected device */
static bool __init ic_is_init_dev(struct net_device *dev) static bool __init ic_is_init_dev(struct net_device *dev)
{ {
...@@ -307,7 +307,7 @@ static void __init ic_close_devs(void) ...@@ -307,7 +307,7 @@ static void __init ic_close_devs(void)
while ((d = next)) { while ((d = next)) {
next = d->next; next = d->next;
dev = d->dev; dev = d->dev;
if (dev != ic_dev && !netdev_uses_dsa(dev)) { if (dev != ic_dev->dev && !netdev_uses_dsa(dev)) {
pr_debug("IP-Config: Downing %s\n", dev->name); pr_debug("IP-Config: Downing %s\n", dev->name);
dev_change_flags(dev, d->flags); dev_change_flags(dev, d->flags);
} }
...@@ -372,7 +372,7 @@ static int __init ic_setup_if(void) ...@@ -372,7 +372,7 @@ static int __init ic_setup_if(void)
int err; int err;
memset(&ir, 0, sizeof(ir)); memset(&ir, 0, sizeof(ir));
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name); strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->dev->name);
set_sockaddr(sin, ic_myaddr, 0); set_sockaddr(sin, ic_myaddr, 0);
if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) { if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) {
pr_err("IP-Config: Unable to set interface address (%d)\n", pr_err("IP-Config: Unable to set interface address (%d)\n",
...@@ -396,7 +396,7 @@ static int __init ic_setup_if(void) ...@@ -396,7 +396,7 @@ static int __init ic_setup_if(void)
* out, we'll try to muddle along. * out, we'll try to muddle along.
*/ */
if (ic_dev_mtu != 0) { if (ic_dev_mtu != 0) {
strcpy(ir.ifr_name, ic_dev->name); strcpy(ir.ifr_name, ic_dev->dev->name);
ir.ifr_mtu = ic_dev_mtu; ir.ifr_mtu = ic_dev_mtu;
if ((err = ic_dev_ioctl(SIOCSIFMTU, &ir)) < 0) if ((err = ic_dev_ioctl(SIOCSIFMTU, &ir)) < 0)
pr_err("IP-Config: Unable to set interface mtu to %d (%d)\n", pr_err("IP-Config: Unable to set interface mtu to %d (%d)\n",
...@@ -568,7 +568,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -568,7 +568,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
goto drop_unlock; goto drop_unlock;
/* We have a winner! */ /* We have a winner! */
ic_dev = dev; ic_dev = d;
if (ic_myaddr == NONE) if (ic_myaddr == NONE)
ic_myaddr = tip; ic_myaddr = tip;
ic_servaddr = sip; ic_servaddr = sip;
...@@ -655,8 +655,6 @@ static struct packet_type bootp_packet_type __initdata = { ...@@ -655,8 +655,6 @@ static struct packet_type bootp_packet_type __initdata = {
.func = ic_bootp_recv, .func = ic_bootp_recv,
}; };
static __be32 ic_dev_xid; /* Device under configuration */
/* /*
* Initialize DHCP/BOOTP extension fields in the request. * Initialize DHCP/BOOTP extension fields in the request.
*/ */
...@@ -1038,12 +1036,6 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str ...@@ -1038,12 +1036,6 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
goto drop_unlock; goto drop_unlock;
} }
/* Is it a reply for the device we are configuring? */
if (b->xid != ic_dev_xid) {
net_err_ratelimited("DHCP/BOOTP: Ignoring delayed packet\n");
goto drop_unlock;
}
/* Parse extensions */ /* Parse extensions */
if (ext_len >= 4 && if (ext_len >= 4 &&
!memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */ !memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */
...@@ -1130,7 +1122,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str ...@@ -1130,7 +1122,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
} }
/* We have a winner! */ /* We have a winner! */
ic_dev = dev; ic_dev = d;
ic_myaddr = b->your_ip; ic_myaddr = b->your_ip;
ic_servaddr = b->server_ip; ic_servaddr = b->server_ip;
ic_addrservaddr = b->iph.saddr; ic_addrservaddr = b->iph.saddr;
...@@ -1225,9 +1217,6 @@ static int __init ic_dynamic(void) ...@@ -1225,9 +1217,6 @@ static int __init ic_dynamic(void)
timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned int) CONF_TIMEOUT_RANDOM); timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned int) CONF_TIMEOUT_RANDOM);
for (;;) { for (;;) {
#ifdef IPCONFIG_BOOTP #ifdef IPCONFIG_BOOTP
/* Track the device we are configuring */
ic_dev_xid = d->xid;
if (do_bootp && (d->able & IC_BOOTP)) if (do_bootp && (d->able & IC_BOOTP))
ic_bootp_send_if(d, jiffies - start_jiffies); ic_bootp_send_if(d, jiffies - start_jiffies);
#endif #endif
...@@ -1245,6 +1234,8 @@ static int __init ic_dynamic(void) ...@@ -1245,6 +1234,8 @@ static int __init ic_dynamic(void)
(ic_proto_enabled & IC_USE_DHCP) && (ic_proto_enabled & IC_USE_DHCP) &&
ic_dhcp_msgtype != DHCPACK) { ic_dhcp_msgtype != DHCPACK) {
ic_got_reply = 0; ic_got_reply = 0;
/* continue on device that got the reply */
d = ic_dev;
pr_cont(","); pr_cont(",");
continue; continue;
} }
...@@ -1487,7 +1478,7 @@ static int __init ip_auto_config(void) ...@@ -1487,7 +1478,7 @@ static int __init ip_auto_config(void)
#endif /* IPCONFIG_DYNAMIC */ #endif /* IPCONFIG_DYNAMIC */
} else { } else {
/* Device selected manually or only one device -> use it */ /* Device selected manually or only one device -> use it */
ic_dev = ic_first_dev->dev; ic_dev = ic_first_dev;
} }
addr = root_nfs_parse_addr(root_server_path); addr = root_nfs_parse_addr(root_server_path);
...@@ -1522,7 +1513,7 @@ static int __init ip_auto_config(void) ...@@ -1522,7 +1513,7 @@ static int __init ip_auto_config(void)
pr_info("IP-Config: Complete:\n"); pr_info("IP-Config: Complete:\n");
pr_info(" device=%s, hwaddr=%*phC, ipaddr=%pI4, mask=%pI4, gw=%pI4\n", pr_info(" device=%s, hwaddr=%*phC, ipaddr=%pI4, mask=%pI4, gw=%pI4\n",
ic_dev->name, ic_dev->addr_len, ic_dev->dev_addr, ic_dev->dev->name, ic_dev->dev->addr_len, ic_dev->dev->dev_addr,
&ic_myaddr, &ic_netmask, &ic_gateway); &ic_myaddr, &ic_netmask, &ic_gateway);
pr_info(" host=%s, domain=%s, nis-domain=%s\n", pr_info(" host=%s, domain=%s, nis-domain=%s\n",
utsname()->nodename, ic_domain, utsname()->domainname); utsname()->nodename, ic_domain, utsname()->domainname);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment