📄 dhcpcboot.c
字号:
/* * No response to new DHCP message format, which can be ignored * by older DHCP servers as too short. Try the earlier format, * which padded the options field to a minimum length. If * successful, all subsequent messages will add that padding. * The initialization guarantees that the transmit buffer can * store the padded message. */ if (!dhcpcOldFlag && dhcpcMsgLength < (DFLTDHCPLEN + UDPHL + IPHL)) { dhcpcOldFlag = TRUE; dhcpcMsgLength = make_discover (); timer = FIRSTTIMER / 2; /* Counteract later doubling. */ retry = 0; } else return (ERROR); } /* Retransmission required - return after sending message. */ switch (gen_retransmit ()) { case 0: /* Transmission successful. */#ifdef DHCPC_DEBUG logMsg ("retransmit DHCPDISCOVER\n", 0, 0, 0, 0, 0, 0);#endif break; case -1: /* Couldn't update timing data */#ifdef DHCPC_DEBUG logMsg ("time() error retransmitting DHCPDISCOVER\n", 0, 0, 0, 0, 0, 0);#endif break; case -2: /* Transmission error in output routine */#ifdef DHCPC_DEBUG logMsg ("Can't retransmit DHCPDISCOVER\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_wait_offer, 0); dhcpcBootLeaseData.timeout = timer; dhcpcBootLeaseData.numRetry = retry; } else { /* * 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 = msgEvent.pMsg; msgAlign (&dhcpcMsgIn, pMsgData); /* Examine type of message. Accept DHCP offers or BOOTP replies. */ pOption = (char *)pickup_opt (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), _DHCP_MSGTYPE_TAG); if (pOption == NULL) { /* * Message type not found - check message length. Ignore * untyped DHCP messages, but accept (shorter) BOOTP replies. * This test might still treat (illegal) untyped DHCP messages * like BOOTP messages if they are short enough, but that case * can't be avoided. Mark the message buffer available after * handling the last DHCP message. */ if (DHCPLEN (dhcpcMsgIn.udp) > DFLTBOOTPLEN) { if (msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (WAIT_OFFER); } } else { if (*OPTBODY (pOption) != DHCPOFFER) { /* * Ignore messages with unexpected types. Mark the message * buffer available after handling the last DHCP message. */ if (msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (WAIT_OFFER); } } /* Allocate memory for configuration parameters. */ pParams = (struct dhcp_param *)calloc (1, sizeof (struct dhcp_param)); if (pParams == NULL) { /* * Memory for configuration parameters is unavailable. Remain * in current state. Mark the message buffer available after * handling the last DHCP message. */ if (msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (WAIT_OFFER); } /* Fill in host requirements defaults. */ dhcpcDefaultsSet (pParams); /* Check offered parameters. Copy to parameter list if acceptable. */ if (dhcp_msgtoparam (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), pParams) == OK) { /* * Accept static BOOTP address or verify that the * address offered by the DHCP server is available * and check offered lease length against minimum value. */ if ( (pParams->msgtype == DHCP_BOOTP || pParams->server_id.s_addr != 0) && (arpans = arp_check (&pParams->yiaddr, &dhcpcIntface)) == OK && pParams->lease_duration >= dhcpcMinLease) { /* * Initial offer accepted. Set client session * to execute next routine and start timer. */ pParams->lease_origin = dhcpcBootLeaseData.initEpoch; dhcpcBootParam = pParams; /* * Reset timer from retransmission interval * to limit for collecting replies. */ wdCancel (dhcpcBootLeaseData.timer); wdStart (dhcpcBootLeaseData.timer, sysClkRateGet() * dhcpcBootLeaseData.leaseReqSpec.waitsecs, (FUNCPTR)alarm_selecting, 0); /* * Mark the message buffer available after handling the * last DHCP message. */ if (msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (SELECTING); /* Next state is SELECTING */ } else { /* * Offer is insufficient. Remove stored parameters * and remain in current state. */ clean_param (pParams); free (pParams); } } else { /* Conversion unsuccessful - remove any stored parameters. */ clean_param (pParams); free (pParams); } } /* * No valid offer received yet. Next state is (still) WAIT_OFFER. Mark * the message buffer available after handling the last DHCP message. */ if (msgEvent.type == DHCP_MSG_ARRIVED && msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (WAIT_OFFER); }/********************************************************************************* dhcpcBootSelecting - Second offering state of client finite state machine** This routine continues the second state of the finite state machine. * It compares additional offers received from DHCP servers to the current* offer, and selects the offer which provides the lognest lease. When* the time limit specified by the DHCPC_OFFER_TIMEOUT definition passes, * processing of the selected DHCP offer will continue with the requesting() * routine. If no DHCP offers were received, the BOOTP reply selected by the * wait_offer() routine will be used by the bootstrap loader.** RETURNS: Next state of state machine, or -1 if error.** ERRNO: N/A** NOMANUAL*/LOCAL int dhcpcBootSelecting ( void ) { int arpans = 0; struct dhcp_param * pParams = NULL; char * pMsgData; char * pOption; EVENT_DATA msgEvent; int status; struct sockaddr_in dest;#ifdef DHCPC_DEBUG logMsg ("dhcp: Entered SELECTING state.\n", 0, 0, 0, 0, 0, 0);#endif /* Wait for message or timer expiration. */ semTake (dhcpcEventSem, WAIT_FOREVER); status = rngBufGet (dhcpcEventRing, (char *) &msgEvent, sizeof (msgEvent)); if (status != sizeof (msgEvent)) { /* Expected event missing or incomplete - remain in current state. */ return (SELECTING); } if (msgEvent.type == DHCP_TIMEOUT) { /* * Collection time expired - * parameters structure holds chosen offer. */ /* No response is needed if a BOOTP reply is chosen. */ if (dhcpcBootParam->msgtype == DHCP_BOOTP) { dhcpcBindType = DHCP_BOOTP; return (BOUND); } dhcpcMsgLength = make_request (dhcpcBootParam, REQUESTING); if (dhcpcMsgLength < 0) {#ifdef DHCPC_DEBUG logMsg ("Error making DHCP request. Entering INIT state.\n", 0, 0, 0, 0, 0, 0);#endif return (INIT); } dhcpcMsgOut.udp->uh_sum = 0; dhcpcMsgOut.udp->uh_sum = udp_cksum (&spudph, (char *) dhcpcMsgOut.udp, ntohs (spudph.ulen)); /* * 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 DHCPREQUEST\n", 0, 0, 0, 0, 0, 0);#endif return (INIT); } /* * DHCP request sent. Set client session to execute next state and * start the retransmission timer. */ dhcpcBootLeaseData.timeout = FIRSTTIMER; dhcpcBootLeaseData.numRetry = 0; wdStart (dhcpcBootLeaseData.timer, sysClkRateGet() * SLEEP_RANDOM (dhcpcBootLeaseData.timeout), (FUNCPTR)retrans_requesting, 0); return (REQUESTING); } else { /* * 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 = msgEvent.pMsg; msgAlign (&dhcpcMsgIn, pMsgData); /* Examine type of message. Only accept DHCP offers. */ pOption = (char *)pickup_opt (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), _DHCP_MSGTYPE_TAG); if (pOption == NULL) { /* * Message type not found - discard untyped DHCP messages, and * any BOOTP replies. Mark the message buffer available after * handling the last DHCP message. */ if (msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (SELECTING); } else { if (*OPTBODY (pOption) != DHCPOFFER) { /* * Ignore messages with unexpected types. Mark the message * buffer available after handling the last DHCP message. */ if (msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (SELECTING); } } /* Allocate memory for configuration parameters. */ pParams = (struct dhcp_param *)calloc (1, sizeof (struct dhcp_param)); if (pParams == NULL) { /* * Memory for configuration parameters is unavailable. Remain * in current state. Mark the message buffer available after * handling the last DHCP message. */ if (msgEvent.lastFlag) dhcpcMessageList [msgEvent.slot].writeFlag = TRUE; return (SELECTING); } /* Fill in host requirements defaults. */ dhcpcDefaultsSet (pParams); /* Switch to offered parameters if they provide a longer DHCP lease. */ if (dhcp_msgtoparam (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), pParams) == OK) { if (pParams->server_id.s_addr != 0 && (arpans = arp_check (&pParams->yiaddr, &dhcpcIntface)) == OK && pParams->lease_duration >= dhcpcMinLease) { /* Take any DHCP message over BOOTP, or take a longer lease. */ if (dhcpcBootParam->msgtype == DHCP_BOOTP || pParams->lease_duration > dhcpcBootParam->lease_duration) { pParams->lease_origin = dhcpcBootLeaseData.initEpoch; clean_param (dhcpcBootParam); free (dhcpcBootParam); dhcpcBootParam = pParams; } } else { /* * Offer is insufficient. Remove stored parameters * and remain in current state. */ clean_param (pParams); free (pParams); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -