📄 dhcpboot.c
字号:
loadBootFile(1); return(0);}intprocessDHCP(struct ether_header *ehdr,ushort size){ struct ip *ihdr; struct Udphdr *uhdr; struct dhcphdr *dhdr; uchar buf[16], *op, msgtype; ulong ip, temp_ip, leasetime; if (DHCPState == BOOTPSTATE_REQUEST) return(processBOOTP(ehdr,size)); printMem((uchar *)ehdr,size); ihdr = (struct ip *)(ehdr + 1); uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); dhdr = (struct dhcphdr *)(uhdr+1); /* Verify incoming transaction id matches the previous outgoing value: */ if (xidCheck((char *)&dhdr->transaction_id,0) < 0) return(-1); op = DhcpGetOption(DHCPOPT_MESSAGETYPE,dhdr+1); if (op) msgtype = *(op+2); else msgtype = DHCPUNKNOWN; if ((DHCPState == DHCPSTATE_SELECT) && (msgtype == DHCPOFFER)) { /* Target issued the DISCOVER, the incoming packet is the server's * OFFER reply. The function "ValidDHCPOffer() will return * non-zero if the request is to be sent. */ if (ValidDHCPOffer(dhdr)) SendDHCPRequest(dhdr); else if (EtherVerbose & SHOW_DHCP) { ulong src; memcpy((char *)&src,(char *)&ihdr->ip_src,4); printf(" DHCP offer from %I ignored\n",src); } } else if ((DHCPState == DHCPSTATE_REQUEST) && (msgtype == DHCPACK)) { ulong cookie; /* Target issued the REQUEST, the incoming packet is the server's * ACK reply. We're done so load the environment now. */ /* If bootfile is nonzero, store it into BOOTFILE shell var: */ if (dhdr->bootfile[0]) DhcpSetEnv("BOOTFILE",dhdr->bootfile); /* Assign IP "server_ip" to the BOOTSRVR shell var (if non-zero): */ memcpy((char *)&temp_ip,(char *)&dhdr->server_ip,4); if (temp_ip) DhcpSetEnv("BOOTSRVR",IpToString(temp_ip,buf)); /* Assign IP "router_ip" to the RLYAGNT shell var (if non-zero): */ memcpy((char *)&temp_ip,(char *)&dhdr->router_ip,4); if (temp_ip) DhcpSetEnv("RLYAGNT",IpToString(temp_ip,buf)); /* Assign IP address loaded in "your_ip" to the IPADD shell var: */ memcpy(BinIpAddr,(char *)&dhdr->your_ip,4); memcpy((char *)&temp_ip,(char *)&dhdr->your_ip,4); DhcpSetEnv("IPADD",IpToString(temp_ip,buf)); /* If STANDARD_MAGIC_COOKIE exists, process options... */ memcpy((char *)&cookie,(char *)&dhdr->magic_cookie,4); if (cookie == ecl(STANDARD_MAGIC_COOKIE)) { /* Assign subnet mask to NETMASK shell var (if found): */ op = DhcpGetOption(DHCPOPT_SUBNETMASK,dhdr+1); if (op) { memcpy((char *)&ip,op+2,4); DhcpSetEnv("NETMASK",IpToString(ip,buf)); } /* Assign gateway IP to GIPADD shell var (if found): * (the router option can have multiple entries, and they are * supposed to be in order of preference, so use the first one). */ op = DhcpGetOption(DHCPOPT_ROUTER,dhdr+1); if (op) { memcpy((char *)&ip,op+2,4); DhcpSetEnv("GIPADD",IpToString(ip,buf)); } /* Process DHCPOPT_LEASETIME option as follows... * If not set, assume infinite and clear DHCPLEASETIME shellvar. * If set, then look for the presence of the DHCPLEASETIME shell * variable and use it as a minimum. If the incoming value is * >= what is in the shell variable, accept it and load the shell * variable with this value. If incoming lease time is less than * what is stored in DHCPLEASETIME, ignore the request. * If DHCPLEASETIME is not set, then just load the incoming lease * into the DHCPLEASETIME shell variable and accept the offer. */ op = DhcpGetOption(DHCPOPT_LEASETIME,dhdr+1); if (op) { memcpy((char *)&leasetime,op+2,4); if (getenv("DHCPLEASETIME")) { ulong minleasetime; minleasetime = strtol(getenv("DHCPLEASETIME"),0,0); if (leasetime < minleasetime) { printf("DHCP: incoming lease time 0x%lx too small.\n", leasetime); return(-1); } } sprintf(buf,"0x%lx",leasetime); setenv("DHCPLEASETIME",buf); } else setenv("DHCPLEASETIME",0); } /* Check for vendor specific stuff... */ DhcpVendorSpecific(dhdr); DhcpBootpDone(0,dhdr, size - ((int)((int)&dhdr->magic_cookie - (int)ehdr))); DHCPState = DHCPSTATE_BOUND; /* Call loadBootFile() which will then kick off a tftp client * transfer if both BOOTFILE and BOOTSRVR shell variables are * loaded; otherwise, we are done. */ loadBootFile(0); } return(0);}char *DHCPop(op)int op;{ switch(op) { case DHCPBOOTP_REQUEST: return("REQUEST"); case DHCPBOOTP_REPLY: return("REPLY"); default: return("???"); }}char *DHCPopt(op)int op;{ switch(op) { case DHCPDISCOVER: return("DISCOVER"); case DHCPOFFER: return("OFFER"); case DHCPREQUEST: return("REQUEST"); case DHCPDECLINE: return("DECLINE"); case DHCPACK: return("ACK"); case DHCPNACK: return("NACK"); case DHCPRELEASE: return("RELEASE"); default: return("???"); }}/* printDhcpOptions(): * Verbosely display the DHCP options pointed to by the incoming * options pointer. */voidprintDhcpOptions(uchar *options){ int i, safety, opt, optlen; safety = 0; while(*options != 0xff) { if (safety++ > 10000) { printf("Aborting, overflow likely\n"); break; } opt = (int)*options++; if (opt == 0) /* padding */ continue; printf(" option %3d: ",opt); optlen = (int)*options++; if (opt==DHCPOPT_MESSAGETYPE) { printf("DHCP%s",DHCPopt(*options++)); } /* Vendor specific information: * Note that the data within this option is vendor specific. * The RFC2132 says that the encapsulated data with this option * SHOULD follow the same format as the outer-layer options, but * is not mandatory. */ else if (opt==DHCPOPT_VENDORSPECIFICINFO) { int vsopt, vsoptlen; printf("\n"); while(*options != 0xff) { vsopt = (int)*options++; vsoptlen = (int)*options++; printf(" vso %3d: ",vsopt); if (!printDhcpVSopt(vsopt,vsoptlen,options)) { printf("0x"); for(i=0;i<vsoptlen;i++) printf("%02x",*options++); } if (*options != 0xff) printf("\n"); } options++; /* Skip over the 0xff within this option sub-set */ } else if ((opt < DHCPOPT_HOSTNAME) || (opt == DHCPOPT_BROADCASTADDRESS) || (opt == DHCPOPT_REQUESTEDIP) || (opt == DHCPOPT_SERVERID) || (opt == DHCPOPT_NISSERVER)) { for(i=0;i<optlen;i++) printf("%d ",*options++); } else if ((opt == DHCPOPT_NISDOMAINNAME) || (opt == DHCPOPT_CLASSID)) { for(i=0;i<optlen;i++) printf("%c",*options++); } else if (opt == DHCPOPT_CLIENTID) { printf("%d 0x",(int)*options++); for(i=1;i<optlen;i++) printf("%02x",*options++); } else { printf("0x"); for(i=0;i<optlen;i++) printf("%02x",*options++); } printf("\n"); }}/* printDhcp(): * Try to format the DHCP stuff... */voidprintDhcp(struct Udphdr *p){ struct dhcphdr *d; char *client_ip, *your_ip, *server_ip, *router_ip; ulong cookie, xid; d = (struct dhcphdr *)(p+1); client_ip = (uchar *)&(d->client_ip); your_ip = (uchar *)&(d->your_ip); server_ip = (uchar *)&(d->server_ip); router_ip = (uchar *)&(d->router_ip); memcpy((char *)&xid,(char *)&d->transaction_id,4); /* xid = ecl(xid) */ printf(" DHCP: sport dport ulen sum\n"); printf(" %4d %4d %4d %4d\n", ecs(p->uh_sport), ecs(p->uh_dport), ecs(p->uh_ulen),ecs(p->uh_sum)); printf(" op = %s, htype = %d, hlen = %d, hops = %d\n", DHCPop(d->op),d->htype,d->hlen,d->hops); printf(" seconds = %d, flags = 0x%x, xid= 0x%lx\n", ecs(d->seconds),ecs(d->flags),xid); printf(" client_macaddr = %02x:%02x:%02x:%02x:%02x:%02x\n", d->client_macaddr[0], d->client_macaddr[1], d->client_macaddr[2], d->client_macaddr[3], d->client_macaddr[4], d->client_macaddr[5]); printf(" client_ip = %d.%d.%d.%d\n", client_ip[0],client_ip[1],client_ip[2],client_ip[3]); printf(" your_ip = %d.%d.%d.%d\n", your_ip[0],your_ip[1],your_ip[2],your_ip[3]); printf(" server_ip = %d.%d.%d.%d\n", server_ip[0],server_ip[1],server_ip[2],server_ip[3]); printf(" router_ip = %d.%d.%d.%d\n", router_ip[0],router_ip[1],router_ip[2],router_ip[3]); if (d->bootfile[0]) printf(" bootfile: %s\n", d->bootfile); if (d->server_hostname[0]) printf(" server_hostname: %s\n", d->server_hostname); /* If STANDARD_MAGIC_COOKIE doesn't exist, then don't process options... */ memcpy((char *)&cookie,(char *)&d->magic_cookie,4); if (cookie != ecl(STANDARD_MAGIC_COOKIE)) return; printDhcpOptions((uchar *)(d+1));}/* DhcpGetOption(): * Based on the incoming option pointer and a specified option value, * search through the options list for the value and return a pointer * to that option. */uchar *DhcpGetOption(optval,options)uchar optval, *options;{ int safety; safety = 0; while(*options != 0xff) { if (safety++ > 1000) break; if (*options == 0) { /* Skip over padding. */ options++; continue; } if (*options == optval) return(options); options += ((*(options+1)) + 2); } return((char *)0);}intDhcpSetEnv(char *name,char *value){ if (EtherVerbose & SHOW_DHCP) printf(" Dhcp/Bootp SetEnv: %s = %s\n",name,value); return(setenv(name,value));}intDhcpIPCheck(char *ipadd){ char verbose; if (!memcmp(ipadd,"DHCP",4)) { verbose = ipadd[4]; DHCPState = DHCPSTATE_INITIALIZE; } else if (!memcmp(ipadd,"BOOTP",5)) { verbose = ipadd[5]; DHCPState = BOOTPSTATE_INITIALIZE; } else { if (IpToBin(ipadd,BinIpAddr) < 0) { verbose = 0; DHCPState = BOOTPSTATE_INITIALIZE; } else { DHCPState = DHCPSTATE_NOTUSED; return(0); } } BinIpAddr[0] = 0; BinIpAddr[1] = 0; BinIpAddr[2] = 0; BinIpAddr[3] = 0; if (verbose == 'V') EtherVerbose = DHCP_VERBOSE; else if (verbose == 'v') EtherVerbose = SHOW_DHCP; return(0);}char *dhcpStringState(int state){ switch(state) { case DHCPSTATE_INITIALIZE: return("DHCP_INITIALIZE"); case DHCPSTATE_SELECT: return("DHCP_SELECT"); case DHCPSTATE_REQUEST: return("DHCP_REQUEST"); case DHCPSTATE_BOUND: return("DHCP_BOUND"); case DHCPSTATE_RENEW: return("DHCP_RENEW"); case DHCPSTATE_REBIND: return("DHCP_REBIND"); case DHCPSTATE_NOTUSED: return("DHCP_NOTUSED"); case DHCPSTATE_RESTART: return("DHCP_RESTART"); case BOOTPSTATE_INITIALIZE: return("BOOTP_INITIALIZE"); case BOOTPSTATE_REQUEST: return("BOOTP_REQUEST"); case BOOTPSTATE_RESTART: return("BOOTP_RESTART"); case BOOTPSTATE_COMPLETE: return("BOOTP_COMPLETE"); default: return("???"); }}voidShowDhcpStats(){ printf("Current DHCP State: %s\n",dhcpStringState(DHCPState));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -