📄 dhcpcboot.c
字号:
( void ) { time_t curr_epoch = 0; struct sockaddr_in dest; BOOL bcastFlag; if (dhcpTime (&curr_epoch) == -1) return (-1); /* Update the appropriate fields in the current DHCP message. */ if (dhcpcCurrState != REQUESTING) dhcpcMsgOut.dhcp->secs = htons (curr_epoch - dhcpcBootLeaseData.initEpoch); dhcpcMsgOut.udp->uh_sum = 0; dhcpcMsgOut.udp->uh_sum = udp_cksum (&spudph, (char *)dhcpcMsgOut.udp, ntohs (spudph.ulen)); /* * Retransmit the message. Set the flag to use a link-level broadcast * address if needed (prevents ARP messages if using Ethernet devices). */ bzero ( (char *)&dest, sizeof (struct sockaddr_in)); dest.sin_len = sizeof (struct sockaddr_in); dest.sin_family = AF_INET; dest.sin_addr.s_addr = dhcpcMsgOut.ip->ip_dst.s_addr; if (dest.sin_addr.s_addr == 0xffffffff) bcastFlag = TRUE; else bcastFlag = FALSE; if (dhcpSend (dhcpcBootLeaseData.ifData.iface, &dest, sbuf.buf, dhcpcMsgLength, bcastFlag) == ERROR) return (-2); return(0); }/********************************************************************************* retrans_wait_offer - retransmission in WAIT_OFFER state** This routine retransmits the DHCP discover message when the timeout interval * for receiving an initial lease offer expires. It is called in response* to a watchdog timer at intervals specified by the wait_offer() routine.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL void retrans_wait_offer ( int unused /* unused watchdog argument */ ) { int status; if (dhcpcCurrState != WAIT_OFFER) return; /* Construct and send a timeout message to the finite state machine. */ status = dhcpcEventAdd (DHCP_AUTO_EVENT, DHCP_TIMEOUT, NULL, TRUE);#ifdef DHCPC_DEBUG if (status == ERROR) logMsg ("Can't notify state machine\n", 0, 0, 0, 0, 0, 0);#endif return; }/********************************************************************************* alarm_selecting - signal when collection time expires ** This routine sends a timeout notification to the finite state machine * when the interval for collecting additional DHCP offers has expired. It * is called in response to a watchdog timer schedule by the selecting()* routine. The timeout causes the state machine to advance to the REQUESTING* state.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL void alarm_selecting ( int unused /* unused watchdog argument */ ) { int status; if (dhcpcCurrState == SELECTING) { /* Construct and send a timeout message to the finite state machine. */ status = dhcpcEventAdd (DHCP_AUTO_EVENT, DHCP_TIMEOUT, NULL, TRUE);#ifdef DHCPC_DEBUG if (status == ERROR) logMsg ("Can't notify state machine\n", 0, 0, 0, 0, 0, 0);#endif } return; }/********************************************************************************* retrans_requesting - retransmission in requesting state** This routine retransmits the DHCP request message when the timeout interval * for receiving a server reply expires. It is called in response to a watchdog * timer at intervals specified by the requesting() routine.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL void retrans_requesting ( int unused /* unused watchdog argument */ ) { int status; if (dhcpcCurrState != REQUESTING) return; /* Construct and send a timeout message to the finite state machine. */ status = dhcpcEventAdd (DHCP_AUTO_EVENT, DHCP_TIMEOUT, NULL, TRUE);#ifdef DHCPC_DEBUG if (status == ERROR) logMsg ("Can't notify state machine\n", 0, 0, 0, 0, 0, 0);#endif return; }/********************************************************************************* dhcpcBootInforming - external configuration state of boot-time state machine** This routine begins the inform message process, which obtains additional* parameters for a host configured with an external address. This processing* is isolated from the normal progression through the state machine. Like the* DHCP discover message, the inform message is the first transmission.* However, the only valid response is an acknowledgement by a server. As a* result, the process is a hybrid between the implementations of the initial * state and the requesting state which finalizes the lease establishment.* This routine implements the initial state of the finite state machine for* an externally assigned IP address.** RETURNS: Next state of state machine, or -1 if error.** ERRNO: N/A** NOMANUAL*/LOCAL int dhcpcBootInforming ( void ) { struct sockaddr_in dest; bzero (sbuf.buf, sbuf.size);#ifdef DHCPC_DEBUG logMsg("dhcpc: Entered INFORM state.\n", 0, 0, 0, 0, 0, 0);#endif /* Create and broadcast DHCP INFORM message. */ dhcpcMsgLength = make_request (dhcpcBootParam, INFORMING); if (dhcpcMsgLength < 0) {#ifdef DHCPC_DEBUG logMsg ("Error making DHCP inform message. Can't continue.\n", 0, 0, 0, 0, 0, 0);#endif return (-1); } dhcpcMsgOut.dhcp->secs = 0; dhcpcMsgOut.udp->uh_sum = 0; dhcpcMsgOut.udp->uh_sum = udp_cksum (&spudph, (char *)dhcpcMsgOut.udp, ntohs (spudph.ulen));#ifdef DHCPC_DEBUG logMsg ("Sending DHCPINFORM\n", 0, 0, 0, 0, 0, 0);#endif /* * Retransmit the message using a link-level broadcast address, which * prevents ARP messages if using Ethernet devices and allows transmission * from interfaces without assigned IP addresses. */ bzero ( (char *)&dest, sizeof (struct sockaddr_in)); dest.sin_len = sizeof (struct sockaddr_in); dest.sin_family = AF_INET; dest.sin_addr.s_addr = dhcpcMsgOut.ip->ip_dst.s_addr; if (dhcpSend (dhcpcIntface.iface, &dest, sbuf.buf, dhcpcMsgLength, TRUE) == ERROR) {#ifdef DHCPC_DEBUG logMsg("Can't send DHCPINFORM\n", 0, 0, 0, 0, 0, 0);#endif return (-1); } /* Set retransmission timer to randomized exponential backoff. */ dhcpcBootLeaseData.timeout = FIRSTTIMER; dhcpcBootLeaseData.numRetry = 0; wdStart (dhcpcBootLeaseData.timer, sysClkRateGet() * SLEEP_RANDOM (dhcpcBootLeaseData.timeout), (FUNCPTR)retrans_requesting, 0); return (REQUESTING); /* Next state is REQUESTING */ }/********************************************************************************* dhcpcBootInitState - initial state of boot-time client finite state machine** This routine implements the initial state of the finite state machine. * After a random backoff delay, it broadcasts a DHCP discover message. This * state may be re-entered after a later state if a recoverable error occurs.** RETURNS: Next state of state machine, or -1 if error.** ERRNO: N/A** NOMANUAL*/LOCAL int dhcpcBootInitState ( void ) { struct sockaddr_in dest; bzero (sbuf.buf, sbuf.size);#ifdef DHCPC_DEBUG logMsg("dhcpc: Entered INIT state.\n", 0, 0, 0, 0, 0, 0);#endif /* * Set lease to generate newer RFC 2131 messages initially. The client * will revert to the older message format if it does not receive a * response to the initial set of discover messages. Older servers might * ignore messages less than the minimum length obtained with a fixed * options field. The older format pads the field to reach that length. */ dhcpcOldFlag = FALSE; wdCancel (dhcpcBootLeaseData.timer); /* Reset watchdog timer. */ dhcpcMsgLength = make_discover (); /* Create DHCP_DISCOVER message. */ /* * Random delay from one to ten seconds to avoid startup congestion. * (Delay length specified in RFC 1541). * */ taskDelay (sysClkRateGet () * (1 + (rand () % INIT_WAITING)) ); dhcpcMsgOut.dhcp->secs = 0; dhcpcMsgOut.udp->uh_sum = 0; dhcpcMsgOut.udp->uh_sum = udp_cksum (&spudph, (char *)dhcpcMsgOut.udp, ntohs (spudph.ulen));#ifdef DHCPC_DEBUG logMsg ("Sending DHCPDISCOVER\n", 0, 0, 0, 0, 0, 0);#endif /* * Retransmit the message using a link-level broadcast address, which * prevents ARP messages if using Ethernet devices and allows transmission * from interfaces without assigned IP addresses. */ bzero ( (char *)&dest, sizeof (struct sockaddr_in)); dest.sin_len = sizeof (struct sockaddr_in); dest.sin_family = AF_INET; dest.sin_addr.s_addr = dhcpcMsgOut.ip->ip_dst.s_addr; if (dhcpSend (dhcpcIntface.iface, &dest, sbuf.buf, dhcpcMsgLength, TRUE) == ERROR) {#ifdef DHCPC_DEBUG logMsg("Can't send DHCPDISCOVER\n", 0, 0, 0, 0, 0, 0);#endif return (-1); } dhcpcBootLeaseData.timeout = FIRSTTIMER; dhcpcBootLeaseData.numRetry = 0; if (dhcpTime (&dhcpcBootLeaseData.initEpoch) == -1) {#ifdef DHCPC_DEBUG logMsg ("time() error setting initEpoch\n", 0, 0, 0, 0, 0, 0);#endif return (ERROR); } /* Set timer to randomized exponential backoff before retransmission. */ wdStart (dhcpcBootLeaseData.timer, sysClkRateGet() * SLEEP_RANDOM (dhcpcBootLeaseData.timeout), (FUNCPTR)retrans_wait_offer, 0); return (WAIT_OFFER); /* Next state is WAIT_OFFER */ }/********************************************************************************* dhcpcBootWaitOffer - Initial offering state of client finite state machine** This routine implements the initial part of the second state of the finite * state machine. It waits until the current timeout value to receive a lease * offer from a DHCP server. If a timeout occurs, the DHCP offer message is * retransmitted.** RETURNS: Next state of state machine, or -1 if error.** ERRNO: N/A** NOMANUAL*/LOCAL int dhcpcBootWaitOffer ( void ) { int arpans = 0; char errmsg [255]; char * pOption; int timer = 0; int retry = 0; struct dhcp_param * pParams = NULL; char * pMsgData; int status; EVENT_DATA msgEvent; bzero (errmsg, sizeof (errmsg));#ifdef DHCPC_DEBUG logMsg ("dhcpc: Entered WAIT_OFFER state.\n", 0, 0, 0, 0, 0, 0);#endif if (dhcpcPrevState == INIT) { /* Clear any previous parameter settings. */ if (dhcpcBootParam != NULL) { clean_param (dhcpcBootParam); free (dhcpcBootParam); dhcpcBootParam = NULL; } } /* Wait for message or retransmission. */ semTake (dhcpcEventSem, WAIT_FOREVER); status = rngBufGet (dhcpcEventRing, (char *)&msgEvent, sizeof (msgEvent)); if (status != sizeof (msgEvent)) { /* Expected event missing or incomplete - remain in current state. */#ifdef DHCPC_DEBUG logMsg ("dhcpWaitOffer: Notification error.\n", 0, 0, 0, 0, 0, 0);#endif return (WAIT_OFFER); } if (msgEvent.type == DHCP_TIMEOUT) { /* Handle timeout - no DHCP offers received yet. */ retry = dhcpcBootLeaseData.numRetry; timer = dhcpcBootLeaseData.timeout; retry++; if (retry == DISCOVER_RETRANS) {#ifdef DHCPC_DEBUG logMsg ("No lease offers received by client.\n", 0, 0, 0, 0, 0, 0);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -