Messages in this thread | | | Date | Fri, 10 Dec 1999 18:58:13 -0800 | From | Chip Salzenberg <> | Subject | PATCH: boot-time DHCP |
| |
I was surprised to find that the plug-and-play network configuration supports BOOTP and RARP(?!) but not DHCP. So I added it myself.
As a bonus, I threw in a new /proc file: "/proc/net/pnp". If it has any non-comment lines, then it's suitable for use as your /etc/resolv.conf. :-)
The first version of the patch is enclosed.
Note that DHCP leases require periodic refreshes. So this patch is *NOT* enough for long-term operation: You still need the DHCP client from user space. But this patch will get you booting, even if your root filesystem is NFS-mounted.
Alan, I'm not quite done with the /proc features, so please do NOT consider this for 2.1.14.
Shar and enjoy!
PS: I'd appreciate some help with some latency issues. I invite anyone who knows the kernel network and scheduler code well to volunteer with some explanations. Thanks.
Index: Documentation/Configure.help *************** *** 2444,2450 **** the boot ROM of your network card was designed for booting Linux and does BOOTP itself, providing all necessary information on the kernel ! command line, you can say N here. If unsure, say Y. Note that if you ! want to use BOOTP, a BOOTP server must be operating on your network. ! Read Documentation/nfsroot.txt for details. RARP support --- 2444,2467 ---- the boot ROM of your network card was designed for booting Linux and does BOOTP itself, providing all necessary information on the kernel ! command line, you can say N here. ! ! If unsure, say Y. Note that if you want to use BOOTP, a BOOTP server ! must be operating on your network. Read Documentation/nfsroot.txt ! for details. ! ! DHCP support ! CONFIG_IP_PNP_DHCP ! If you want your Linux box to mount its whole root filesystem (the ! one containing the directory /) from some other computer over the ! net via NFS and you want the IP address of your computer to be ! discovered automatically at boot time using the DHCP protocol (a ! special protocol designed for doing this job), say Y here. In case ! the boot ROM of your network card was designed for booting Linux and ! does DHCP itself, providing all necessary information on the kernel ! command line, you can say N here. ! ! If unsure, say Y. Note that if you want to use DHCP, a DHCP server ! must be operating on your network. Read Documentation/nfsroot.txt ! for details. RARP support
Index: include/linux/proc_fs.h *************** *** 148,151 **** --- 148,152 ---- PROC_NET_AT_AARP, PROC_NET_BRIDGE, + PROC_NET_PNP, PROC_NET_LAST };
Index: include/net/ipconfig.h *************** *** 7,21 **** */ ! extern __u32 root_server_addr; ! extern u8 root_server_path[]; ! extern u32 ic_myaddr; ! extern u32 ic_servaddr; ! extern u32 ic_gateway; ! extern u32 ic_netmask; ! extern int ic_enable; ! extern int ic_host_name_set; ! extern int ic_set_manually; ! extern int ic_proto_enabled; ! #define IC_BOOTP 1 ! #define IC_RARP 2 --- 7,35 ---- */ ! /* The following are initdata: */ ! extern int ic_enable; /* Enable or disable the whole shebang */ ! ! extern int ic_proto_enabled; /* Protocols enabled (see IC_xxx) */ ! extern int ic_host_name_set; /* Host name set by ipconfig? */ ! ! extern u32 ic_myaddr; /* My IP address */ ! extern u32 ic_netmask; /* Netmask for local subnet */ ! extern u32 ic_gateway; /* Gateway IP address */ ! ! extern u32 ic_servaddr; /* Boot server IP address */ ! ! extern u32 root_server_addr; /* Address of NFS server */ ! extern u8 root_server_path[]; /* Path to mount as root */ ! ! /* The following are persistent (not initdata): */ ! ! extern int ic_proto_used; /* Protocol used, if any */ ! extern u32 ic_nameserver; /* DNS server IP address */ ! extern u8 ic_domain[]; /* DNS (not NIS) domain name */ ! ! /* bits in ic_proto_{enabled,used} */ ! #define IC_PROTO 0xFF /* Protocols mask: */ ! #define IC_BOOTP 0x01 /* BOOTP (or DHCP, see below) */ ! #define IC_RARP 0x02 /* RARP */ ! #define IC_USE_DHCP 0x100 /* If on, use DHCP instead of BOOTP */
Index: Documentation/nfsroot.txt *************** *** 25,29 **** in this case. The configuration script will then ask you whether you want to use nfsroot, and if yes what kind of auto configuration ! system you want to use. Selecting both BOOTP and RARP is safe. --- 25,29 ---- in this case. The configuration script will then ask you whether you want to use nfsroot, and if yes what kind of auto configuration ! system you want to use. Selecting both DHCP/BOOTP and RARP is safe. *************** *** 89,100 **** assumed to be empty, and the defaults mentioned below apply. In general this means that the kernel tries to configure everything using both ! RARP and BOOTP (depending on what has been enabled during kernel confi- ! guration, and if both what protocol answer got in first). <client-ip> IP address of the client. If empty, the address will either ! be determined by RARP or BOOTP. What protocol is used de- ! pends on what has been enabled during kernel configuration and on the <autoconf> parameter. If this parameter is not ! empty, neither RARP nor BOOTP will be used. <server-ip> IP address of the NFS server. If RARP is used to determine --- 89,100 ---- assumed to be empty, and the defaults mentioned below apply. In general this means that the kernel tries to configure everything using both ! RARP and DHCP/BOOTP (depending on what has been enabled during kernel ! configuration, and if both what protocol answer got in first). <client-ip> IP address of the client. If empty, the address will either ! be determined by RARP or DHCP/BOOTP. What protocol is used ! depends on what has been enabled during kernel configuration and on the <autoconf> parameter. If this parameter is not ! empty, neither RARP nor DHCP/BOOTP will be used. <server-ip> IP address of the NFS server. If RARP is used to determine *************** *** 104,121 **** here (or leave it blank), and specify your NFS server in the `nfsroot' parameter (see above). If this entry is blank ! the address of the server is used which answered the RARP ! or BOOTP request. <gw-ip> IP address of a gateway if the server is on a different subnet. If this entry is empty no gateway is used and the ! server is assumed to be on the local network, unless a ! value has been received by BOOTP. <netmask> Netmask for local network interface. If this is empty, the netmask is derived from the client IP address assuming ! classful addressing, unless overridden in BOOTP reply. <hostname> Name of the client. If empty, the client IP address is ! used in ASCII notation, or the value received by BOOTP. <device> Name of network device to use. If this is empty, all --- 104,123 ---- here (or leave it blank), and specify your NFS server in the `nfsroot' parameter (see above). If this entry is blank ! the address of the server is used which answered the RARP, ! or the server address in the DHCP/BOOTP reply. (Note that ! this may *not* be the DHCP/BOOTP server itself.) <gw-ip> IP address of a gateway if the server is on a different subnet. If this entry is empty no gateway is used and the ! server is assumed to be on the local network, unless ! overridden by DHCP/BOOTP reply. <netmask> Netmask for local network interface. If this is empty, the netmask is derived from the client IP address assuming ! classful addressing, unless overridden by DHCP/BOOTP reply. <hostname> Name of the client. If empty, the client IP address is ! used in ASCII notation, unless overridden by DHCP/BOOTP ! reply. <device> Name of network device to use. If this is empty, all *************** *** 124,132 **** only one device, you can safely leave this blank. ! <autoconf> Method to use for autoconfiguration. If this is either ! 'rarp' or 'bootp', the specified protocol is used. ! If the value is 'both' or empty, both protocols are used ! so far as they have been enabled during kernel configura- ! tion. 'off' means no autoconfiguration. The <autoconf> parameter can appear alone as the value to the `ip' --- 126,136 ---- only one device, you can safely leave this blank. ! <autoconf> Method to use for autoconfiguration. If this is 'dhcp', ! 'bootp', or 'rarp', the specified protocol is used. If ! the value is 'both' or empty, then both BOOTP and RARP are ! used so far as they are configured into the kernel. (For ! backward compatibility, DHCP will not be used in this ! case, unless BOOTP is not configured.) If the value is ! 'off', no autoconfiguration of any kind occurs. The <autoconf> parameter can appear alone as the value to the `ip' *************** *** 162,171 **** You can then remove the dummy device /dev/boot255 again. There is no real device available for it. The other two kernel command line parameters cannot be substi- ! tuted with rdev. Therefore, using this method the kernel will ! by default use RARP and/or BOOTP, and if it gets an answer via RARP will mount the directory /tftpboot/<client-ip>/ as its ! root. If it got a BOOTP answer the directory name in that answer ! is used. --- 166,176 ---- You can then remove the dummy device /dev/boot255 again. There is no real device available for it. + The other two kernel command line parameters cannot be substi- ! tuted with rdev. Therefore, using this method the kernel will by ! default use DHCP/BOOTP and/or RARP, and if it gets an answer via RARP will mount the directory /tftpboot/<client-ip>/ as its ! root. If it gets a DHCP/BOOTP answer the directory name in that ! answer is used.
Index: net/ipv4/Config.in *************** *** 18,21 **** --- 18,22 ---- bool 'IP: kernel level autoconfiguration' CONFIG_IP_PNP if [ "$CONFIG_IP_PNP" = "y" ]; then + bool ' DHCP support' CONFIG_IP_PNP_DHCP bool ' BOOTP support' CONFIG_IP_PNP_BOOTP bool ' RARP support' CONFIG_IP_PNP_RARP
Index: net/ipv4/ipconfig.c *************** *** 2,7 **** * $Id: ipconfig.c,v 1.20.2.1 1999/06/28 11:33:27 davem Exp $ * ! * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied ! * information to configure own IP address and routes. * * Copyright (C) 1996--1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz> --- 2,7 ---- * $Id: ipconfig.c,v 1.20.2.1 1999/06/28 11:33:27 davem Exp $ * ! * Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or ! * user-supplied information to configure own IP address and routes. * * Copyright (C) 1996--1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz> *************** *** 13,16 **** --- 13,20 ---- * of misusing the IP layer. num_bugs_causing_wrong_arp_replies--; * -- MJ, December 1998 + * + * DHCP support added. To users this looks like a whole separate + * protocol, but we know it's just a bag on the side of BOOTP. + * -- Chip Salzenberg <chip@valinux.com>, Dec. 1999 */ *************** *** 21,26 **** #include <linux/sched.h> #include <linux/random.h> - #include <linux/init.h> #include <linux/utsname.h> #include <linux/in.h> #include <linux/if.h> --- 25,31 ---- #include <linux/sched.h> #include <linux/random.h> #include <linux/utsname.h> + #include <linux/proc_fs.h> + #include <linux/init.h> #include <linux/in.h> #include <linux/if.h> *************** *** 50,54 **** #endif ! /* Define the timeout for waiting for a RARP/BOOTP reply */ #define CONF_BASE_TIMEOUT (HZ*5) /* Initial timeout: 5 seconds */ #define CONF_RETRIES 10 /* 10 retries */ --- 55,72 ---- #endif ! #if defined(CONFIG_IP_PNP_DHCP) ! #define IPCONFIG_DHCP ! #endif ! #if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_DHCP) ! #define IPCONFIG_BOOTP ! #endif ! #if defined(CONFIG_IP_PNP_RARP) ! #define IPCONFIG_RARP ! #endif ! #if defined(IPCONFIG_BOOTP) || defined(IPCONFIG_RARP) ! #define IPCONFIG_DYNAMIC ! #endif ! ! /* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */ #define CONF_BASE_TIMEOUT (HZ*5) /* Initial timeout: 5 seconds */ #define CONF_RETRIES 10 /* 10 retries */ *************** *** 57,95 **** #define CONF_TIMEOUT_MAX (HZ*30) /* Maximum allowed timeout */ - /* IP configuration */ - static char user_dev_name[IFNAMSIZ] __initdata = { 0, };/* Name of user-selected boot device */ - u32 ic_myaddr __initdata = INADDR_NONE; /* My IP address */ - u32 ic_servaddr __initdata = INADDR_NONE; /* Server IP address */ - u32 ic_gateway __initdata = INADDR_NONE; /* Gateway IP address */ - u32 ic_netmask __initdata = INADDR_NONE; /* Netmask for local subnet */ - int ic_enable __initdata = 1; /* Automatic IP configuration enabled */ - int ic_host_name_set __initdata = 0; /* Host name configured manually */ - int ic_set_manually __initdata = 0; /* IPconfig parameters set manually */ - u32 root_server_addr __initdata = INADDR_NONE; /* Address of boot server */ - u8 root_server_path[256] __initdata = { 0, }; /* Path to mount as root */ ! #if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP) ! #define CONFIG_IP_PNP_DYNAMIC ! static int ic_proto_enabled __initdata = 0 /* Protocols enabled */ ! #ifdef CONFIG_IP_PNP_BOOTP | IC_BOOTP #endif ! #ifdef CONFIG_IP_PNP_RARP | IC_RARP #endif ; - static int ic_got_reply __initdata = 0; /* Protocol(s) we got reply from */ ! #else ! static int ic_proto_enabled __initdata = 0; ! #endif static int ic_proto_have_if __initdata = 0; /* * Network devices --- 75,133 ---- #define CONF_TIMEOUT_MAX (HZ*30) /* Maximum allowed timeout */ ! /* ! * Public IP configuration ! */ ! int ic_enable __initdata = 1; /* Automatic IP cfg enabled? */ ! /* Protocol choice */ ! static int ic_proto_enabled __initdata = 0 ! #ifdef IPCONFIG_BOOTP | IC_BOOTP #endif ! #ifdef CONFIG_IP_PNP_DHCP ! | IC_USE_DHCP ! #endif ! #ifdef IPCONFIG_RARP | IC_RARP #endif ; ! int ic_host_name_set __initdata = 0; /* Host name set by us? */ ! u32 ic_myaddr __initdata = INADDR_NONE; /* My IP address */ ! u32 ic_netmask __initdata = INADDR_NONE; /* Netmask for local subnet */ ! u32 ic_gateway __initdata = INADDR_NONE; /* Gateway IP address */ ! u32 ic_servaddr __initdata = INADDR_NONE; /* Boot server IP address */ + u32 root_server_addr __initdata = INADDR_NONE; /* Address of NFS server */ + u8 root_server_path[256] __initdata = { 0, }; /* Path to mount as root */ + + /* Persistent data: */ + + int ic_proto_used = 0; /* Protocol used, if any */ + u32 ic_nameserver = INADDR_NONE; /* DNS Server IP address */ + u8 ic_domain[64] = { 0, }; /* DNS (not NIS) domain name */ + + /* + * Private state. + */ + + /* Name of user-selected boot device */ + static char user_dev_name[IFNAMSIZ] __initdata = { 0, }; + + /* Protocols supported by available interfaces */ static int ic_proto_have_if __initdata = 0; + #ifdef IPCONFIG_DYNAMIC + static int ic_got_reply = 0; /* Protocol(s) we got reply from */ + #endif + #ifdef IPCONFIG_DHCP + static int ic_dhcp_msgtype __initdata = 0; /* Last incoming msg type */ + #endif + + /* * Network devices *************** static int __init ic_open_devs(void) *** 122,126 **** able |= IC_BOOTP; else ! printk(KERN_WARNING "BOOTP: Ignoring device %s, MTU %d too small", dev->name, dev->mtu); if (!(dev->flags & IFF_NOARP)) able |= IC_RARP; --- 160,164 ---- able |= IC_BOOTP; else ! printk(KERN_WARNING "DHCP/BOOTP: Ignoring device %s, MTU %d too small", dev->name, dev->mtu); if (!(dev->flags & IFF_NOARP)) able |= IC_RARP; *************** static int __init ic_defaults(void) *** 300,304 **** */ ! #ifdef CONFIG_IP_PNP_RARP static int ic_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt); --- 338,342 ---- */ ! #ifdef IPCONFIG_RARP static int ic_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt); *************** static void __init ic_rarp_send(void) *** 400,407 **** /* ! * BOOTP support. */ ! #ifdef CONFIG_IP_PNP_BOOTP struct bootp_pkt { /* BOOTP packet format */ --- 438,445 ---- /* ! * DHCP/BOOTP support. */ ! #ifdef IPCONFIG_BOOTP struct bootp_pkt { /* BOOTP packet format */ *************** struct bootp_pkt { /* BOOTP packet form *** 417,434 **** u32 client_ip; /* Client's IP address if known */ u32 your_ip; /* Assigned IP address */ ! u32 server_ip; /* Server's IP address */ u32 relay_ip; /* IP address of BOOTP relay */ u8 hw_addr[16]; /* Client's HW address */ ! u8 serv_name[64]; /* Server host name */ ! u8 boot_file[128]; /* Name of boot file */ ! u8 vendor_area[128]; /* Area for extensions */ }; ! #define BOOTP_REQUEST 1 ! #define BOOTP_REPLY 2 static u32 ic_bootp_xid; ! static int ic_bootp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt); static struct packet_type bootp_packet_type __initdata = { --- 455,484 ---- u32 client_ip; /* Client's IP address if known */ u32 your_ip; /* Assigned IP address */ ! u32 server_ip; /* (Next, e.g. NFS) Server's IP address */ u32 relay_ip; /* IP address of BOOTP relay */ u8 hw_addr[16]; /* Client's HW address */ ! char server_name[64]; /* Server host name */ ! char boot_file[128]; /* Name of boot file */ ! u8 exten[312]; /* DHCP options / BOOTP vendor extensions */ }; ! /* packet ops */ ! #define BOOTP_REQUEST 1 ! #define BOOTP_REPLY 2 ! ! /* DHCP message types */ ! #define DHCPDISCOVER 1 ! #define DHCPOFFER 2 ! #define DHCPREQUEST 3 ! #define DHCPDECLINE 4 ! #define DHCPACK 5 ! #define DHCPNAK 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); static struct packet_type bootp_packet_type __initdata = { *************** static struct packet_type bootp_packet_t *** 442,453 **** /* ! * Initialize BOOTP extension fields in the request. */ ! static void __init ic_bootp_init_ext(u8 *e) { ! *e++ = 99; /* RFC1048 Magic Cookie */ ! *e++ = 130; ! *e++ = 83; ! *e++ = 99; *e++ = 1; /* Subnet mask request */ *e++ = 4; --- 492,556 ---- /* ! * Initialize DHCP/BOOTP extension fields in the request. */ ! ! static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 }; ! ! #ifdef IPCONFIG_DHCP ! ! static void __init ! ic_dhcp_init_options(u8 *options) { ! u8 msgtype = ((ic_dhcp_msgtype == DHCPOFFER) ! ? DHCPREQUEST : DHCPDISCOVER); ! u8 *e = options; ! ! #ifdef IPCONFIG_DEBUG ! printk("DHCP: Sending message type %d\n", msgtype); ! #endif ! ! memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ ! e += 4; ! ! *e++ = 53; /* DHCP message type */ ! *e++ = 1; ! *e++ = msgtype; ! ! if (msgtype == DHCPREQUEST) { ! *e++ = 50; /* Requested IP address */ ! *e++ = 4; ! memcpy(e, &ic_myaddr, 4); ! e += 4; ! } ! ! /* always? */ ! { ! static const u8 ic_req_params[] = { ! 1, /* Subnet mask */ ! 3, /* Default gateway */ ! 6, /* DNS server */ ! 12, /* Host name */ ! 15, /* Domain name */ ! 17, /* Boot path */ ! 40, /* NIS domain name */ ! }; ! ! *e++ = 55; /* Parameter request list */ ! *e++ = sizeof(ic_req_params); ! memcpy(e, ic_req_params, sizeof(ic_req_params)); ! e += sizeof(ic_req_params); ! } ! ! *e++ = 255; /* End of the list */ ! } ! ! #endif /* IPCONFIG_DHCP */ ! ! static void __init ! ic_bootp_init_ext(u8 *ext) ! { ! u8 *e = ext; ! memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ ! e += 4; *e++ = 1; /* Subnet mask request */ *e++ = 4; *************** static void __init ic_bootp_init_ext(u8 *** 456,459 **** --- 559,565 ---- *e++ = 4; e += 4; + *e++ = 5; /* Name server reqeust */ + *e++ = 8; + e += 8; *e++ = 12; /* Host name request */ *e++ = 32; *************** static void __init ic_bootp_init_ext(u8 *** 463,479 **** e += 32; *e++ = 17; /* Boot path */ ! *e++ = 32; ! e += 32; ! *e = 255; /* End of the list */ } /* ! * Initialize the BOOTP mechanism. */ ! static inline void ic_bootp_init(void) { get_random_bytes(&ic_bootp_xid, sizeof(u32)); ! DBG(("BOOTP: XID=%08x\n", ic_bootp_xid)); dev_add_pack(&bootp_packet_type); } --- 569,586 ---- e += 32; *e++ = 17; /* Boot path */ ! *e++ = 40; ! e += 40; ! *e++ = 255; /* End of the list */ } /* ! * Initialize the DHCP/BOOTP mechanism. */ ! 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); } *************** static inline void ic_bootp_init(void) *** 481,487 **** /* ! * BOOTP cleanup. */ ! static inline void ic_bootp_cleanup(void) { dev_remove_pack(&bootp_packet_type); --- 588,595 ---- /* ! * DHCP/BOOTP cleanup. */ ! static inline void ! ic_bootp_cleanup(void) { dev_remove_pack(&bootp_packet_type); *************** static inline void ic_bootp_cleanup(void *** 490,496 **** /* ! * Send BOOTP request to single interface. */ ! static void __init ic_bootp_send_if(struct ic_device *d, u32 jiffies) { struct device *dev = d->dev; --- 598,605 ---- /* ! * Send DHCP/BOOTP request to single interface. */ ! static void __init ! ic_bootp_send_if(struct ic_device *d, u32 jiffies) { struct device *dev = d->dev; *************** static void __init ic_bootp_send_if(stru *** 525,536 **** /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */ ! /* Construct BOOTP header */ b->op = BOOTP_REQUEST; b->htype = dev->type; b->hlen = dev->addr_len; memcpy(b->hw_addr, dev->dev_addr, dev->addr_len); b->secs = htons(jiffies / HZ); b->xid = ic_bootp_xid; ! ic_bootp_init_ext(b->vendor_area); /* Chain packet down the line... */ --- 634,654 ---- /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */ ! /* Construct DHCP/BOOTP header */ b->op = BOOTP_REQUEST; b->htype = dev->type; b->hlen = dev->addr_len; + b->your_ip = INADDR_NONE; + 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; ! ! /* add DHCP options or BOOTP extensions */ ! #ifdef IPCONFIG_DHCP ! if (ic_proto_enabled & IC_USE_DHCP) ! ic_dhcp_init_options(b->exten); ! else ! #endif ! ic_bootp_init_ext(b->exten); /* Chain packet down the line... */ *************** static void __init ic_bootp_send_if(stru *** 545,549 **** /* ! * Send BOOTP requests to all interfaces. */ static void __init ic_bootp_send(u32 jiffies) --- 663,667 ---- /* ! * Send DHCP/BOOTP requests to all interfaces. */ static void __init ic_bootp_send(u32 jiffies) *************** static void __init ic_bootp_send(u32 jif *** 551,557 **** struct ic_device *d; ! for(d=ic_first_dev; d; d=d->next) if (d->able & IC_BOOTP) ic_bootp_send_if(d, jiffies); } --- 669,676 ---- struct ic_device *d; ! for(d = ic_first_dev; d; d=d->next) { if (d->able & IC_BOOTP) ic_bootp_send_if(d, jiffies); + } } *************** static int __init ic_bootp_string(char * *** 566,577 **** if (len > max-1) len = max-1; ! strncpy(dest, src, len); dest[len] = '\0'; return 1; } /* ! * Process BOOTP extension. */ static void __init ic_do_bootp_ext(u8 *ext) --- 685,695 ---- if (len > max-1) len = max-1; ! memcpy(dest, src, len); dest[len] = '\0'; return 1; } /* ! * Process BOOTP extensions. */ static void __init ic_do_bootp_ext(u8 *ext) *************** static void __init ic_do_bootp_ext(u8 *e *** 580,584 **** u8 *c; ! printk("BOOTP: Got extension %02x",*ext); for(c=ext+2; c<ext+2+ext[1]; c++) printk(" %02x", *c); --- 698,702 ---- u8 *c; ! printk("DHCP/BOOTP: Got extension %d:",*ext); for(c=ext+2; c<ext+2+ext[1]; c++) printk(" %02x", *c); *************** static void __init ic_do_bootp_ext(u8 *e *** 595,604 **** memcpy(&ic_gateway, ext+1, 4); break; case 12: /* Host name */ ic_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN); ic_host_name_set = 1; break; ! case 40: /* NIS Domain name */ ! ic_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN); break; case 17: /* Root path */ --- 713,726 ---- memcpy(&ic_gateway, ext+1, 4); break; + case 6: /* DNS server */ + if (ic_nameserver == INADDR_NONE) + memcpy(&ic_nameserver, ext+1, 4); + break; case 12: /* Host name */ ic_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN); ic_host_name_set = 1; break; ! case 15: /* Domain name (DNS) */ ! ic_bootp_string(ic_domain, ext+1, *ext, sizeof(ic_domain)); break; case 17: /* Root path */ *************** static void __init ic_do_bootp_ext(u8 *e *** 606,609 **** --- 728,734 ---- ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path)); break; + case 40: /* NIS domain name (_not_ DNS) */ + ic_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN); + break; } } *************** static int __init ic_bootp_recv(struct s *** 638,642 **** /* Fragments are not supported */ if (h->frag_off & htons(IP_OFFSET|IP_MF)) { ! printk(KERN_ERR "BOOTP: Ignoring fragmented reply.\n"); goto drop; } --- 763,767 ---- /* Fragments are not supported */ if (h->frag_off & htons(IP_OFFSET|IP_MF)) { ! printk(KERN_ERR "DHCP/BOOTP: Ignoring fragmented reply.\n"); goto drop; } *************** static int __init ic_bootp_recv(struct s *** 651,681 **** } - /* Extract basic fields */ - ic_myaddr = b->your_ip; - ic_servaddr = b->server_ip; ic_got_reply = IC_BOOTP; ic_dev = dev; /* Parse extensions */ ! if (b->vendor_area[0] == 99 && /* Check magic cookie */ ! b->vendor_area[1] == 130 && ! b->vendor_area[2] == 83 && ! b->vendor_area[3] == 99) { ! u8 *ext = &b->vendor_area[4]; u8 *end = (u8 *) b + ntohs(b->iph.tot_len); while (ext < end && *ext != 0xff) { ! if (*ext == 0) /* Padding */ ! ext++; ! else { ! u8 *opt = ext; ! ext += ext[1] + 2; ! if (ext <= end) ! ic_do_bootp_ext(opt); } } } if (ic_gateway == INADDR_NONE && b->relay_ip) ic_gateway = b->relay_ip; drop: --- 776,857 ---- } ic_got_reply = IC_BOOTP; ic_dev = dev; /* Parse extensions */ ! if (!memcmp(b->exten, ic_bootp_cookie, 4)) { u8 *end = (u8 *) b + ntohs(b->iph.tot_len); + u8 *ext; + + #ifdef IPCONFIG_DHCP + + u32 server_id = INADDR_NONE; + ic_dhcp_msgtype = 0; + + ext = &b->exten[4]; while (ext < end && *ext != 0xff) { ! u8 *opt = ext++; ! if (*opt == 0) /* Padding */ ! continue; ! ext += *ext + 1; ! if (ext >= end) ! break; ! switch (*opt) { ! case 53: /* Message type */ ! if (opt[1]) ! ic_dhcp_msgtype = opt[2]; ! break; ! case 54: /* Server ID (IP address) */ ! if (opt[1] >= 4) ! memcpy(&server_id, opt + 2, 4); ! break; } } + + #ifdef IPCONFIG_DEBUG + printk("DHCP: Got message type %d\n", ic_dhcp_msgtype); + #endif + + switch (ic_dhcp_msgtype) { + case DHCPOFFER: + /* Let's accept that offer. */ + ic_myaddr = b->your_ip; + ic_servaddr = server_id; + #ifdef IPCONFIG_DEBUG + printk("DHCP: Offered address %s", in_ntoa(ic_myaddr)); + printk(" by server %s\n", in_ntoa(ic_servaddr)); + #endif + goto drop; + + case DHCPACK: + /* Yeah! */ + break; + + default: + /* Urque. Forget it*/ + ic_myaddr = INADDR_NONE; + ic_servaddr = INADDR_NONE; + goto drop; + } + + #endif /* IPCONFIG_DHCP */ + + ext = &b->exten[4]; + while (ext < end && *ext != 0xff) { + u8 *opt = ext++; + if (*opt == 0) /* Padding */ + continue; + ext += *ext + 1; + if (ext < end) + ic_do_bootp_ext(opt); + } } + ic_myaddr = b->your_ip; + ic_servaddr = b->server_ip; if (ic_gateway == INADDR_NONE && b->relay_ip) ic_gateway = b->relay_ip; + if (ic_nameserver == INADDR_NONE) + ic_nameserver = ic_servaddr; drop: *************** drop: *** 689,696 **** /* ! * Dynamic IP configuration -- BOOTP and RARP. */ ! #ifdef CONFIG_IP_PNP_DYNAMIC static int __init ic_dynamic(void) --- 865,872 ---- /* ! * Dynamic IP configuration -- DHCP, BOOTP, RARP. */ ! #ifdef IPCONFIG_DYNAMIC static int __init ic_dynamic(void) *************** static int __init ic_dynamic(void) *** 699,710 **** unsigned long timeout, jiff; unsigned long start_jiffies; - int do_rarp = ic_proto_have_if & IC_RARP; int do_bootp = ic_proto_have_if & IC_BOOTP; /* ! * If neither BOOTP nor RARP was selected, return with an error. This ! * routine gets only called when some pieces of information are mis- ! * sing, and without BOOTP and RARP we are not able to get that in- ! * formation. */ if (!ic_proto_enabled) { --- 875,885 ---- unsigned long timeout, jiff; unsigned long start_jiffies; int do_bootp = ic_proto_have_if & IC_BOOTP; + int do_rarp = ic_proto_have_if & IC_RARP; /* ! * If none of DHCP/BOOTP/RARP was selected, return with an error. ! * This routine gets only called when some pieces of information ! * are missing, and without BOOTP and RARP we are unable to get it. */ if (!ic_proto_enabled) { *************** static int __init ic_dynamic(void) *** 713,722 **** } ! #ifdef CONFIG_IP_PNP_BOOTP if ((ic_proto_enabled ^ ic_proto_have_if) & IC_BOOTP) ! printk(KERN_ERR "BOOTP: No suitable device found.\n"); #endif ! ! #ifdef CONFIG_IP_PNP_RARP if ((ic_proto_enabled ^ ic_proto_have_if) & IC_RARP) printk(KERN_ERR "RARP: No suitable device found.\n"); --- 888,896 ---- } ! #ifdef IPCONFIG_BOOTP if ((ic_proto_enabled ^ ic_proto_have_if) & IC_BOOTP) ! printk(KERN_ERR "DHCP/BOOTP: No suitable device found.\n"); #endif ! #ifdef IPCONFIG_RARP if ((ic_proto_enabled ^ ic_proto_have_if) & IC_RARP) printk(KERN_ERR "RARP: No suitable device found.\n"); *************** static int __init ic_dynamic(void) *** 728,741 **** /* ! * Setup RARP and BOOTP protocols */ ! #ifdef CONFIG_IP_PNP_RARP ! if (do_rarp) ! ic_rarp_init(); ! #endif ! #ifdef CONFIG_IP_PNP_BOOTP if (do_bootp) ic_bootp_init(); #endif /* --- 902,915 ---- /* ! * Setup protocols */ ! #ifdef IPCONFIG_BOOTP if (do_bootp) ic_bootp_init(); #endif + #ifdef IPCONFIG_RARP + if (do_rarp) + ic_rarp_init(); + #endif /* *************** static int __init ic_dynamic(void) *** 748,754 **** */ printk(KERN_NOTICE "Sending %s%s%s requests...", ! do_bootp ? "BOOTP" : "", ! do_bootp && do_rarp ? " and " : "", ! do_rarp ? "RARP" : ""); start_jiffies = jiffies; retries = CONF_RETRIES; --- 922,929 ---- */ 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; retries = CONF_RETRIES; *************** static int __init ic_dynamic(void) *** 756,779 **** timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM); for(;;) { ! #ifdef CONFIG_IP_PNP_BOOTP if (do_bootp) ic_bootp_send(jiffies - start_jiffies); #endif ! #ifdef CONFIG_IP_PNP_RARP if (do_rarp) ic_rarp_send(); #endif printk("."); jiff = jiffies + timeout; while (jiffies < jiff && !ic_got_reply) ; if (ic_got_reply) { printk(" OK\n"); break; } if (! --retries) { printk(" timed out!\n"); break; } timeout = timeout CONF_TIMEOUT_MULT; if (timeout > CONF_TIMEOUT_MAX) --- 931,968 ---- timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM); for(;;) { ! #ifdef IPCONFIG_BOOTP if (do_bootp) ic_bootp_send(jiffies - start_jiffies); #endif ! #ifdef IPCONFIG_RARP if (do_rarp) ic_rarp_send(); #endif printk("."); + jiff = jiffies + timeout; while (jiffies < jiff && !ic_got_reply) ; + #ifdef IPCONFIG_DHCP + if ((ic_got_reply & IC_BOOTP) + && (ic_proto_enabled & IC_USE_DHCP) + && ic_dhcp_msgtype != DHCPACK) + { + printk(","); + ic_got_reply = 0; + continue; + } + #endif /* IPCONFIG_DHCP */ + if (ic_got_reply) { printk(" OK\n"); break; } + if (! --retries) { printk(" timed out!\n"); break; } + timeout = timeout CONF_TIMEOUT_MULT; if (timeout > CONF_TIMEOUT_MAX) *************** static int __init ic_dynamic(void) *** 781,792 **** } ! #ifdef CONFIG_IP_PNP_RARP ! if (do_rarp) ! ic_rarp_cleanup(); ! #endif ! #ifdef CONFIG_IP_PNP_BOOTP if (do_bootp) ic_bootp_cleanup(); #endif if (!ic_got_reply) --- 970,981 ---- } ! #ifdef IPCONFIG_BOOTP if (do_bootp) ic_bootp_cleanup(); #endif + #ifdef IPCONFIG_RARP + if (do_rarp) + ic_rarp_cleanup(); + #endif if (!ic_got_reply) *************** static int __init ic_dynamic(void) *** 794,799 **** printk("IP-Config: Got %s answer from %s, ", ! (ic_got_reply & IC_BOOTP) ? "BOOTP" : "RARP", ! in_ntoa(ic_servaddr)); printk("my address is %s\n", in_ntoa(ic_myaddr)); --- 983,989 ---- printk("IP-Config: Got %s answer from %s, ", ! ((ic_got_reply & IC_RARP) ? "RARP" ! : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"), ! in_ntoa(ic_servaddr)); printk("my address is %s\n", in_ntoa(ic_myaddr)); *************** static int __init ic_dynamic(void) *** 801,805 **** } ! #endif /* --- 991,1028 ---- } ! #endif /* IPCONFIG_DYNAMIC */ ! ! #ifdef CONFIG_PROC_FS ! ! static int pnp_get_info(char *buffer, char **start, ! off_t offset, int length, int dummy) ! { ! int len; ! ! if (ic_proto_used & IC_PROTO) ! sprintf(buffer, "#PROTO: %s\n", ! (ic_proto_used & IC_RARP) ? "RARP" ! : (ic_proto_used & IC_USE_DHCP) ? "DHCP" : "BOOTP"); ! else ! strcpy(buffer, "#MANUAL\n"); ! len = strlen(buffer); ! ! if (ic_domain[0]) ! len += sprintf(buffer + len, ! "domain %s\n", ic_domain); ! if (ic_nameserver != INADDR_NONE) ! len += sprintf(buffer + len, ! "nameserver %s\n", in_ntoa(ic_nameserver)); ! ! if (offset > len) ! offset = len; ! *start = buffer + offset; ! ! if (offset + length > len) ! length = len - offset; ! return length; ! } ! ! #endif /* CONFIG_PROC_FS */ /* *************** static int __init ic_dynamic(void) *** 809,812 **** --- 1032,1044 ---- int __init ip_auto_config(void) { + #ifdef CONFIG_PROC_FS + proc_net_register(&(struct proc_dir_entry) { + PROC_NET_PNP, 3, "pnp", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_net_inode_operations, + pnp_get_info + }); + #endif /* CONFIG_PROC_FS */ + if (!ic_enable) return 0; *************** int __init ip_auto_config(void) *** 828,833 **** (root_server_addr == INADDR_NONE && ic_servaddr == INADDR_NONE) || #endif ! ic_first_dev->next) { ! #ifdef CONFIG_IP_PNP_DYNAMIC if (ic_dynamic() < 0) { printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n"); --- 1060,1067 ---- (root_server_addr == INADDR_NONE && ic_servaddr == INADDR_NONE) || #endif ! ic_first_dev->next) ! { ! ! #ifdef IPCONFIG_DYNAMIC if (ic_dynamic() < 0) { printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n"); *************** int __init ip_auto_config(void) *** 839,845 **** ic_close_devs(); return -1; ! #endif } else { ! ic_dev = ic_first_dev->dev; /* Device selected manually or only one device -> use it */ } --- 1073,1081 ---- ic_close_devs(); return -1; ! #endif /* IPCONFIG_DYNAMIC */ ! } else { ! /* Device selected manually or only one device -> use it */ ! ic_dev = ic_first_dev->dev; } *************** int __init ip_auto_config(void) *** 858,865 **** return -1; ! DBG(("IP-Config: device=%s, local=%08x, server=%08x, boot=%08x, gw=%08x, mask=%08x\n", ! ic_dev->name, ic_myaddr, ic_servaddr, root_server_addr, ic_gateway, ic_netmask)); ! DBG(("IP-Config: host=%s, domain=%s, path=`%s'\n", system_utsname.nodename, ! system_utsname.domainname, root_server_path)); return 0; } --- 1094,1115 ---- return -1; ! /* ! * Record which protocol was actually used. ! */ ! ic_proto_used = ic_got_reply | (ic_proto_enabled & IC_USE_DHCP); ! ! #ifdef IPCONFIG_DEBUG ! printk("IP-Config: device=%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)); ! printk(",\n host=%s, domain=%s, nis-domain=%s", ! system_utsname.nodename, ic_domain, system_utsname.domainname); ! printk(",\n bootserver=%s", in_ntoa(ic_servaddr)); ! printk(", rootserver=%s", in_ntoa(root_server_addr)); ! printk(", rootpath=%s", root_server_path); ! printk("\n"); ! #endif ! return 0; } *************** int __init ip_auto_config(void) *** 870,874 **** * the following order: * ! * <client-ip>:<server-ip>:<gw-ip>:<netmask>:<host name>:<device>:<bootp|rarp> * * Any of the fields can be empty which means to use a default value: --- 1120,1124 ---- * the following order: * ! * <client-ip>:<server-ip>:<gw-ip>:<netmask>:<host name>:<device>:<PROTO> * * Any of the fields can be empty which means to use a default value: *************** int __init ip_auto_config(void) *** 881,895 **** * by BOOTP * <device> - use all available devices ! * <bootp|rarp|both|off> - use both protocols to determine my own address */ static int __init ic_proto_name(char *name) { ! if (!strcmp(name, "off")) { ic_proto_enabled = 0; return 1; } #ifdef CONFIG_IP_PNP_BOOTP else if (!strcmp(name, "bootp")) { ! ic_proto_enabled &= ~IC_RARP; return 1; } --- 1131,1154 ---- * 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 */ static int __init ic_proto_name(char *name) { ! if (!strcmp(name, "off") || !strcmp(name, "none")) { ic_proto_enabled = 0; return 1; } + #ifdef CONFIG_IP_PNP_DHCP + else if (!strcmp(name, "dhcp")) { + ic_proto_enabled &= ~IC_RARP; + return 1; + } + #endif #ifdef CONFIG_IP_PNP_BOOTP else if (!strcmp(name, "bootp")) { ! ic_proto_enabled &= ~(IC_RARP | IC_USE_DHCP); return 1; } *************** static int __init ic_proto_name(char *na *** 897,906 **** #ifdef CONFIG_IP_PNP_RARP else if (!strcmp(name, "rarp")) { ! ic_proto_enabled &= ~IC_BOOTP; return 1; } #endif ! #ifdef CONFIG_IP_PNP_DYNAMIC else if (!strcmp(name, "both")) { return 1; } --- 1156,1166 ---- #ifdef CONFIG_IP_PNP_RARP else if (!strcmp(name, "rarp")) { ! ic_proto_enabled &= ~(IC_BOOTP | IC_USE_DHCP); return 1; } #endif ! #ifdef IPCONFIG_DYNAMIC else if (!strcmp(name, "both")) { + ic_proto_enabled &= ~IC_USE_DHCP; /* backward compat :-( */ return 1; } *************** void __init ip_auto_config_setup(char *a *** 914,919 **** int num = 0; ! ic_set_manually = 1; ! if (!strcmp(addrs, "off")) { ic_enable = 0; return; --- 1174,1178 ---- int num = 0; ! if (!strcmp(addrs, "off") || !strcmp(addrs, "none")) { ic_enable = 0; return;
-- Chip Salzenberg - a.k.a. - <chip@valinux.com> "Fleagal. Bingo. Drooper. Snork. They're cops." //MST3K
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |