📄 dhcpcboot.c
字号:
/* Redirect incoming packets. */ if (muxDevExists (dhcpcDevice.name, dhcpcDevice.unit)) etherInputHookAdd (dhcpcBootOfferInputHook, dhcpcDevice.name, dhcpcDevice.unit); else etherInputHookAdd (dhcpcBootOfferInputHook, NULL, dhcpcDevice.unit); /* Clear any previous parameter settings. */ if (dhcpcBootParam != NULL) { clean_param (dhcpcBootParam); free (dhcpcBootParam); dhcpcBootParam = NULL; } } else if (retry == DISCOVER_RETRANS) {#ifdef DHCPC_DEBUG logMsg ("No lease offers received by client.\n", 0, 0, 0, 0, 0, 0);#endif return (-1); } else if (timer < MAXTIMER) { /* Double retransmission delay with each attempt. (RFC 1541). */ timer *= 2; } wdCancel (dhcpcBootEventTimer); /* Reset timer. */ /* Set timer to randomized exponential backoff before retransmission. */ wdStart (dhcpcBootEventTimer, sysClkRateGet() * SLEEP_RANDOM (timer), (FUNCPTR)netJobAdd, (int)retrans_wait_offer); /* * Wait for incoming message. Exit when processed successfully or when * retransmission occurs. */ FOREVER { /* Wait for message or retransmission. */ semTake (dhcpcBootEventSem, WAIT_FOREVER); /* Error adding notification. */ if (rngIsEmpty (dhcpcBootEventRing) == TRUE) {#ifdef DHCPC_DEBUG logMsg ("dhcpWaitOffer: Notification empty.\n", 0, 0, 0, 0, 0, 0);#endif status = DHCP_TIMEOUT; /* Treat error like timeout. */ break; } status = rngBufGet (dhcpcBootEventRing, (char *)&msgEvent, sizeof (msgEvent)); if (status != sizeof (msgEvent)) {#ifdef DHCPC_DEBUG logMsg ("dhcpWaitOffer: Notification error.\n", 0, 0, 0, 0, 0, 0);#endif status = DHCP_TIMEOUT; /* Treat error like timeout. */ break; } if (msgEvent.type == DHCP_TIMEOUT) /* Retransmission - exit. */ { status = DHCP_TIMEOUT; break; } /* * Process DHCP message. Access receive buffer at offset to provide * 4-byte alignment of IP header needed by Sun BSP's. */ status = rngBufGet (dhcpcBootMsgRing, &rbuf.buf [DHCPC_OFF], msgEvent.length); /* Error reading DHCP message - ignore. */ if (status != msgEvent.length) continue; msgAlign (&dhcpcMsgIn, &rbuf.buf [DHCPC_OFF]); /* allocate memory for dhcp_param */ paramp = (struct dhcp_param *)calloc (1, sizeof (struct dhcp_param)); if (paramp == NULL) continue; dhcpcBootDefaultsSet (paramp); /* Fill in required host defaults. */ /* * Store received options in dhcp_param structure. Copy to * parameter list if acceptable. */ if (dhcp_msgtoparam (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), paramp) == OK) { if ( (paramp->msgtype == DHCP_BOOTP || paramp->server_id.s_addr != 0) && (arpans = arp_check (¶mp->yiaddr)) == OK && paramp->lease_duration >= dhcpcBootMinLease) { paramp->lease_origin = dhcpcInitEpoch; dhcpcBootParam = paramp; return (SELECTING); /* Next state is SELECTING */ } else { clean_param (paramp); free (paramp); paramp = NULL; } } else { /* Conversion unsuccessful - remove any stored parameters. */ clean_param (paramp); free (paramp); paramp = NULL; } } #ifdef DHCPC_DEBUG if (status == DHCP_TIMEOUT) /* Retransmission occurred. */ logMsg("dhcp: timed out in WAIT_OFFER state.\n", 0, 0, 0, 0, 0, 0);#endif retry++; return (WAIT_OFFER); /* Next state is 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 * paramp = NULL; EVENT_DATA msgEvent; int status;#ifdef DHCPC_DEBUG logMsg ("dhcp: Entered SELECTING state.\n", 0, 0, 0, 0, 0, 0);#endif /* Reset timer. */ wdCancel (dhcpcBootEventTimer); /* Collect incoming DHCP offers. */ /* Set timer to limit for collecting replies. */ wdStart (dhcpcBootEventTimer, sysClkRateGet() * dhcpcBootReqSpec.waitsecs, (FUNCPTR) netJobAdd, (int)alarm_selecting); FOREVER { /* Wait for message or timer expiration. */ semTake (dhcpcBootEventSem, WAIT_FOREVER); if (rngIsEmpty (dhcpcBootEventRing) == TRUE) { status = DHCP_TIMEOUT; /* Treat error like timeout. */ break; } status = rngBufGet (dhcpcBootEventRing, (char *) &msgEvent, sizeof (msgEvent)); if (status != sizeof (msgEvent)) { status = DHCP_TIMEOUT; /* Treat error like timeout. */ break; } /* Collection time expired - exit. */ if (msgEvent.type == DHCP_TIMEOUT) { status = DHCP_TIMEOUT; break; } /* * Process DHCP message. Access receive buffer at offset to provide * 4-byte alignment of IP header needed by Sun BSP's. */ status = rngBufGet (dhcpcBootMsgRing, &rbuf.buf [DHCPC_OFF], msgEvent.length); if (status != msgEvent.length) /* Error reading message - ignore. */ continue; msgAlign (&dhcpcMsgIn, &rbuf.buf [DHCPC_OFF]); /* Allocate memory for parameters structure. */ paramp = (struct dhcp_param *)calloc (1, sizeof (struct dhcp_param)); if (paramp == NULL) continue; dhcpcBootDefaultsSet (paramp); /* Fill in required host defaults. */ /* Switch to offered parameters if they provide a longer DHCP lease. */ if (dhcp_msgtoparam (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), paramp) == OK) { if (paramp->msgtype != DHCP_BOOTP && paramp->server_id.s_addr != 0 && (arpans = arp_check (¶mp->yiaddr)) == OK && paramp->lease_duration >= dhcpcBootMinLease) { /* Take any DHCP message over BOOTP, or take a longer lease. */ if (dhcpcBootParam->msgtype == DHCP_BOOTP || paramp->lease_duration > dhcpcBootParam->lease_duration) { paramp->lease_origin = dhcpcInitEpoch; clean_param (dhcpcBootParam); free (dhcpcBootParam); dhcpcBootParam = paramp; } } else { /* Parameters in structure not valid. */ clean_param (paramp); free (paramp); paramp = NULL; } } else { /* Couldn't convert parameters to structure. */ clean_param (paramp); free (paramp); paramp = NULL; } } /* 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); } if (make_request (dhcpcBootParam, REQUESTING) < 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)); if (etherOutput (dhcpcIntface.iface, dhcpcMsgOut.ether, &sbuf.buf [DHCPC_OFF + ETHERHL], sbuf.size - ETHERHL) == ERROR) {#ifdef DHCPC_DEBUG logMsg ("Can't send DHCPREQUEST\n", 0, 0, 0, 0, 0, 0);#endif return (INIT); } return (REQUESTING); }/********************************************************************************* 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. 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 ) { int arpans = 0; char *option = NULL; char errmsg[255]; static int timer = 0; static int retry = 0; struct dhcp_param tmpparam; struct dhcp_reqspec tmp_reqspec; EVENT_DATA newEvent; int status;#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 *)&tmpparam, sizeof (tmpparam)); bzero ( (char *)&tmp_reqspec, sizeof (tmp_reqspec)); if (dhcpcPrevState == SELECTING) { timer = FIRSTTIMER; /* Replace packet filter from earlier states. */ if (muxDevExists (dhcpcDevice.name, dhcpcDevice.unit)) { etherInputHookDelete (dhcpcBootOfferInputHook, dhcpcDevice.name, dhcpcDevice.unit); etherInputHookAdd (dhcpcBootReplyInputHook, dhcpcDevice.name, dhcpcDevice.unit); } else { etherInputHookDelete (dhcpcBootOfferInputHook, NULL, dhcpcDevice.unit); etherInputHookAdd (dhcpcBootReplyInputHook, NULL, dhcpcDevice.unit); } retry = 0; } else 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 return (INIT); /* Next state is INIT */ } else if (timer < MAXTIMER) /* Double retransmission delay with each attempt. (RFC 1541). */ timer *= 2; /* Reset timer. */ wdCancel (dhcpcBootEventTimer); /* Set timer to randomized exponential backoff before retransmission. */ wdStart (dhcpcBootEventTimer, sysClkRateGet() * SLEEP_RANDOM(timer), (FUNCPTR) netJobAdd, (int)retrans_requesting); /* * Wait for server response. Exit when processed successfully or when * retransmission occurs. */ FOREVER { bzero ( (char *)&tmpparam, sizeof (tmpparam)); /* Wait for server response or retransmission. */ semTake (dhcpcBootEventSem, WAIT_FOREVER); if (rngIsEmpty (dhcpcBootEventRing) == TRUE) { status = DHCP_TIMEOUT; /* Treat error like timeout. */ break; } status = rngBufGet (dhcpcBootEventRing, (char *)&newEvent, sizeof (newEvent)); if (status != sizeof (newEvent)) { status = DHCP_TIMEOUT; /* Treat error like timeout. */ break; } if (newEvent.type == DHCP_TIMEOUT) /* Retransmission - exit. */ { status = DHCP_TIMEOUT; break; } /* * Process DHCP message. Access receive buffer at offset to provide * 4-byte alignment of IP header needed by Sun BSP's. */ status = rngBufGet (dhcpcBootMsgRing, &rbuf.buf [DHCPC_OFF],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -