📄 dhcpboot.c
字号:
DHCPState = BOOTPSTATE_COMPLETE;
/* 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(1);
return(0);
}
int
processDHCP(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));
if (EtherVerbose & SHOW_HEX)
printMem((uchar *)ehdr,size,EtherVerbose & SHOW_ASCII);
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,(char *)(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) {
char ip[4];
memcpy(ip,(char *)&ihdr->ip_src,4);
printf(" DHCP offer from %d.%d.%d.%d ignored\n",
ip[0],ip[1],ip[2],ip[3]);
}
}
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,(char *)(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,(char *)(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,(char *)(dhdr+1));
if (op) {
memcpy((char *)&leasetime,op+2,4);
leasetime = ecl(leasetime);
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.
*/
void
printDhcpOptions(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...
*/
void
printDhcp(struct Udphdr *p)
{
struct dhcphdr *d;
uchar *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(unsigned char optval,unsigned char *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);
}
int
DhcpSetEnv(char *name,char *value)
{
if (EtherVerbose & SHOW_DHCP)
printf(" Dhcp/Bootp SetEnv: %s = %s\n",name,value);
return(setenv(name,value));
}
int
DhcpIPCheck(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("???");
}
}
void
ShowDhcpStats()
{
printf("Current DHCP State: %s\n",dhcpStringState(DHCPState));
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -