patch-2.2.18 linux/net/ipv4/ipconfig.c
Next file: linux/net/ipv4/proc.c
Previous file: linux/net/ipv4/ip_masq_user.c
Back to the patch index
Back to the overall index
- Lines: 454
- Date:
Tue Nov 21 17:33:20 2000
- Orig file:
v2.2.17/net/ipv4/ipconfig.c
- Orig date:
Sun Jun 11 21:44:23 2000
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
@@ -1,5 +1,5 @@
/*
- * $Id: ipconfig.c,v 1.20.2.1 1999/06/28 11:33:27 davem Exp $
+ * $Id: ipconfig.c,v 1.20.2.3 2000/09/07 03:55:40 davem Exp $
*
* Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or
* user-supplied information to configure own IP address and routes.
@@ -74,8 +74,9 @@
#define CONF_POST_OPEN (1*HZ) /* After opening: 1 second */
/* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */
-#define CONF_OPEN_RETRIES 3 /* (Re)open devices three times */
-#define CONF_SEND_RETRIES 3 /* Send requests three times */
+#define CONF_OPEN_RETRIES 2 /* (Re)open devices twice */
+#define CONF_SEND_RETRIES 6 /* Send six requests per open */
+#define CONF_INTER_TIMEOUT (HZ/2) /* Inter-device timeout: 1/2 second */
#define CONF_BASE_TIMEOUT (HZ*2) /* Initial timeout: 2 seconds */
#define CONF_TIMEOUT_RANDOM (HZ) /* Maximum amount of randomization */
#define CONF_TIMEOUT_MULT *7/4 /* Rate of timeout growth */
@@ -86,7 +87,7 @@
* Public IP configuration
*/
-int ic_enable __initdata = 1; /* Automatic IP cfg enabled? */
+int ic_enable __initdata = 0; /* IP config enabled? */
/* Protocol choice */
static int ic_proto_enabled __initdata = 0
@@ -129,10 +130,11 @@
static int ic_proto_have_if __initdata = 0;
#ifdef IPCONFIG_DYNAMIC
-static volatile int ic_got_reply = 0; /* Protocol(s) we got reply from */
+static spinlock_t ic_recv_lock = SPIN_LOCK_UNLOCKED;
+static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */
#endif
#ifdef IPCONFIG_DHCP
-static int ic_dhcp_msgtype __initdata = 0; /* Last incoming msg type */
+static int ic_dhcp_msgtype __initdata = 0; /* DHCP msg type received */
#endif
@@ -144,11 +146,12 @@
struct ic_device *next;
struct device *dev;
unsigned short flags;
- int able;
+ short able;
+ u32 xid;
};
-static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
-static struct device *ic_dev __initdata = NULL; /* Selected device */
+static struct ic_device *ic_first_dev __initdata = NULL; /* Open devices */
+static struct device *ic_dev __initdata = NULL; /* Selected device */
static int __init ic_open_devs(void)
{
@@ -185,8 +188,13 @@
last = &d->next;
d->flags = oflags;
d->able = able;
+ if (able & IC_BOOTP)
+ get_random_bytes(&d->xid, sizeof(u32));
+ else
+ d->xid = 0;
ic_proto_have_if |= able;
- DBG((SELF "%s UP (able=%d)\n", dev->name, able));
+ DBG((SELF "%s UP (able=%d, xid=%08x)\n",
+ dev->name, able, d->xid));
}
*last = NULL;
@@ -386,11 +394,22 @@
unsigned char *rarp_ptr = (unsigned char *) (rarp + 1);
unsigned long sip, tip;
unsigned char *sha, *tha; /* s for "source", t for "target" */
+ struct ic_device *d;
+
+ /* One reply at a time, please. */
+ spin_lock(&ic_recv_lock);
/* If we already have a reply, just drop the packet */
if (ic_got_reply)
goto drop;
+ /* Find the ic_device that the packet arrived on */
+ d = ic_first_dev;
+ while (d && d->dev != dev)
+ d = d->next;
+ if (!d)
+ goto drop; /* should never happen */
+
/* If this test doesn't pass, it's not IP, or we should ignore it anyway */
if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd))
goto drop;
@@ -420,7 +439,7 @@
if (ic_servaddr != INADDR_NONE && ic_servaddr != sip)
goto drop;
- /* Victory! The packet is what we were looking for! */
+ /* We have a winner! */
ic_dev = dev;
if (ic_myaddr == INADDR_NONE)
ic_myaddr = tip;
@@ -428,8 +447,12 @@
ic_got_reply = IC_RARP;
drop:
- /* and throw the packet out */
+ /* Show's over. Nothing to see here. */
+ spin_unlock(&ic_recv_lock);
+
+ /* Throw the packet out. */
kfree_skb(skb);
+
return 0;
}
@@ -437,16 +460,23 @@
/*
* Send RARP request packet over all devices which allow RARP.
*/
+static void __init ic_rarp_send_if(struct ic_device *d)
+{
+ struct device *dev = d->dev;
+ arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
+ dev->dev_addr, dev->dev_addr);
+}
+
+/*
+ * Send RARP request package over a single interface.
+ */
static void __init ic_rarp_send(void)
{
struct ic_device *d;
for (d=ic_first_dev; d; d=d->next)
- if (d->able & IC_RARP) {
- struct device *dev = d->dev;
- arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
- dev->dev_addr, dev->dev_addr);
- }
+ if (d->able & IC_RARP)
+ ic_rarp_send_if(d);
}
#endif
@@ -491,8 +521,6 @@
#define DHCPRELEASE 7
#define DHCPINFORM 8
-static u32 ic_bootp_xid;
-
static int ic_bootp_recv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt);
@@ -516,12 +544,12 @@
static void __init
ic_dhcp_init_options(u8 *options)
{
- u8 msgtype = ((ic_dhcp_msgtype == DHCPOFFER)
- ? DHCPREQUEST : DHCPDISCOVER);
+ u8 mt = ((ic_servaddr == INADDR_NONE)
+ ? DHCPDISCOVER : DHCPREQUEST);
u8 *e = options;
#ifdef IPCONFIG_DEBUG
- printk("DHCP: Sending message type %d\n", msgtype);
+ printk("DHCP: Sending message type %d\n", mt);
#endif
memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */
@@ -529,9 +557,14 @@
*e++ = 53; /* DHCP message type */
*e++ = 1;
- *e++ = msgtype;
+ *e++ = mt;
+
+ if (mt == DHCPREQUEST) {
+ *e++ = 54; /* Server ID (IP address) */
+ *e++ = 4;
+ memcpy(e, &ic_servaddr, 4);
+ e += 4;
- if (msgtype == DHCPREQUEST) {
*e++ = 50; /* Requested IP address */
*e++ = 4;
memcpy(e, &ic_myaddr, 4);
@@ -595,8 +628,6 @@
static inline void
ic_bootp_init(void)
{
- get_random_bytes(&ic_bootp_xid, sizeof(u32));
- DBG(("DHCP/BOOTP: XID=%08x\n", ic_bootp_xid));
dev_add_pack(&bootp_packet_type);
}
@@ -656,7 +687,7 @@
b->server_ip = INADDR_NONE;
memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
b->secs = htons(jiffies / HZ);
- b->xid = ic_bootp_xid;
+ b->xid = d->xid;
/* add DHCP options or BOOTP extensions */
#ifdef IPCONFIG_DHCP
@@ -756,12 +787,23 @@
{
struct bootp_pkt *b = (struct bootp_pkt *) skb->nh.iph;
struct iphdr *h = &b->iph;
+ struct ic_device *d;
int len;
+ /* One reply at a time, please. */
+ spin_lock(&ic_recv_lock);
+
/* If we already have a reply, just drop the packet */
if (ic_got_reply)
goto drop;
+ /* Find the ic_device that the packet arrived on */
+ d = ic_first_dev;
+ while (d && d->dev != dev)
+ d = d->next;
+ if (!d)
+ goto drop; /* should never happen */
+
/* Check whether it's a BOOTP packet */
if (skb->pkt_type == PACKET_OTHERHOST ||
skb->len < sizeof(struct udphdr) + sizeof(struct iphdr) ||
@@ -783,9 +825,9 @@
/* Is it a reply to our BOOTP request? */
len = ntohs(b->udph.len) - sizeof(struct udphdr);
- if (len < 300 || /* See RFC 951:2.1 */
+ if (len < 300 || /* See RFC 951:2.1 */
b->op != BOOTP_REPLY ||
- b->xid != ic_bootp_xid) {
+ b->xid != d->xid) {
printk("?");
goto drop;
}
@@ -798,7 +840,7 @@
#ifdef IPCONFIG_DHCP
u32 server_id = INADDR_NONE;
- ic_dhcp_msgtype = 0;
+ int mt = 0;
ext = &b->exten[4];
while (ext < end && *ext != 0xff) {
@@ -811,7 +853,7 @@
switch (*opt) {
case 53: /* Message type */
if (opt[1])
- ic_dhcp_msgtype = opt[2];
+ mt = opt[2];
break;
case 54: /* Server ID (IP address) */
if (opt[1] >= 4)
@@ -821,11 +863,15 @@
}
#ifdef IPCONFIG_DEBUG
- printk("DHCP: Got message type %d\n", ic_dhcp_msgtype);
+ printk("DHCP: Got message type %d\n", mt);
#endif
- switch (ic_dhcp_msgtype) {
+ switch (mt) {
case DHCPOFFER:
+ /* While in the process of accepting one offer,
+ ignore all others. */
+ if (ic_myaddr != INADDR_NONE)
+ goto drop;
/* Let's accept that offer. */
ic_myaddr = b->your_ip;
ic_servaddr = server_id;
@@ -833,7 +879,7 @@
printk("DHCP: Offered address %s", in_ntoa(ic_myaddr));
printk(" by server %s\n", in_ntoa(ic_servaddr));
#endif
- goto drop;
+ break;
case DHCPACK:
/* Yeah! */
@@ -846,6 +892,8 @@
goto drop;
}
+ ic_dhcp_msgtype = mt;
+
#endif /* IPCONFIG_DHCP */
ext = &b->exten[4];
@@ -859,6 +907,7 @@
}
}
+ /* We have a winner! */
ic_dev = dev;
ic_myaddr = b->your_ip;
ic_servaddr = b->server_ip;
@@ -869,8 +918,12 @@
ic_got_reply = IC_BOOTP;
drop:
- /* and throw the packet out */
+ /* Show's over. Nothing to see here. */
+ spin_unlock(&ic_recv_lock);
+
+ /* Throw the packet out. */
kfree_skb(skb);
+
return 0;
}
@@ -887,8 +940,8 @@
static int __init ic_dynamic(void)
{
int retries;
- unsigned long timeout, jiff;
- unsigned long start_jiffies;
+ struct ic_device *d;
+ unsigned long start_jiffies, timeout, jiff;
int do_bootp = ic_proto_have_if & IC_BOOTP;
int do_rarp = ic_proto_have_if & IC_RARP;
@@ -936,36 +989,39 @@
* [Actually we could now, but the nothing else running note still
* applies.. - AC]
*/
- printk(KERN_NOTICE "Sending %s%s%s requests ",
+ printk(KERN_NOTICE "Sending %s%s%s requests .",
do_bootp
? ((ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP") : "",
(do_bootp && do_rarp) ? " and " : "",
do_rarp ? "RARP" : "");
+
start_jiffies = jiffies;
+ d = ic_first_dev;
retries = CONF_SEND_RETRIES;
get_random_bytes(&timeout, sizeof(timeout));
timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM);
for(;;) {
#ifdef IPCONFIG_BOOTP
- if (do_bootp)
- ic_bootp_send(jiffies - start_jiffies);
+ if (do_bootp && (d->able & IC_BOOTP))
+ ic_bootp_send_if(d, jiffies - start_jiffies);
#endif
#ifdef IPCONFIG_RARP
- if (do_rarp)
- ic_rarp_send();
+ if (do_rarp && (d->able & IC_RARP))
+ ic_rarp_send_if(d);
#endif
- printk(".");
- jiff = jiffies + timeout;
+ jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout);
while (jiffies < jiff && !ic_got_reply)
;
+
#ifdef IPCONFIG_DHCP
+ /* DHCP isn't done until we get a DHCPACK. */
if ((ic_got_reply & IC_BOOTP)
&& (ic_proto_enabled & IC_USE_DHCP)
&& ic_dhcp_msgtype != DHCPACK)
{
- printk(",");
ic_got_reply = 0;
+ printk(",");
continue;
}
#endif /* IPCONFIG_DHCP */
@@ -975,14 +1031,21 @@
break;
}
+ if ((d = d->next))
+ continue;
+
if (! --retries) {
printk(" timed out!\n");
break;
}
+ d = ic_first_dev;
+
timeout = timeout CONF_TIMEOUT_MULT;
if (timeout > CONF_TIMEOUT_MAX)
timeout = CONF_TIMEOUT_MAX;
+
+ printk(".");
}
#ifdef IPCONFIG_BOOTP
@@ -997,7 +1060,8 @@
if (!ic_got_reply)
return -1;
- printk(SELF "Got %s answer from %s\n",
+ printk(SELF "%s: Got %s answer from %s\n",
+ ic_dev->name,
((ic_got_reply & IC_RARP) ? "RARP"
: (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"),
in_ntoa(ic_servaddr));
@@ -1167,7 +1231,7 @@
* Clue in the operator.
*/
printk(SELF "Complete:");
- printk("\n device=%s", ic_dev->name);
+ printk( "\n if=%s", ic_dev->name);
printk(", addr=%s", in_ntoa(ic_myaddr));
printk(", mask=%s", in_ntoa(ic_netmask));
printk(", gw=%s", in_ntoa(ic_gateway));
@@ -1199,14 +1263,14 @@
* by BOOTP
* <device> - use all available devices
* <PROTO>:
- * dhcp|bootp|rarp - use given protocol
- * both or empty - use both BOOTP and RARP (not DHCP)
- * off or none - don't do autoconfig at all
+ * off|none - don't do autoconfig at all (DEFAULT)
+ * on|any - use any configured protocol
+ * dhcp|bootp|rarp - use only the specified protocol
+ * both - use both BOOTP and RARP (not DHCP)
*/
static int __init ic_proto_name(char *name)
{
- if (!strcmp(name, "off") || !strcmp(name, "none")) {
- ic_proto_enabled = 0;
+ if (!strcmp(name, "on") || !strcmp(name, "any")) {
return 1;
}
#ifdef CONFIG_IP_PNP_DHCP
@@ -1241,10 +1305,10 @@
char *cp, *ip, *dp;
int num = 0;
- if (!strcmp(addrs, "off") || !strcmp(addrs, "none")) {
- ic_enable = 0;
+ ic_enable = (*addrs && strcmp(addrs, "off") && strcmp(addrs, "none"));
+ if (!ic_enable)
return;
- }
+
if (ic_proto_name(addrs))
return;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)