📄 dhcpcboot.c
字号:
else { /* Conversion unsuccessful - remove any stored parameters. */ clean_param (pParams); free (pParams); } } /* * Processed new offer before timer expired. Next state is (still) * SELECTING. Mark the message buffer available after handling the * last DHCP message. */ if (msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (SELECTING); }/********************************************************************************* dhcpcBootRequesting - Lease request state of client finite state machine** This routine implements the third state of the client finite state machine.* It sends a lease request to the DHCP server whose offer was selected,* and waits up to the current timeout value to receive a reply from that* server. If a timeout occurs, the DHCP request message is retransmitted.* If the request is refused or the retransmission limit is reached, the lease* negotiation process will restart or the inform process will exit. If the* request is acknowledged, the corresponding parameters will be used by the* bootstrap loader to configure the boot device and fetch the runtime image.** RETURNS: Next state of state machine, or -1 if error.** ERRNO: N/A** NOMANUAL*/LOCAL int dhcpcBootRequesting ( void ) { STATUS result = OK; char *pOption = NULL; char errmsg[255]; int timer = 0; int retry = 0; struct dhcp_param tmpparam; struct dhcp_reqspec tmp_reqspec; EVENT_DATA newEvent; char * pMsgData; int status; int msgtype;#ifdef DHCPC_DEBUG char newAddr [INET_ADDR_LEN]; logMsg ("dhcpc: Entering requesting state.\n", 0, 0, 0, 0, 0, 0);#endif bzero (errmsg, sizeof (errmsg)); bzero ( (char *)&tmp_reqspec, sizeof (tmp_reqspec)); /* Wait for message or retransmission. */ semTake (dhcpcEventSem, WAIT_FOREVER); status = rngBufGet (dhcpcEventRing, (char *)&newEvent, sizeof (newEvent)); if (status != sizeof (newEvent)) { /* Expected event missing or incomplete - remain in current state. */ return (REQUESTING); } if (newEvent.type == DHCP_TIMEOUT) { /* Handle timeout - no DHCP reply received yet. */ retry = dhcpcBootLeaseData.numRetry; timer = dhcpcBootLeaseData.timeout; retry++; if (retry > REQUEST_RETRANS) {#ifdef DHCPC_DEBUG logMsg ("Client can't get ACK/NAK reply from server\n", 0, 0, 0, 0, 0, 0);#endif /* Exit if unable to get additional parameters for known address. */ if (dhcpcPrevState == INFORMING) return (BOUND); return (INIT); /* Next state is INIT */ } /* Retransmission required - return after sending message. */ switch (gen_retransmit ()) { case 0: /* Transmission successful. */#ifdef DHCPC_DEBUG logMsg ("retransmit DHCPREQUEST\n", 0, 0, 0, 0, 0, 0);#endif break; case -1: /* Couldn't update timing data */#ifdef DHCPC_DEBUG logMsg ("time() error retransmitting DHCPREQUEST\n", 0, 0, 0, 0, 0, 0);#endif break; case -2: /* Transmission error in output routine */#ifdef DHCPC_DEBUG logMsg ("Can't retransmit DHCPREQUEST\n", 0, 0, 0, 0, 0, 0);#endif break; } if (timer < MAXTIMER) { /* Double retransmission delay with each attempt. (RFC 1541). */ timer *= 2; } /* Set retransmission timer to randomized exponential backoff. */ wdStart (dhcpcBootLeaseData.timer, sysClkRateGet() * SLEEP_RANDOM (timer), (FUNCPTR)retrans_requesting, 0); dhcpcBootLeaseData.timeout = timer; dhcpcBootLeaseData.numRetry = retry; } else { bzero ( (char *)&tmpparam, sizeof (tmpparam)); /* * Process DHCP message stored in receive buffer by monitor task. * The 4-byte alignment of the IP header needed by Sun BSP's is * guaranteed by the Berkeley Packet Filter during input. */ pMsgData = newEvent.pMsg; msgAlign (&dhcpcMsgIn, pMsgData); pOption = (char *) pickup_opt (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), _DHCP_MSGTYPE_TAG); if (pOption != NULL) { msgtype =*OPTBODY (pOption); /* * Ignore unknown message types. If the client does not receive * a valid response within the expected interval, it will * timeout and retransmit the request - RFC 2131, section 3.1.5. */ if (msgtype != DHCPACK && msgtype != DHCPNAK) { /* * Mark the message buffer available after * handling the last DHCP message. */ if (newEvent.lastFlag) dhcpcMessageList [newEvent.slot].writeFlag = TRUE; return (REQUESTING); } if (msgtype == DHCPNAK) {#ifdef DHCPC_DEBUG logMsg ("Got DHCPNAK from server\n", 0, 0, 0, 0, 0, 0); pOption = (char *)pickup_opt (dhcpcMsgIn.dhcp, DHCPLEN(dhcpcMsgIn.udp), _DHCP_ERRMSG_TAG); if (pOption != NULL && nvttostr (OPTBODY (pOption), errmsg, (int)DHCPOPTLEN (pOption)) == 0) logMsg ("DHCPNAK contains the error message \"%s\"\n", (int)errmsg, 0, 0, 0, 0, 0);#endif /* * Mark the message buffer available after handling the * last DHCP message. */ if (newEvent.lastFlag) dhcpcMessageList [newEvent.slot].writeFlag = TRUE; /* Ignore invalid responses to DHCP inform message. */ if (dhcpcPrevState == INFORMING) return (REQUESTING); clean_param (dhcpcBootParam); free (dhcpcBootParam); dhcpcBootParam = NULL; return (INIT); /* Next state is INIT */ } /* * Got acknowledgement: fill in host requirements defaults and * add any parameters from message options. */ dhcpcDefaultsSet (&tmpparam); result = dhcp_msgtoparam (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), &tmpparam); /* * Mark the message buffer available after * handling the last DHCP message. */ if (newEvent.lastFlag) dhcpcMessageList [newEvent.slot].writeFlag = TRUE; if (result == OK) { /* Options parsed successfully - test as needed. */ if (dhcpcPrevState == INFORMING) dhcpcBindType = DHCP_MANUAL; /* Not a lease. */ else { /* Full lease negotiation - send ARP probe. */ result = arp_check (&tmpparam.yiaddr, &dhcpcIntface); if (result == OK) { #ifdef DHCPC_DEBUG inet_ntoa_b (dhcpcBootParam->yiaddr, newAddr); logMsg ("Got DHCPACK (IP = %s, duration = %d secs)\n", (int)newAddr, dhcpcBootParam->lease_duration, 0, 0, 0, 0);#endif dhcpcBindType = DHCP_NATIVE; } } /* Save additional parameters if address is available. */ if (result == OK) { merge_param (dhcpcBootParam, &tmpparam); *dhcpcBootParam = tmpparam; if (dhcpcBindType == DHCP_NATIVE) { /* Save the lease start time. */ dhcpcBootParam->lease_origin = dhcpcBootLeaseData.initEpoch; } return (BOUND); /* Address is available. */ } } /* * Invalid parameters or (for a full lease negotiation) a * failed ARP probe (address in use). For the full lease * negotiation, send the DHCPDECLINE message which is now * required when an ARP probe fails: RFC 2131, section 3.1.5. */ if (dhcpcPrevState != INFORMING) { set_declinfo (&tmp_reqspec, errmsg); dhcp_decline (&tmp_reqspec); clean_param (dhcpcBootParam); free (dhcpcBootParam); dhcpcBootParam = NULL;#ifdef DHCPC_DEBUG logMsg ("Received unacceptable ACK. Entering INIT state.\n", 0, 0, 0, 0, 0, 0);#endif return (INIT); } /* Ignore invalid parameters for DHCP inform messages. */ return (REQUESTING); } /* * Message type unavailable - remain in current state. Mark * the message buffer available after handling the last DHCP * message. */ if (newEvent.lastFlag) dhcpcMessageList [newEvent.slot].writeFlag = TRUE; } /* Timeout occurred - remain in current state. */ return (REQUESTING); }/********************************************************************************* generate_xid - generate a transaction identifier ** This routine forms a transaction identifier for outgoing messages from the* DHCP client. It is called from multiple locations after the initialization * routines have retrieved the network interface hardware address.** RETURNS: 32-bit transaction identifier in host byte order. ** ERRNO: N/A** NOMANUAL*/LOCAL long generate_xid ( void ) { time_t current = 0; u_short result1 = 0; u_short result2 = 0; u_short tmp[6]; bcopy (dhcpcIntface.haddr.haddr, (char *)tmp, 6); dhcpTime (¤t); result1 = checksum (tmp, 6); result2 = checksum ( (u_short *)¤t, 2); return ( (result1 << 16) + result2); }/********************************************************************************* msgAlign - set the buffer pointers to access message components** This routine sets the pointers in the given message descriptor* structure to access the various components of a received DHCP* message. It is used internally by the state machine routines.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL void msgAlign ( struct msg *rmsg, /* Components of received message */ char *rbuf /* Received Ethernet packet */ ) { rmsg->ip = (struct ip *) rbuf; if ( (ntohs (rmsg->ip->ip_off) & 0x1fff) == 0 && ntohs (rmsg->ip->ip_len) >= (DFLTDHCPLEN - DFLTOPTLEN + 4) + UDPHL + IPHL) {#if BSD<44 rmsg->udp = (struct udphdr *)&rbuf [(rmsg->ip->ip_v_hl & 0xf) * WORD]; rmsg->dhcp = (struct dhcp *)&rbuf [(rmsg->ip->ip_v_hl & 0xf) * WORD + UDPHL];#else rmsg->udp = (struct udphdr *) &rbuf [rmsg->ip->ip_hl * WORD]; rmsg->dhcp = (struct dhcp *) &rbuf [rmsg->ip->ip_hl * WORD + UDPHL];#endif } else { rmsg->udp = NULL; rmsg->dhcp = NULL; } return; }/********************************************************************************* arp_check - use ARP to check if given address is in use** This routine broadcasts an ARP request and waits for a reply to determine if* an IP address offered by a DHCP server is already in use.** RETURNS: ERROR if ARP indicates client in use, or OK otherwise.** ERRNO: N/A** NOMANUAL*/int arp_check ( struct in_addr *target, struct if_info *pIfData /* interface used by lease */ ) { int i = 0; int tmp; char inbuf [MAX_ARPLEN]; char *pField1; char *pField2; struct arphdr * pArpHdr = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -