📄 dhcpcstate2.c
字号:
int msgtype; int status; struct dhcp_param tmpparam;#ifdef DHCPC_DEBUG char newAddr[INET_ADDR_LEN];#endif LEASE_DATA *pLeaseData; char *pMsgData; int length; struct sockaddr_in dest; struct ifnet *pIf; struct ifreq ifr; bzero (errmsg, sizeof (errmsg)); bzero ((char *) &tmpparam, sizeof (tmpparam)); if (dhcpTime (&curr_epoch) == -1) {#ifdef DHCPC_DEBUG logMsg ("time() error in rebinding()\n", 0, 0, 0, 0, 0, 0);#endif return (ERROR); } /* * Use the cookie to access the lease-specific data structures. For now, * just typecast the cookie. This translation could be replaced with a more * sophisticated lookup at some point. */ pLeaseData = (LEASE_DATA *) pEvent->leaseId; if (pLeaseData->prevState == BOUND) { /* Resume filtering with the BPF device (suspended while bound). */ bzero ((char *) &ifr, sizeof (struct ifreq)); sprintf (ifr.ifr_name, "%s%d", pLeaseData->ifData.iface->if_name, pLeaseData->ifData.iface->if_unit); ioctl (pLeaseData->ifData.bpfDev, BIOCSTART, (int) &ifr); } if (pEvent->source == DHCP_AUTO_EVENT) { if (pEvent->type == DHCP_TIMEOUT) { /* * The interval between a timeout event and the entry to the * rebinding() routine depends on the workload of the client * monitor task and is completely unpredictable. The lease * may have expired during that time, and the final retransmission * timeout will always end after the lease has expired. In either * case, set the lease data to restart the negotiation with the * init() routine. Otherwise, repeat the broadcast of the request * message. */ limit = pLeaseData->dhcpcParam->lease_origin + pLeaseData->dhcpcParam->lease_duration; if (limit <= curr_epoch) { /* Lease has expired: * shut down network and return to initial state. */#ifdef DHCPC_DEBUG logMsg ("Can't extend lease. Entering INIT state.\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->prevState = REBINDING; pLeaseData->currState = INIT; return (DHCPC_MORE); } /* Retransmit rebinding request. */ length = make_request (pLeaseData, REBINDING, FALSE); if (length < 0) {#ifdef DHCPC_DEBUG logMsg ("Error making rebind request. Entering INIT state.\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->prevState = REBINDING; pLeaseData->currState = INIT; return (DHCPC_MORE); } dhcpcMsgOut.udp->uh_sum = 0; dhcpcMsgOut.udp->uh_sum = udp_cksum (&spudph, (char *) dhcpcMsgOut.udp, ntohs (spudph.ulen)); 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; pIf = pLeaseData->ifData.iface; if (dhcpSend (pIf, &dest, sbuf.buf, length, TRUE) == ERROR) {#ifdef DHCPC_DEBUG logMsg ("Can't send DHCPREQUEST(REBINDING)\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->prevState = REBINDING; pLeaseData->currState = INIT; return (DHCPC_MORE); } /* DHCP request sent. Set lease data to repeat current state. */ pLeaseData->prevState = REBINDING; pLeaseData->currState = REBINDING; pLeaseData->initEpoch = curr_epoch; /* * Set the retransmission timer to wait for one-half of the * remaining time before the lease expires, or 60 seconds if it * expires in less than one minute. */ timeout = pLeaseData->dhcpcParam->lease_origin + pLeaseData->dhcpcParam->lease_duration - curr_epoch; timeout /= 2; if (timeout < 60) timeout = 60; /* Set timer for retransmission of request message. */ wdStart (pLeaseData->timer, sysClkRateGet () * timeout, (FUNCPTR) retrans_rebinding, (int) pLeaseData); } /* End of timeout processing. */ 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 = pLeaseData->msgBuffer; align_msg (&dhcpcMsgIn, pMsgData); /* Examine type of message. Accept DHCPACK or DHCPNAK replies. */ option = (char *) pickup_opt (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), _DHCP_MSGTYPE_TAG); if (option == NULL) { /* * Message type not found - ignore untyped DHCP messages, and * any BOOTP replies. */ return (OK); } else { msgtype = *OPTBODY (option); if (msgtype == DHCPNAK) {#ifdef DHCPC_DEBUG logMsg ("Got DHCPNAK in rebinding()\n", 0, 0, 0, 0, 0, 0); option = (char *) pickup_opt (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), _DHCP_ERRMSG_TAG); if (option != NULL && nvttostr (OPTBODY (option), errmsg, (int) DHCPOPTLEN (option)) == 0) logMsg ("DHCPNAK contains the error message \"%s\"\n", (int) errmsg, 0, 0, 0, 0, 0);#endif clean_param (pLeaseData->dhcpcParam); free (pLeaseData->dhcpcParam); pLeaseData->dhcpcParam = NULL; pLeaseData->prevState = REBINDING; pLeaseData->currState = INIT; return (DHCPC_MORE); } else if (msgtype == DHCPACK) { /* Fill in host requirements defaults. */ dhcpcDefaultsSet (&tmpparam); if (dhcp_msgtoparam (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), &tmpparam) == OK) { merge_param (pLeaseData->dhcpcParam, &tmpparam); *(pLeaseData->dhcpcParam) = tmpparam; pLeaseData->dhcpcParam->lease_origin = pLeaseData->initEpoch;#ifdef DHCPC_DEBUG inet_ntoa_b (pLeaseData->dhcpcParam->yiaddr, newAddr); logMsg ("Got DHCPACK (IP = %s, duration = %d secs)\n", (int) newAddr, pLeaseData->dhcpcParam->lease_duration, 0, 0, 0, 0);#endif status = use_parameter (pLeaseData->dhcpcParam, pLeaseData); semTake (dhcpcMutexSem, WAIT_FOREVER); if (status != 0) {#ifdef DHCPC_DEBUG logMsg ("Error configuring network. Shutting down.\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->leaseGood = FALSE; } else { pLeaseData->leaseGood = TRUE; } semGive (dhcpcMutexSem); pLeaseData->prevState = REBINDING; pLeaseData->currState = BOUND; } return (DHCPC_MORE); } } /* End of processing for typed DHCP message. */ } /* End of DHCP message processing. */ } else { /* Process user requests. */ if (pEvent->type == DHCP_USER_RELEASE) { /* Relinquish lease. */ release (pLeaseData, TRUE); return (DHCPC_DONE); } if (pEvent->type == DHCP_USER_VERIFY) { /* Verify lease. */ /* Set the lease data to execute verify() routine. */ pLeaseData->prevState = REBINDING; pLeaseData->currState = VERIFY; return (DHCPC_MORE); } } return (OK);}/********************************************************************************* init_reboot - Rebooting state of the client finite state machine** This routine implements the "zeroth" state of the client finite state* machine. It attempts to renew an active lease after the client has* rebooted. This generally requires the presence of a cache, but the lease* data may also be read from global variables to renew the lease obtained* during system startup. If no lease data is found or renewal fails, processing* continues with the INIT state.* .IP* This routine is invoked by the event handler of the client monitor task,* and should only be called internally. Any user requests generated by* incorrect calls or delayed responses to the dhcpcVerify() routine are * ignored.** RETURNS: OK (processing complete), DHCPC_DONE (remove lease),* DHCPC_MORE (continue), or ERROR.** ERRNO: N/A** INTERNAL** When calculating the values for the lease timers, floating-point calculations* can't be used because some boards (notably the SPARC architectures) disable* software floating point by default to speed up context switching. These* boards abort with an exception when floating point operations are* encountered. The error introduced by the integer approximations is not* significant.** NOMANUAL*/int init_reboot (EVENT_DATA * pEvent /* pointer to event descriptor */ ){ char *rbufp = NULL; STATUS result; int length = 0; unsigned long origin = 0; int tmp; int status; struct sockaddr_in dest; struct ifnet *pIf; LEASE_DATA *pLeaseData = NULL; /* * Use the cookie to access the lease-specific data structures. For now, * just typecast the cookie. This translation could be replaced with a more * sophisticated lookup at some point. */ pLeaseData = (LEASE_DATA *) pEvent->leaseId; /* * The DHCP_USER_RELEASE event occurs in response to the dhcpcRelease() * or dhcpcShutdown() call. Remove all data structures for this lease. */ if (pEvent->type == DHCP_USER_RELEASE) { dhcpcLeaseCleanup (pLeaseData); return (DHCPC_DONE); } /* Ignore verify user events, which are meaningless here. */ if (pEvent->source == DHCP_USER_EVENT && pEvent->type != DHCP_USER_BIND) return (OK); /* * Safety check - ignore timeouts and message arrivals, which are * theoretically possible under extremely unlikely chains of events. */ if (pEvent->source == DHCP_AUTO_EVENT) return (OK); /* If a cache is needed and unavailable, restart from the INIT state. */ if (pLeaseData->cacheHookRtn == NULL && pLeaseData->leaseType == DHCP_MANUAL) { pLeaseData->prevState = INIT_REBOOT; pLeaseData->currState = INIT; return (DHCPC_MORE); }#ifdef DHCPC_DEBUG logMsg ("dhcpc: Attempting to re-use parameters.\n", 0, 0, 0, 0, 0, 0);#endif bzero (sbuf.buf, sbuf.size); /* * The client might have established a lease (during boot-time) with * an older DHCP server which ignores messages less than the minimum * length obtained with a fixed options field. Set this lease attempt * to pad the renewal request to the minimum size (for RFC 1541) to * avoid unnecessary retransmissions in that case. */ pLeaseData->oldFlag = TRUE; if (pLeaseData->leaseType == DHCP_MANUAL) { /* * Post-boot: read from cache into aligned scratch buffer * (used during other states to transmit DHCP messages). */ length = sbuf.size; rbufp = sbuf.buf; result = (*pLeaseData->cacheHookRtn) (DHCP_CACHE_READ, &origin, &length, rbufp); if (result != OK) { /* Can't re-use stored parameters. */ pLeaseData->prevState = INIT_REBOOT; pLeaseData->currState = INIT; return (DHCPC_MORE); } /* * Set the pointers to access the individual DHCP message components. */ dhcpcMsgIn.ip = (struct ip *) rbufp;#if BSD<44 dhcpcMsgIn.udp = (struct udphdr *) &rbufp[(dhcpcMsgIn.ip->ip_v_hl & 0xf) * WORD]; dhcpcMsgIn.dhcp = (struct dhcp *) &rbufp[(dhcpcMsgIn.ip->ip_v_hl & 0xf) * WORD + UDPHL];#else dhcpcMsgIn.udp = (struct udphdr *) &rbufp[dhcpcMsgIn.ip->ip_hl * WORD]; dhcpcMsgIn.dhcp = (struct dhcp *) &rbufp[dhcpcMsgIn.ip->ip_hl * WORD + UDPHL];#endif } if (pLeaseData->dhcpcParam == NULL) { pLeaseData->dhcpcParam = (struct dhcp_param *) calloc (1, sizeof (struct dhcp_param)); if (pLeaseData->dhcpcParam == NULL) {#ifdef DHCPC_DEBUG logMsg ("calloc() error in init_reboot()\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->prevState = INIT_REBOOT; pLeaseData->currState = INIT; return (DHCPC_MORE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -