📄 dhcpcboot.c
字号:
struct ifreq ifr; struct timeval timeout; fd_set readFds; bzero (inbuf, MAX_ARPLEN); pArpHdr = (struct arphdr *) inbuf; pArpHdr->ar_hrd = htons (pIfData->haddr.htype); pArpHdr->ar_pro = htons (ETHERTYPE_IP); pArpHdr->ar_hln = pIfData->haddr.hlen; pArpHdr->ar_pln = 4; pArpHdr->ar_op = htons (ARPOP_REQUEST); /* Set sender H/W address to your address for ARP requests. (RFC 1541). */ pField1 = &inbuf [ARPHL]; /* Source hardware address. */ pField2 = pField1 + pArpHdr->ar_hln + 4; /* Target hardware address. */ for (i = 0; i < pIfData->haddr.hlen; i++) { pField1[i] = pIfData->haddr.haddr[i]; pField2[i] = 0; } /* Set sender IP address to 0 for ARP requests as per RFC 1541. */ pField1 += pArpHdr->ar_hln; /* Source IP address. */ pField2 += pArpHdr->ar_hln; /* Target IP address. */ tmp = 0; bcopy ( (char *)&tmp, pField1, pArpHdr->ar_pln); bcopy ( (char *)&target->s_addr, pField2, pArpHdr->ar_pln); /* Update BPF filter to check for ARP reply from target IP address. */ arpfilter [9].k = htonl (target->s_addr); if (ioctl (bpfArpDev, BIOCSETF, (int)&arpread) != 0) return (OK); /* Ignore errors (permits use of IP address). */ tmp = ARPHL + 2 * (pArpHdr->ar_hln + 4); /* Size of ARP message. */ dhcpcArpSend (pIfData->iface, inbuf, tmp); /* Set BPF to monitor interface for reply. */ bzero ( (char *)&ifr, sizeof (struct ifreq)); sprintf (ifr.ifr_name, "%s%d", pIfData->iface->if_name, pIfData->iface->if_unit); if (ioctl (bpfArpDev, BIOCSETIF, (int)&ifr) != 0) return (OK); /* Ignore errors (permits use of IP address). */ /* Wait one-half second for (unexpected) reply from target IP address. */ timeout.tv_sec = 0; timeout.tv_usec = 500000; FD_ZERO (&readFds); FD_SET (bpfArpDev, &readFds); tmp = select (bpfArpDev + 1, &readFds, NULL, NULL, &timeout); /* Disconnect BPF device from input stream until next ARP probe. */ ioctl (bpfArpDev, BIOCSTOP, 0); if (tmp) /* ARP reply received? Duplicate IP address. */ return (ERROR); else /* Timeout occurred - no ARP reply. Probe succeeded. */ return (OK); }#ifdef DHCPC_DEBUG/********************************************************************************* nvttostr - convert NVT ASCII to strings** This routine implements a limited NVT conversion which removes any embedded* NULL characters from the input string.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL int nvttostr ( char * nvt, char * str, int length ) { FAST int i = 0; FAST char *tmp = NULL; tmp = str; for (i = 0; i < length; i++) { if (nvt[i] != '\0') { *tmp = nvt[i]; tmp++; } } str [length] = '\0'; return (0); }#endif/********************************************************************************* dhcp_msgtoparam - expand DHCP message into data structure** This routine converts a DHCP message from the transmission format into the* dhcp_param structure. It copies the core fields directly and multiplexes* the options to the appropriate handle_* functions.** RETURNS: 0 if conversion successful, or -1 otherwise** ERRNO: N/A** INTERNAL** When calculating the values for the lease timers, floating-point calculations* can't be used because some boards (notably the SPARC architectures) disable * software floating point by default to speed up context switching. These * boards abort with an exception when floating point operations are * encountered. The error introduced by the integer approximations is not* significant.** NOMANUAL*/LOCAL int dhcp_msgtoparam ( struct dhcp *msg, int msglen, struct dhcp_param *parameter ) { FAST char *optp = NULL; char tag = 0; BOOL sname_is_opt = FALSE; BOOL file_is_opt = FALSE; int err = 0; char *endofopt; endofopt = &msg->options [msglen - DFLTDHCPLEN + DFLTOPTLEN]; bzero (parameter->got_option, OPTMASKSIZE); for (optp = &msg->options [MAGIC_LEN]; optp <= endofopt; optp++) { tag = *optp; /* skip the PAD option */ if (tag == _DHCP_PAD_TAG) continue; /* stop processing when the END option is encountered */ if (tag == _DHCP_END_TAG) break; /* handle the "Option Overload" */ if (tag == _DHCP_OPT_OVERLOAD_TAG) { optp += 2; switch (*optp) { case FILE_ISOPT: file_is_opt = TRUE; break; case SNAME_ISOPT: sname_is_opt = TRUE; break; case BOTH_AREOPT: file_is_opt = sname_is_opt = TRUE; break; default: break; } continue; } if ((tag > 0) && (tag < MAXTAGNUM) && (handle_param [(int)tag] != NULL)) { if ( (err = (*handle_param [ (int)tag]) (optp, parameter)) != 0) return (err); else SETBIT (parameter->got_option, tag); } /* Set the message type tag to distinguish DHCP and BOOTP messages. */ else if (tag == _DHCP_MSGTYPE_TAG) SETBIT (parameter->got_option, tag); optp++; optp += *optp; } if (file_is_opt) { endofopt = &msg->file [MAX_FILE]; for (optp = msg->file; optp <= endofopt; optp++) { tag = *optp; /* skip the PAD option */ if (tag == _DHCP_PAD_TAG) continue; /* stop processing when the END option is reached */ if (tag == _DHCP_END_TAG) break; if (handle_param [ (int)tag] != NULL) { if ( (err = (*handle_param [ (int)tag]) (optp, parameter)) != 0) return (err); else SETBIT(parameter->got_option, tag); } /* Set the message type to distinguish DHCP and BOOTP messages. */ else if (tag == _DHCP_MSGTYPE_TAG) SETBIT (parameter->got_option, tag); optp++; optp += *optp; } } else { if ( (parameter->file = calloc (1, strlen (msg->file) + 1)) == NULL) return (-1); strcpy (parameter->file, msg->file); } if (sname_is_opt) { endofopt = &msg->sname [MAX_SNAME]; for (optp = msg->sname; optp <= endofopt; optp++) { tag = *optp; /* skip the PAD option */ if (tag == _DHCP_PAD_TAG) continue; /* stop processing when the END option is reached */ if (tag == _DHCP_END_TAG) break; if (handle_param [ (int)tag] != NULL) { if ( (err = (*handle_param [ (int)tag]) (optp, parameter)) != 0) return(err); else SETBIT (parameter->got_option, tag); } /* Set the message type to distinguish DHCP and BOOTP messages. */ else if (tag == _DHCP_MSGTYPE_TAG) SETBIT (parameter->got_option, tag); optp++; optp += *optp; } } else { if ( (parameter->sname = calloc (1, strlen (msg->sname) + 1)) == NULL) return (-1); strcpy(parameter->sname, msg->sname); } parameter->ciaddr.s_addr = msg->ciaddr.s_addr; parameter->yiaddr.s_addr = msg->yiaddr.s_addr; parameter->siaddr.s_addr = msg->siaddr.s_addr; parameter->giaddr.s_addr = msg->giaddr.s_addr; if (ISSET (parameter->got_option, _DHCP_MSGTYPE_TAG)) parameter->msgtype = DHCP_NATIVE; else parameter->msgtype = DHCP_BOOTP; /* Set lease duration to infinite for BOOTP replies. */ if (parameter->msgtype == DHCP_BOOTP) { parameter->lease_duration = ~0; return (0); } /* Assign any server name provided if 'sname' used for options. */ if (sname_is_opt) { parameter->sname = parameter->temp_sname; parameter->temp_sname = NULL; } /* Assign any bootfile provided if 'file' used for options. */ if (file_is_opt) { if (ISSET (parameter->got_option, _DHCP_BOOTFILE_TAG)) { parameter->file = parameter->temp_file; parameter->temp_file = NULL; } } if (parameter->dhcp_t1 == 0) { /* Timer t1 is half the lease duration - but don't divide. */ parameter->dhcp_t1 = (parameter->lease_duration) >> 1; SETBIT (parameter->got_option, _DHCP_T1_TAG); } if (parameter->dhcp_t2 == 0) { /* Timer T2 is .875 of the lease - but don't use floating point. */ int tmp = (parameter->lease_duration * 7) >> 3; parameter->dhcp_t2 = (unsigned long) tmp; SETBIT(parameter->got_option, _DHCP_T2_TAG); } return(0); }/********************************************************************************* clean_param - clean the parameters data structure** This routine frees all the memory allocated for the storage of parameters* received from a DHCP server. It is called to remove the unselected offers* or if an error occurs in the state machine after offers have been received.** RETURNS: 0, always.** ERRNO: N/A** NOMANUAL*/LOCAL int clean_param ( struct dhcp_param *param ) { if (param == NULL) return(0); if (param->sname != NULL) free (param->sname); if (param->temp_sname != NULL) free (param->temp_sname); if (param->file != NULL) free (param->file); if (param->temp_file != NULL) free (param->temp_file); if (param->hostname != NULL) free (param->hostname); if (param->merit_dump != NULL) free (param->merit_dump); if (param->dns_domain != NULL) free (param->dns_domain); if (param->root_path != NULL) free (param->root_path); if (param->extensions_path != NULL) free (param->extensions_path); if (param->nis_domain != NULL) free (param->nis_domain); if (param->nb_scope != NULL) free (param->nb_scope); if (param->errmsg != NULL) free (param->errmsg); if (param->nisp_domain != NULL) free (param->nisp_domain); if (param->mtu_plateau_table != NULL) { if (param->mtu_plateau_table->shortnum != NULL) free (param->mtu_plateau_table->shortnum); free (param->mtu_plateau_table); } if (param->subnet_mask != NULL) free (param->subnet_mask); if (param->swap_server != NULL) free (param->swap_server); if (param->brdcast_addr != NULL) free (param->brdcast_addr); if (param->router != NULL) { if (param->router->addr != NULL) free (param->router->addr); free (param->router); } if (param->time_server != NULL) { if (param->time_server->addr != NULL) free (param->time_server->addr); free (param->time_server); } if (param->name_server != NULL) { if (param->name_server->addr != NULL) free (param->name_server->addr); free (param->name_server); } if (param->dns_server !
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -