📄 dhcpcboot.c
字号:
} if (*OPTBODY (option) != DHCPOFFER) return (0); return (1); }/********************************************************************************* check_requesting - verify that a received packet is a DHCP server reply** This routine examines an IP message received at the DHCP client port to* determine if it is a DHCP server reply. It is used internally by the* Ethernet input hook from the REQUESTING state onward.** RETURNS: 1 if message recognized, or 0 otherwise.** ERRNO: N/A** NOMANUAL*/int check_requesting ( void ) { u_short ripcksum = 0; u_short rudpcksum = 0; struct ps_udph rpudph; /* Check if UDP and DHCP portions are present (set by msgAlign). */ if (dhcpcRbufMsg.udp == NULL || dhcpcRbufMsg.dhcp == NULL) return (0); /* Construct a UDP pseudo-header. */ bzero ( (char *)&rpudph, sizeof (rpudph)); ripcksum = dhcpcRbufMsg.ip->ip_sum; dhcpcRbufMsg.ip->ip_sum = 0; rudpcksum = dhcpcRbufMsg.udp->uh_sum; dhcpcRbufMsg.udp->uh_sum = 0; rpudph.zero = 0; rpudph.prto = IPPROTO_UDP; rpudph.srcip.s_addr = dhcpcRbufMsg.ip->ip_src.s_addr; rpudph.dstip.s_addr = dhcpcRbufMsg.ip->ip_dst.s_addr; rpudph.ulen = dhcpcRbufMsg.udp->uh_ulen; /* Check lengths of each portion of message. */ if (ntohs (dhcpcRbufMsg.ip->ip_len) < DFLTBOOTPLEN + UDPHL + IPHL) return (0); if (ntohs (dhcpcRbufMsg.udp->uh_ulen) < DFLTBOOTPLEN + UDPHL) return (0); /* Verify message received at client port. */ if (dhcpcRbufMsg.udp->uh_dport != dhcpc_port) return (0); /* Check message IP checksum. */#if BSD<44 if (ripcksum != checksum ( (u_short *)dhcpcRbufMsg.ip, (dhcpcRbufMsg.ip->ip_v_hl & 0xf) << 2))#else if (ripcksum != checksum ( (u_short *)dhcpcRbufMsg.ip, dhcpcRbufMsg.ip->ip_hl << 2))#endif return (0); /* Check message UDP checksum. */ if (dhcpcRbufMsg.udp->uh_sum != 0 && rudpcksum != udp_cksum (&rpudph, (char *)dhcpcRbufMsg.udp, ntohs (rpudph.ulen))) return (0); /* Check DHCP message opcode, transaction ID, and magic cookie. */ if (dhcpcRbufMsg.dhcp->op != BOOTREPLY || dhcpcRbufMsg.dhcp->xid != dhcpcMsgOut.dhcp->xid) return (0); if (bcmp (dhcpcRbufMsg.dhcp->options, (char *)dhcpCookie, MAGIC_LEN) != 0) return (0); return (1); }/********************************************************************************* gen_retransmit - generic retransmission after timeout** This routine retransmits the current DHCP client message (a discover or* a request message) when the appropriate timeout interval expires.* It is called from multiple locations in the finite state machine.** RETURNS: 0 if transmission completed, or negative value on error.** ERRNO: N/A** NOMANUAL*/LOCAL int gen_retransmit ( void ) { time_t curr_epoch = 0; EVENT_DATA newEvent; int status; /* Construct and send a timeout message to the finite state machine. */ newEvent.type = DHCP_TIMEOUT; semTake (dhcpcBootRingSem, WAIT_FOREVER); status = rngBufPut (dhcpcBootEventRing, (char *)&newEvent, sizeof (newEvent)); semGive (dhcpcBootRingSem); semGive (dhcpcBootEventSem); if (status != sizeof (newEvent)) return (-3); if (time (&curr_epoch) == -1) return (-1); /* Update the appropriate fields in the current DHCP message. */ if (dhcpcCurrState != REQUESTING) dhcpcMsgOut.dhcp->secs = htons (curr_epoch - dhcpcInitEpoch); dhcpcMsgOut.dhcp->xid = generate_xid (); dhcpcMsgOut.udp->uh_sum = 0; dhcpcMsgOut.udp->uh_sum = udp_cksum (&spudph, (char *)dhcpcMsgOut.udp, ntohs (spudph.ulen)); /* * Retransmit the message. Access buffer at offset to allow * 4-byte alignment of IP header needed by Sun BSP's. */ if (etherOutput (dhcpcIntface.iface, dhcpcMsgOut.ether, &sbuf.buf [ETHERHL + DHCPC_OFF], sbuf.size - ETHERHL) == 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 ( void ) { if (dhcpcCurrState != WAIT_OFFER) return; switch (gen_retransmit ()) /* Attempt to retransmit current message. */ { 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 in retrans_wait_offer()\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; case -3: /* Error signalling state machine */#ifdef DHCPC_DEBUG logMsg ("Can't notify state machine\n", 0, 0, 0, 0, 0, 0);#endif break; default: break; } 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 ( void ) { EVENT_DATA newEvent; int status; if (dhcpcCurrState == SELECTING) { newEvent.type = DHCP_TIMEOUT; semTake (dhcpcBootRingSem, WAIT_FOREVER); status = rngBufPut (dhcpcBootEventRing, (char *) &newEvent, sizeof (newEvent)); semGive (dhcpcBootRingSem);#ifdef DHCPC_DEBUG if (status != sizeof (newEvent)) logMsg ("Warning: ring buffer overflow.\n", 0, 0, 0, 0, 0, 0);#endif semGive (dhcpcBootEventSem); /* Stop collection in state machine. */ } 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 ( void ) { time_t curr_epoch = 0; EVENT_DATA newEvent; int status; if (dhcpcCurrState != REQUESTING) return; /* Construct and send timeout notification to the finite state machine. */ newEvent.type = DHCP_TIMEOUT; semTake (dhcpcBootRingSem, WAIT_FOREVER); status = rngBufPut (dhcpcBootEventRing, (char *)&newEvent, sizeof (newEvent)); semGive (dhcpcBootRingSem); semGive (dhcpcBootEventSem); /* Update the appropriate fields in the request message. */ if (time (&curr_epoch) == -1) {#ifdef DHCPC_DEBUG logMsg("time() error in retrans_requesting()\n", 0, 0, 0, 0, 0, 0);#endif return; } 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 [ETHERHL + DHCPC_OFF], sbuf.size - ETHERHL) == ERROR) {#ifdef DHCPC_DEBUG logMsg ("Can't retransmit DHCPREQUEST(REQUESTING)\n", 0, 0, 0, 0, 0, 0);#endif return; }#ifdef DHCPC_DEBUG logMsg ("retransmit DHCPREQUEST(REQUESTING)\n", 0, 0, 0, 0, 0, 0);#endif return; }/********************************************************************************* 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 ) { bzero (sbuf.buf, sbuf.size + DHCPC_OFF);#ifdef DHCPC_DEBUG logMsg("dhcpc: Entered INIT state.\n", 0, 0, 0, 0, 0, 0);#endif /* Remove any prior input hooks. */ if (muxDevExists (dhcpcDevice.name, dhcpcDevice.unit)) { etherInputHookDelete (dhcpcBootOfferInputHook, dhcpcDevice.name, dhcpcDevice.unit); etherInputHookDelete (dhcpcBootReplyInputHook, dhcpcDevice.name, dhcpcDevice.unit); } else { etherInputHookDelete (dhcpcBootOfferInputHook, NULL, dhcpcDevice.unit); etherInputHookDelete (dhcpcBootReplyInputHook, NULL, dhcpcDevice.unit); } wdCancel (dhcpcBootEventTimer); /* Reset watchdog timer. */ 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 if (etherOutput (dhcpcIntface.iface, dhcpcMsgOut.ether, &sbuf.buf [DHCPC_OFF + ETHERHL], sbuf.size - ETHERHL) == ERROR) {#ifdef DHCPC_DEBUG logMsg("Can't send DHCPDISCOVER\n", 0, 0, 0, 0, 0, 0);#endif return (-1); } 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]; static int timer = 0; static int retry = 0; struct dhcp_param * paramp = NULL; 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) { timer = FIRSTTIMER; retry = 0; if (time (&dhcpcInitEpoch) == -1) {#ifdef DHCPC_DEBUG logMsg ("time() error in wait_offer()\n", 0, 0, 0, 0, 0, 0);#endif return (-1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -