📄 ipconfig.c
字号:
ic_got_reply = IC_RARP;drop: /* Show's over. Nothing to see here. */ spin_unlock(&ic_recv_lock); /* Throw the packet out. */ kfree_skb(skb); return 0;}/* * Send RARP request packet over a signle interface. */static void __init ic_rarp_send_if(struct ic_device *d){ struct net_device *dev = d->dev; arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL, dev->dev_addr, dev->dev_addr);}#endif/* * DHCP/BOOTP support. */#ifdef IPCONFIG_BOOTPstruct bootp_pkt { /* BOOTP packet format */ struct iphdr iph; /* IP header */ struct udphdr udph; /* UDP header */ u8 op; /* 1=request, 2=reply */ u8 htype; /* HW address type */ u8 hlen; /* HW address length */ u8 hops; /* Used only by gateways */ u32 xid; /* Transaction ID */ u16 secs; /* Seconds since we started */ u16 flags; /* Just what it says */ 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 */ u8 serv_name[64]; /* Server host name */ u8 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 8static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);static struct packet_type bootp_packet_type __initdata = { type: __constant_htons(ETH_P_IP), func: ic_bootp_recv,};/* * Initialize DHCP/BOOTP extension fields in the request. */static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 };#ifdef IPCONFIG_DHCPstatic void __initic_dhcp_init_options(u8 *options){ u8 mt = ((ic_servaddr == INADDR_NONE) ? DHCPDISCOVER : DHCPREQUEST); u8 *e = options;#ifdef IPCONFIG_DEBUG printk("DHCP: Sending message type %d\n", mt);#endif memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ e += 4; *e++ = 53; /* DHCP message type */ *e++ = 1; *e++ = mt; if (mt == DHCPREQUEST) { *e++ = 54; /* Server ID (IP address) */ *e++ = 4; memcpy(e, &ic_servaddr, 4); e += 4; *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 *e){ memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ e += 4; *e++ = 1; /* Subnet mask request */ *e++ = 4; e += 4; *e++ = 3; /* Default gateway request */ *e++ = 4; e += 4; *e++ = 5; /* Name server reqeust */ *e++ = 8; e += 8; *e++ = 12; /* Host name request */ *e++ = 32; e += 32; *e++ = 40; /* NIS Domain name request */ *e++ = 32; e += 32; *e++ = 17; /* Boot path */ *e++ = 40; e += 40; *e++ = 57; /* set extension buffer size for reply */ *e++ = 2; *e++ = 1; /* 128+236+8+20+14, see dhcpd sources */ *e++ = 150; *e++ = 255; /* End of the list */}/* * Initialize the DHCP/BOOTP mechanism. */static inline void ic_bootp_init(void){ dev_add_pack(&bootp_packet_type);}/* * DHCP/BOOTP cleanup. */static inline void ic_bootp_cleanup(void){ dev_remove_pack(&bootp_packet_type);}/* * Send DHCP/BOOTP request to single interface. */static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_diff){ struct net_device *dev = d->dev; struct sk_buff *skb; struct bootp_pkt *b; int hh_len = (dev->hard_header_len + 15) & ~15; struct iphdr *h; /* Allocate packet */ skb = alloc_skb(sizeof(struct bootp_pkt) + hh_len + 15, GFP_KERNEL); if (!skb) return; skb_reserve(skb, hh_len); b = (struct bootp_pkt *) skb_put(skb, sizeof(struct bootp_pkt)); memset(b, 0, sizeof(struct bootp_pkt)); /* Construct IP header */ skb->nh.iph = h = &b->iph; h->version = 4; h->ihl = 5; h->tot_len = htons(sizeof(struct bootp_pkt)); h->frag_off = __constant_htons(IP_DF); h->ttl = 64; h->protocol = IPPROTO_UDP; h->daddr = INADDR_BROADCAST; h->check = ip_fast_csum((unsigned char *) h, h->ihl); /* Construct UDP header */ b->udph.source = __constant_htons(68); b->udph.dest = __constant_htons(67); b->udph.len = htons(sizeof(struct bootp_pkt) - sizeof(struct iphdr)); /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */ /* Construct DHCP/BOOTP header */ b->op = BOOTP_REQUEST; if (dev->type < 256) /* check for false types */ b->htype = dev->type; else if (dev->type == ARPHRD_IEEE802_TR) /* fix for token ring */ b->htype = ARPHRD_IEEE802; else { printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name); b->htype = dev->type; /* can cause undefined behavior */ } 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_diff / HZ); b->xid = d->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... */ skb->dev = dev; skb->protocol = __constant_htons(ETH_P_IP); if ((dev->hard_header && dev->hard_header(skb, dev, ntohs(skb->protocol), dev->broadcast, dev->dev_addr, skb->len) < 0) || dev_queue_xmit(skb) < 0) printk("E");}/* * Copy BOOTP-supplied string if not already set. */static int __init ic_bootp_string(char *dest, char *src, int len, int max){ if (!len) return 0; 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){#ifdef IPCONFIG_DEBUG u8 *c; printk("DHCP/BOOTP: Got extension %d:",*ext); for(c=ext+2; c<ext+2+ext[1]; c++) printk(" %02x", *c); printk("\n");#endif switch (*ext++) { case 1: /* Subnet mask */ if (ic_netmask == INADDR_NONE) memcpy(&ic_netmask, ext+1, 4); break; case 3: /* Default gateway */ if (ic_gateway == INADDR_NONE) 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 */ if (!root_server_path[0]) 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; }}/* * Receive BOOTP reply. */static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt){ 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) || h->ihl != 5 || h->version != 4 || ip_fast_csum((char *) h, h->ihl) != 0 || skb->len < ntohs(h->tot_len) || h->protocol != IPPROTO_UDP || b->udph.source != __constant_htons(67) || b->udph.dest != __constant_htons(68) || ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr)) goto drop; /* Fragments are not supported */ if (h->frag_off & __constant_htons(IP_OFFSET | IP_MF)) { printk(KERN_ERR "DHCP/BOOTP: Ignoring fragmented reply.\n"); goto drop; } /* Is it a reply to our BOOTP request? */ len = ntohs(b->udph.len) - sizeof(struct udphdr); if (len < 300 || /* See RFC 951:2.1 */ b->op != BOOTP_REPLY || b->xid != d->xid) { printk("?"); goto drop; } /* Parse extensions */ if (!memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */ u8 *end = (u8 *) b + ntohs(b->iph.tot_len); u8 *ext;#ifdef IPCONFIG_DHCP if (ic_proto_enabled & IC_USE_DHCP) { u32 server_id = INADDR_NONE; int mt = 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]) mt = 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", mt);#endif 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;#ifdef IPCONFIG_DEBUG printk("DHCP: Offered address %u.%u.%u.%u", NIPQUAD(ic_myaddr)); printk(" by server %u.%u.%u.%u\n", NIPQUAD(ic_servaddr));#endif /* The DHCP indicated server address takes * precedence over the bootp header one if * they are different. */ if ((server_id != INADDR_NONE) && (b->server_ip != server_id)) b->server_ip = ic_servaddr; break; case DHCPACK: /* Yeah! */ break; default: /* Urque. Forget it*/ ic_myaddr = INADDR_NONE; ic_servaddr = INADDR_NONE; goto drop; }; ic_dhcp_msgtype = mt; }#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); } } /* We have a winner! */ ic_dev = dev; ic_myaddr = b->your_ip; ic_servaddr = b->server_ip; if (ic_gateway == INADDR_NONE && b->relay_ip)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -