⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcpcboot.c

📁 VxWorks下DHCP的源代码!
💻 C
📖 第 1 页 / 共 5 页
字号:
* 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 or the inform process will exit. 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){    STATUS result = OK;    char *pOption = NULL;    char errmsg[255];    int timer = 0;    int retry = 0;    struct dhcp_param tmpparam;    struct dhcp_reqspec tmp_reqspec;    EVENT_DATA newEvent;    char *pMsgData;    int status;    int msgtype;#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 *) &tmp_reqspec, sizeof (tmp_reqspec));    /* Wait for message or retransmission. */    semTake (dhcpcEventSem, WAIT_FOREVER);    status = rngBufGet (dhcpcEventRing, (char *) &newEvent, sizeof (newEvent));    if (status != sizeof (newEvent)) {        /* Expected event missing or incomplete - remain in current state. */        return (REQUESTING);    }    if (newEvent.type == DHCP_TIMEOUT) {        /* Handle timeout - no DHCP reply received yet. */        retry = dhcpcBootLeaseData.numRetry;        timer = dhcpcBootLeaseData.timeout;        retry++;        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            /* Exit if unable to get additional parameters for known address. */            if (dhcpcPrevState == INFORMING)                return (BOUND);            return (INIT);      /* Next state is INIT */        }        /* Retransmission required - return after sending message. */        switch (gen_retransmit ()) {        case 0:                /* Transmission successful. */#ifdef DHCPC_DEBUG            logMsg ("retransmit DHCPREQUEST\n", 0, 0, 0, 0, 0, 0);#endif            break;        case -1:               /* Couldn't update timing data */#ifdef DHCPC_DEBUG            logMsg ("time() error retransmitting DHCPREQUEST\n", 0, 0, 0, 0, 0, 0);#endif            break;        case -2:               /* Transmission error in output routine */#ifdef DHCPC_DEBUG            logMsg ("Can't retransmit DHCPREQUEST\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_requesting, 0);        dhcpcBootLeaseData.timeout = timer;        dhcpcBootLeaseData.numRetry = retry;    } 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 = newEvent.pMsg;        msgAlign (&dhcpcMsgIn, pMsgData);        pOption = (char *) pickup_opt (dhcpcMsgIn.dhcp,                                       DHCPLEN (dhcpcMsgIn.udp), _DHCP_MSGTYPE_TAG);        if (pOption != NULL) {            msgtype = *OPTBODY (pOption);            /*             * Ignore unknown message types. If the client does not receive             * a valid response within the expected interval, it will             * timeout and retransmit the request - RFC 2131, section 3.1.5.             */            if (msgtype != DHCPACK && msgtype != DHCPNAK) {                /*                 * Mark the message buffer available after                 * handling the last DHCP message.                 */                if (newEvent.lastFlag)                    dhcpcMessageList[newEvent.slot].writeFlag = TRUE;                return (REQUESTING);            }            if (msgtype == DHCPNAK) {#ifdef DHCPC_DEBUG                logMsg ("Got DHCPNAK from server\n", 0, 0, 0, 0, 0, 0);                pOption = (char *) pickup_opt (dhcpcMsgIn.dhcp,                                               DHCPLEN (dhcpcMsgIn.udp), _DHCP_ERRMSG_TAG);                if (pOption != NULL &&                    nvttostr (OPTBODY (pOption), errmsg, (int) DHCPOPTLEN (pOption)) == 0)                    logMsg ("DHCPNAK contains the error message \"%s\"\n",                            (int) errmsg, 0, 0, 0, 0, 0);#endif                /*                 * Mark the message buffer available after handling the                 * last DHCP message.                 */                if (newEvent.lastFlag)                    dhcpcMessageList[newEvent.slot].writeFlag = TRUE;                /* Ignore invalid responses to DHCP inform message. */                if (dhcpcPrevState == INFORMING)                    return (REQUESTING);                clean_param (dhcpcBootParam);                free (dhcpcBootParam);                dhcpcBootParam = NULL;                return (INIT);  /* Next state is INIT */            }            /*             * Got acknowledgement: fill in host requirements defaults and             * add any parameters from message options.             */            dhcpcDefaultsSet (&tmpparam);            result = dhcp_msgtoparam (dhcpcMsgIn.dhcp, DHCPLEN (dhcpcMsgIn.udp), &tmpparam);            /*             * Mark the message buffer available after             * handling the last DHCP message.             */            if (newEvent.lastFlag)                dhcpcMessageList[newEvent.slot].writeFlag = TRUE;            if (result == OK) {                /* Options parsed successfully - test as needed. */                if (dhcpcPrevState == INFORMING)                    dhcpcBindType = DHCP_MANUAL;    /* Not a lease. */                else {                    /* Full lease negotiation - send ARP probe. */                    result = arp_check (&tmpparam.yiaddr, &dhcpcIntface);                    if (result == OK) {#ifdef DHCPC_DEBUG                        inet_ntoa_b (dhcpcBootParam->yiaddr, newAddr);                        logMsg ("Got DHCPACK (IP = %s, duration = %d secs)\n",                                (int) newAddr, dhcpcBootParam->lease_duration, 0, 0, 0, 0);#endif                        dhcpcBindType = DHCP_NATIVE;                    }                }                /* Save additional parameters if address is available. */                if (result == OK) {                    merge_param (dhcpcBootParam, &tmpparam);                    *dhcpcBootParam = tmpparam;                    if (dhcpcBindType == DHCP_NATIVE) {                        /* Save the lease start time. */                        dhcpcBootParam->lease_origin = dhcpcBootLeaseData.initEpoch;                    }                    return (BOUND); /* Address is available. */                }            }            /*             * Invalid parameters or (for a full lease negotiation) a             * failed ARP probe (address in use). For the full lease             * negotiation, send the DHCPDECLINE message which is now             * required when an ARP probe fails: RFC 2131, section 3.1.5.             */            if (dhcpcPrevState != INFORMING) {                set_declinfo (&tmp_reqspec, errmsg);                dhcp_decline (&tmp_reqspec);                clean_param (dhcpcBootParam);                free (dhcpcBootParam);                dhcpcBootParam = NULL;#ifdef DHCPC_DEBUG                logMsg ("Received unacceptable ACK. Entering INIT state.\n", 0, 0, 0, 0, 0, 0);#endif                return (INIT);            }            /* Ignore invalid parameters for DHCP inform messages. */            return (REQUESTING);        }        /*         * Message type unavailable - remain in current state. Mark         * the message buffer available after handling the last DHCP         * message.         */        if (newEvent.lastFlag)            dhcpcMessageList[newEvent.slot].writeFlag = TRUE;    }    /* Timeout occurred - remain in current state. */    return (REQUESTING);}/********************************************************************************* generate_xid - generate a transaction identifier ** This routine forms a transaction identifier for outgoing messages from the* DHCP client. It is called from multiple locations after the initialization * routines have retrieved the network interface hardware address.** RETURNS: 32-bit transaction identifier in host byte order. ** ERRNO: N/A** NOMANUAL*/LOCAL long generate_xid (void){    time_t current = 0;    u_short result1 = 0;    u_short result2 = 0;    u_short tmp[6];    bcopy (dhcpcIntface.haddr.haddr, (char *) tmp, 6);    dhcpTime (&current);    result1 = checksum (tmp, 6);    result2 = checksum ((u_short *) & current, 2);    return ((result1 << 16) + result2);}/********************************************************************************* msgAlign - set the buffer pointers to access message components** This routine sets the pointers in the given message descriptor* structure to access the various components of a received DHCP* message. It is used internally by the state machine routines.** RETURNS: N/A** ERRNO:   N/A** NOMANUAL*/LOCAL void msgAlign (struct msg *rmsg,  /* Components of received message */                     char *rbuf /* Received Ethernet packet */    ){    rmsg->ip = (struct ip *) rbuf;    if ((ntohs (rmsg->ip->ip_off) & 0x1fff) == 0 &&        ntohs (rmsg->ip->ip_len) >= (DFLTDHCPLEN - DFLTOPTLEN + 4) + UDPHL + IPHL) {#if BSD<44        rmsg->udp = (struct udphdr *) &rbuf[(rmsg->ip->ip_v_hl & 0xf) * WORD];        rmsg->dhcp = (struct dhcp *) &rbuf[(rmsg->ip->ip_v_hl & 0xf) * WORD + UDPHL];#else        rmsg->udp = (struct udphdr *) &rbuf[rmsg->ip->ip_hl * WORD];        rmsg->dhcp = (struct dhcp *) &rbuf[rmsg->ip->ip_hl * WORD + UDPHL];#endif    } else {        rmsg->udp = NULL;        rmsg->dhcp = NULL;    }    return;}/********************************************************************************* arp_check - use ARP to check if given address is in use** This routine broadcasts an ARP request and waits for a reply to determine if* an IP address offered by a DHCP server is already in use.** RETURNS: ERROR if ARP indicates client in use, or OK otherwise.** ERRNO: N/A** NOMANUAL*/int arp_check (struct in_addr *target, struct if_info *pIfData  /* interface used by lease */    ){    int i = 0;    int tmp;    char inbuf[MAX_ARPLEN];    char *pField1;    char *pField2;    struct arphdr *pArpHdr = NULL;    struct ifreq ifr;    struct timeval timeout;    fd_set readFds;    bzero (inbuf, MAX_ARPLEN);    pArpHdr = (struct arphdr *) inbuf;    pArpHdr->ar_hrd = htons (pIfData->haddr.htype);    pArpHdr->ar_pro = htons (ETHERTYPE_IP);    pArpHdr->ar_hln = pIfData->haddr.hlen;    pArpHdr->ar_pln = 4;    pArpHdr->ar_op = htons (ARPOP_REQUEST);    /* Set sender H/W address to your address for ARP requests. (RFC 1541). */    pField1 = &inbuf[ARPHL];    /* Source hardware address. */    pField2 = pField1 + pArpHdr->ar_hln + 4;    /* Target hardware address. */    for (i = 0; i < pIfData->haddr.hlen; i++) {        pField1[i] = pIfData->haddr.haddr[i];        pField2[i] = 0;    }    /* Set sender IP address to 0 for ARP requests as per RFC 1541. */    pField1 += pArpHdr->ar_hln; /* Source IP address. */    pField2 += pArpHdr->ar_hln; /* Target IP address. */    tmp = 0;    bcopy ((char *) &tmp, pField1, pArpHdr->ar_pln);    bcopy ((char *) &target->s_addr, pField2, pArpHdr->ar_pln);    /* Update BPF filter to check for ARP reply from target IP address. */    arpfilter[9].k = htonl (target->s_addr);    if (ioctl (bpfArpDev, BIOCSETF, (int) &arpread) != 0)        return (OK);            /* Ignore errors (permits use of IP address). */    tmp = ARPHL + 2 * (pArpHdr->ar_hln + 4);    /* Size of ARP message. */    dhcpcArpSend (pIfData->iface, inbuf, tmp);    /* Set BPF to monitor interface for reply. */    bzero ((char *) &ifr, sizeof (struct ifreq));    sprintf (ifr.ifr_name, "%s%d", pIfData->iface->if_name, pIfData->iface->if_unit);    if (ioctl (bpfArpDev, BIOCSETIF, (int) &ifr) != 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -