#include <linux/in.h>
#include <linux/if.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/seq_file.h>
#include <linux/major.h>
#include <linux/root_dev.h>
+#include <linux/delay.h>
+#include <linux/nfs_fs.h>
#include <net/arp.h>
#include <net/ip.h>
#include <net/ipconfig.h>
+#include <net/route.h>
#include <asm/uaccess.h>
#include <net/checksum.h>
#endif
/* Define the friendly delay before and after opening net devices */
-#define CONF_PRE_OPEN (HZ/2) /* Before opening: 1/2 second */
-#define CONF_POST_OPEN (1*HZ) /* After opening: 1 second */
+#define CONF_PRE_OPEN 500 /* Before opening: 1/2 second */
+#define CONF_POST_OPEN 1 /* After opening: 1 second */
/* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */
#define CONF_OPEN_RETRIES 2 /* (Re)open devices twice */
*/
int ic_set_manually __initdata = 0; /* IPconfig parameters set manually */
-int ic_enable __initdata = 0; /* IP config enabled? */
+static int ic_enable __initdata = 0; /* IP config enabled? */
/* Protocol choice */
int ic_proto_enabled __initdata = 0
#endif
;
-int ic_host_name_set __initdata = 0; /* Host name set by us? */
+static int ic_host_name_set __initdata = 0; /* Host name set by us? */
u32 ic_myaddr = INADDR_NONE; /* My IP address */
-u32 ic_netmask = INADDR_NONE; /* Netmask for local subnet */
+static u32 ic_netmask = INADDR_NONE; /* Netmask for local subnet */
u32 ic_gateway = INADDR_NONE; /* Gateway IP address */
u32 ic_servaddr = INADDR_NONE; /* Boot server IP address */
/* Persistent data: */
-int ic_proto_used; /* Protocol used, if any */
-u32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */
-u8 ic_domain[64]; /* DNS (not NIS) domain name */
+static int ic_proto_used; /* Protocol used, if any */
+static u32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */
+static u8 ic_domain[64]; /* DNS (not NIS) domain name */
/*
* Private state.
static int ic_proto_have_if __initdata = 0;
#ifdef IPCONFIG_DYNAMIC
-static spinlock_t ic_recv_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ic_recv_lock);
static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */
#endif
#ifdef IPCONFIG_DHCP
unsigned short oflags;
last = &ic_first_dev;
- rtnl_shlock();
+ rtnl_lock();
+
+ /* bring loopback device up first */
+ if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0)
+ printk(KERN_ERR "IP-Config: Failed to open %s\n", loopback_dev.name);
+
for (dev = dev_base; dev; dev = dev->next) {
+ if (dev == &loopback_dev)
+ continue;
if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
(!(dev->flags & IFF_LOOPBACK) &&
(dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
continue;
}
if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
- rtnl_shunlock();
+ rtnl_unlock();
return -1;
}
d->dev = dev;
dev->name, able, d->xid));
}
}
- rtnl_shunlock();
+ rtnl_unlock();
*last = NULL;
struct ic_device *d, *next;
struct net_device *dev;
- rtnl_shlock();
+ rtnl_lock();
next = ic_first_dev;
while ((d = next)) {
next = d->next;
}
kfree(d);
}
- rtnl_shunlock();
+ rtnl_unlock();
}
/*
mm_segment_t oldfs = get_fs();
set_fs(get_ds());
- res = devinet_ioctl(cmd, arg);
+ res = devinet_ioctl(cmd, (struct ifreq __user *) arg);
set_fs(oldfs);
return res;
}
mm_segment_t oldfs = get_fs();
set_fs(get_ds());
- res = ip_rt_ioctl(cmd, arg);
+ res = ip_rt_ioctl(cmd, (void __user *) arg);
set_fs(oldfs);
return res;
}
#ifdef IPCONFIG_RARP
-static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
+static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev);
static struct packet_type rarp_packet_type __initdata = {
.type = __constant_htons(ETH_P_RARP),
* Process received RARP packet.
*/
static int __init
-ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct arphdr *rarp;
unsigned char *rarp_ptr;
#define DHCPRELEASE 7
#define DHCPINFORM 8
-static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
+static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev);
static struct packet_type bootp_packet_type __initdata = {
.type = __constant_htons(ETH_P_IP),
b->htype = dev->type;
else if (dev->type == ARPHRD_IEEE802_TR) /* fix for token ring */
b->htype = ARPHRD_IEEE802;
+ else if (dev->type == ARPHRD_FDDI)
+ b->htype = ARPHRD_ETHER;
else {
printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name);
b->htype = dev->type; /* can cause undefined behavior */
/*
* Receive BOOTP reply.
*/
-static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
struct bootp_pkt *b;
struct iphdr *h;
struct ic_device *d;
- int len;
+ int len, ext_len;
/* Perform verifications before taking the lock. */
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
len = ntohs(b->udph.len) - sizeof(struct udphdr);
- if (len < 300)
+ ext_len = len - (sizeof(*b) -
+ sizeof(struct iphdr) -
+ sizeof(struct udphdr) -
+ sizeof(b->exten));
+ if (ext_len < 0)
goto drop;
/* Ok the front looks good, make sure we can get at the rest. */
}
/* Parse extensions */
- if (!memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */
+ if (ext_len >= 4 &&
+ !memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */
u8 *end = (u8 *) b + ntohs(b->iph.tot_len);
u8 *ext;
break;
case DHCPACK:
+ if (memcmp(dev->dev_addr, b->hw_addr, dev->addr_len) != 0)
+ goto drop_unlock;
+
/* Yeah! */
break;
#endif
jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout);
- while (time_before(jiffies, jiff) && !ic_got_reply) {
- barrier();
- cpu_relax();
- }
+ while (time_before(jiffies, jiff) && !ic_got_reply)
+ schedule_timeout_uninterruptible(1);
#ifdef IPCONFIG_DHCP
/* DHCP isn't done until we get a DHCPACK. */
if ((ic_got_reply & IC_BOOTP)
ic_rarp_cleanup();
#endif
- if (!ic_got_reply)
+ if (!ic_got_reply) {
+ ic_myaddr = INADDR_NONE;
return -1;
+ }
printk("IP-Config: Got %s answer from %u.%u.%u.%u, ",
((ic_got_reply & IC_RARP) ? "RARP"
if (*cp == ':')
*cp++ = '\0';
addr = in_aton(name);
- strcpy(name, cp);
+ memmove(name, cp, strlen(cp) + 1);
} else
addr = INADDR_NONE;
static int __init ip_auto_config(void)
{
- unsigned long jiff;
u32 addr;
#ifdef CONFIG_PROC_FS
try_try_again:
#endif
/* Give hardware a chance to settle */
- jiff = jiffies + CONF_PRE_OPEN;
- while (time_before(jiffies, jiff))
- cpu_relax();
+ msleep(CONF_PRE_OPEN);
/* Setup all network devices */
if (ic_open_devs() < 0)
return -1;
/* Give drivers a chance to settle */
- jiff = jiffies + CONF_POST_OPEN;
- while (time_before(jiffies, jiff))
- cpu_relax();
+ ssleep(CONF_POST_OPEN);
/*
* If the config information is insufficient (e.g., our IP address or