📄 dhcpcstate2.c
字号:
/* * 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); } } if (pLeaseData->leaseType == DHCP_AUTOMATIC) { /* Get parameters previously read from bootline. */ bcopy ( (char *)&dhcpcBootLease.yiaddr, (char *)&pLeaseData->dhcpcParam->yiaddr, sizeof (struct in_addr)); origin = dhcpcBootLease.lease_origin; pLeaseData->dhcpcParam->lease_duration = dhcpcBootLease.lease_duration; pLeaseData->dhcpcParam->dhcp_t1 = pLeaseData->dhcpcParam->lease_duration / 2; SETBIT (pLeaseData->dhcpcParam->got_option, _DHCP_T1_TAG); /* Set t2 to .875 of lease without using floating point. */ tmp = (pLeaseData->dhcpcParam->lease_duration * 7) >> 3; pLeaseData->dhcpcParam->dhcp_t2 = (unsigned long)tmp; SETBIT (pLeaseData->dhcpcParam->got_option, _DHCP_T2_TAG); } else /* Get parameters from cached message. */ { /* Host requirements defaults. */ dhcpcDefaultsSet (pLeaseData->dhcpcParam); if (dhcp_msgtoparam (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), pLeaseData->dhcpcParam) != OK) {#ifdef DHCPC_DEBUG logMsg("dhcp_msgtoparam() error in init_reboot()\n", 0, 0, 0, 0, 0, 0);#endif clean_param (pLeaseData->dhcpcParam); free (pLeaseData->dhcpcParam); pLeaseData->dhcpcParam = NULL; pLeaseData->prevState = INIT_REBOOT; pLeaseData->currState = INIT; return (DHCPC_MORE); } } pLeaseData->dhcpcParam->lease_origin = origin; /* * If the cache contained a BOOTP reply, no further processing is needed. * Set the lease type to prevent the inclusion of timing information in * the bootline so that a later reboot will not attempt to renew the lease. */ if (pLeaseData->leaseType == DHCP_MANUAL && pLeaseData->dhcpcParam->msgtype == DHCP_BOOTP) { pLeaseData->leaseType = DHCP_BOOTP; pLeaseData->prevState = INIT_REBOOT; pLeaseData->currState = BOUND; 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; pLeaseData->prevState = INIT_REBOOT; pLeaseData->currState = INIT; } else { pLeaseData->leaseGood = TRUE; } semGive (dhcpcMutexSem); if (status != 0) return (DHCPC_MORE); return (OK); } /* The cache contained the record of a DHCP lease. Send the request. */ length = make_request (pLeaseData, REBOOTING, TRUE); if (length < 0) {#ifdef DHCPC_DEBUG logMsg("error constructing REBOOTING message. Entering INIT state.\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->prevState = INIT_REBOOT; 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(REBOOTING)\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->prevState = INIT_REBOOT; pLeaseData->currState = INIT; return (DHCPC_MORE); } /* Set lease data to execute next state and start retransmission timer. */ pLeaseData->prevState = INIT_REBOOT; pLeaseData->currState = REBOOTING; pLeaseData->timeout = FIRSTTIMER; pLeaseData->numRetry = 0; wdStart (pLeaseData->timer, sysClkRateGet() * SLEEP_RANDOM (pLeaseData->timeout), (FUNCPTR)retrans_reboot_verify, (int)pLeaseData); return (OK); }/********************************************************************************* verify - Initial lease verification state of client finite state machine** This routine begins the verification process by broadcasting a DHCP verify* message. It is called in response to the user request generated by the* dhcpcVerify() routine in the API.** RETURNS: OK (processing complete), ERROR (failure), or DHCPC_MORE (continue).** ERRNO: N/A** NOMANUAL*/int verify ( EVENT_DATA * pEvent /* pointer to event descriptor */ ) { int limit = 0; int length; time_t curr_epoch; LEASE_DATA * pLeaseData; struct sockaddr_in dest; struct ifnet * pIf; struct ifreq ifr; if (dhcpTime (&curr_epoch) == -1) {#ifdef DHCPC_DEBUG logMsg ("time() error in verify()\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); } /* * The interval between the user request and the entry to the verify() * routine depends on the workload of the client monitor task and the * status of the lease timers. The lease may have expired before this * routine executes, which will cause the negotiation process to restart * with the init() routine. */ limit = pLeaseData->dhcpcParam->lease_origin + pLeaseData->dhcpcParam->lease_duration; if (limit <= curr_epoch) { pLeaseData->prevState = VERIFY; pLeaseData->currState = INIT; return (DHCPC_MORE); } length = make_request (pLeaseData, VERIFYING, TRUE); if (length < 0) {#ifdef DHCPC_DEBUG logMsg("Unable to construct verify message. Entering INIT state.\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->prevState = VERIFY; pLeaseData->currState = INIT; return (DHCPC_MORE); } dhcpcMsgOut.udp->uh_sum = 0; dhcpcMsgOut.udp->uh_sum = udp_cksum (&spudph, (char *)dhcpcMsgOut.udp, ntohs (spudph.ulen)); if (dhcpTime (&pLeaseData->initEpoch) == -1) {#ifdef DHCPC_DEBUG logMsg ("time() error setting initEpoch\n", 0, 0, 0, 0, 0, 0);#endif return (ERROR); } 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(VERIFY)\n", 0, 0, 0, 0, 0, 0);#endif pLeaseData->prevState = VERIFY; pLeaseData->currState = INIT; return (DHCPC_MORE); } /* Set lease data to execute next state and start retransmission timer. */ pLeaseData->prevState = VERIFY; pLeaseData->currState = VERIFYING; pLeaseData->timeout = FIRSTTIMER; pLeaseData->numRetry = 0; wdStart (pLeaseData->timer, sysClkRateGet() * SLEEP_RANDOM (pLeaseData->timeout), (FUNCPTR)retrans_reboot_verify, (int)pLeaseData); return (OK); /* Next state is REBOOT_VERIFY */ }/********************************************************************************* reboot_verify - Final lease verification state of client finite state machine** This routine continues the verification process of the finite state machine* by waiting for a server response until the current timeout value expires.* If a timeout occurs, the DHCP message is retransmitted. This routine collects* the replies for manual lease renewals and lease renewals resulting from a* reboot of the client.** RETURNS: OK (processing complete), DHCPC_DONE (remove lease),* DHCPC_MORE (continue
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -