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

📄 dhcps.c

📁 vxworks下dhcpc,dhcpr,dhcps库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        /* Insert options from matching resource entry not already present. */        if (params != NULL) {            for (i = 0; i < _DHCP_LAST_OPTION; i++)                if (ISCLR (inserted, i))                    if (insert_opt (params, lease, i, inserted, PASSIVE)                        == E_NOMORE) {#ifdef DHCPS_DEBUG                        logMsg ("No space left in options field for DHCP%s",                                (int) ((msgtype == DHCPOFFER) ? "OFFER" : "ACK"), 0, 0, 0, 0, 0);#endif                        break;                    }        }    }    /* Insert any class-specific options. */    option = pickup_opt (dhcpsMsgIn.dhcp, rdhcplen, _DHCP_CLASS_ID_TAG);    if (option != NULL) {        paramId.idlen = DHCPOPTLEN (option);        paramId.idtype = 0;     /* Unused for class identifiers. */        bcopy (OPTBODY (option), paramId.id, paramId.idlen);        params = hash_find (&paramhashtable, paramId.id, paramId.idlen, paramcidcmp, &paramId);        /* Insert options from matching resource entry not already present. */        if (params != NULL) {            for (i = 0; i < _DHCP_LAST_OPTION; i++)                if (ISCLR (inserted, i))                    if (insert_opt (params, lease, i, inserted, PASSIVE)                        == E_NOMORE) {#ifdef DHCPS_DEBUG                        logMsg ("No space left in options field for DHCP%s",                                (int) ((msgtype == DHCPOFFER) ? "OFFER" : "ACK"), 0, 0, 0, 0, 0);#endif                        break;                    }        }    }    return;}/********************************************************************************* select_wciaddr - retrieve resource with matching IP address** This routine attempts to find an address pool entry whose IP address matches* the value requested by the client. If the matching IP address is part of a* manual lease, it also verifies that the client ID matches the required value.* Otherwise, it checks if the requesting client received an offer from the* server.** RETURNS: Matching resource, or NULL if none or not available.** ERRNO: N/A** NOMANUAL*//* * choose resource with ciaddr */static struct dhcp_resource *select_wciaddr (struct client_id *cid, /* pointer to identifier of request client */                                             time_t curr_epoch, /* current time, in seconds */                                             int *nosuchaddr    /* flag indicating if address foun in table */    ){    struct dhcp_resource *res = NULL;#ifdef DHCPS_DEBUG    char tmp[INET_ADDR_LEN];#endif    *nosuchaddr = FALSE;    res = (struct dhcp_resource *) hash_find (&iphashtable,                                              (char *) &dhcpsMsgIn.dhcp->ciaddr.s_addr,                                              sizeof (u_long), resipcmp, &dhcpsMsgIn.dhcp->ciaddr);    if (res == NULL) {        *nosuchaddr = TRUE;     /* Fatal error - expected entry not found. */        return (NULL);    } else {        /* Check for subnet match. */        if (cid->subnet.s_addr != (res->ip_addr.s_addr & res->subnet_mask.s_addr)) {#ifdef DHCPS_DEBUG            inet_ntoa_b (dhcpsMsgIn.dhcp->ciaddr, tmp);            logMsg ("Subnet mismatch for DHCPREQUEST (cid: %s, ciaddr: %s).\n",                    (int) cidtos (cid, 1), (int) tmp, 0, 0, 0, 0);#endif            return (NULL);        } else if (ISSET (res->valid, S_CLIENT_ID)) {   /* Manual allocation. */            /* Fatal error if no binding present for manual allocation. */            if (res->binding == NULL) {#ifdef DHCPS_DEBUG                inet_ntoa_b (dhcpsMsgIn.dhcp->ciaddr, tmp);                logMsg ("DHCPREQUEST(cid:\"%s\"): No binding for %s",                        (int) cidtos (cid, 1), (int) tmp, 0, 0, 0, 0);#endif                *nosuchaddr = TRUE;                return (NULL);            }            /* Check that client ID of binding matches requesting client. */            else if (res->binding->cid.idtype != cid->idtype ||                     res->binding->cid.idlen != cid->idlen ||                     bcmp (res->binding->cid.id, cid->id, cid->idlen) != 0) {#ifdef DHCPS_DEBUG                inet_ntoa_b (dhcpsMsgIn.dhcp->ciaddr, tmp);                logMsg ("DHCPREQUEST(cid:\"%s\", ciaddr:%s) - client ID mismatch.\n",                        (int) cidtos (cid, 1), (int) tmp, 0, 0, 0, 0);#endif                return (NULL);            }        }        /* Dynamic or automatic allocation. Fails if no binding present         * (i.e. - unknown request), or lease has expired (i.e. - late         * request), or if client ID doesn't match expected value from         * the DHCP offer message.         */        else if (res->binding == NULL ||                 (res->binding->expire_epoch != 0xffffffff &&                  res->binding->expire_epoch <= curr_epoch) ||                 res->binding->cid.idtype != cid->idtype ||                 res->binding->cid.idlen != cid->idlen ||                 bcmp (res->binding->cid.id, cid->id, cid->idlen) != 0) {#ifdef DHCPS_DEBUG            inet_ntoa_b (dhcpsMsgIn.dhcp->ciaddr, tmp);            logMsg ("DHCPREQUEST(cid:\"%s\",ciaddr:%s): is unavailable.\n",                    (int) cidtos (cid, 1), (int) tmp, 0, 0, 0, 0);#endif            return (NULL);        }    }    return (res);}/********************************************************************************* discover - handle client discover messages** This routine examines client discover messages, selects an available * resource (if any), calculates the length of the lease, and sends the * appropriate offer to the client.** RETURNS: 0 if processing successful, or -1 on error.** ERRNO: N/A** NOMANUAL*/static int discover (struct if_info *ifp    /* pointer to descriptor of receiving interface */    ){    struct dhcp_resource *offer_res = NULL; /* lease descriptor chosen */    struct client_id cid;       /* ID of requesting client */    u_long offer_lease = 0;     /* offered lease duration */    u_long reqlease = 0;        /* requested lease duration */    time_t curr_epoch = 0;      /* current time, in seconds */    int result;                 /* error value, if any */    bzero ((char *) &cid, sizeof (cid));    if (dhcpTime (&curr_epoch) == -1) {#ifdef DHCPS_DEBUG        logMsg ("Warning: discover() couldn't retrieve current time.\n", 0, 0, 0, 0, 0, 0);#endif        return (-1);    }    /* Extract requested lease from DHCP message. */    reqlease = get_reqlease (dhcpsMsgIn.dhcp, rdhcplen);    /* Determine maximum length available in DHCP message for options. */    maxoptlen = get_maxoptlen (dhcpsMsgIn.dhcp, rdhcplen);    /* Set pointers to access client ID within DHCP message options field. */    get_cid (dhcpsMsgIn.dhcp, rdhcplen, &cid);    /* Critical section with dhcpsLeaseEntryAdd(). */    semTake (dhcpsMutexSem, WAIT_FOREVER);    /* Retrieve subnet for incoming message. */    if (get_subnet (dhcpsMsgIn.dhcp, rdhcplen, &cid.subnet, ifp) != 0) {        semGive (dhcpsMutexSem);        return (-1);    }    /* Select an available lease descriptor. */    if ((offer_res = choose_res (&cid, curr_epoch, reqlease)) == NULL) {        semGive (dhcpsMutexSem);        return (-1);    }    /* Select a lease duration. */    offer_lease = choose_lease (reqlease, curr_epoch, offer_res);    /* Record lease offer in data structures. */    result = update_db (DHCPDISCOVER, &cid, offer_res, offer_lease, curr_epoch);    semGive (dhcpsMutexSem);    if (result != 0)        return (-1);    /* Create outgoing DHCP offer message. */    construct_msg (DHCPOFFER, offer_res, offer_lease, ifp);    /*     * xxx must be able to handle the fragments, but currently not implemented     */    /* Transfer message to receiving interface. */    send_dhcp (ifp, DHCPOFFER);    return (0);}/********************************************************************************* request - handle client request messages** This routine responds to request messages sent by clients in response* to an offer from a DHCP server. If the server generated the offer, it* sends the appropriate ACK or NAK message. Otherwise, it updates the * internal data structure to reflect the implicit decline from the client.** RETURNS: 0 if processing successful, or -1 on error.** ERRNO: N/A** NOMANUAL*/static int request (struct if_info *ifp /* pointer to descriptor of receiving interface */    ){    BOOL reqforme = FALSE;    BOOL nosuchaddr = FALSE;    struct dhcp_resource *res = NULL;    struct client_id cid;    struct in_addr reqip;    struct in_addr netmask;    unsigned long offer_lease = 0;  /* offering lease */    unsigned long reqlease = 0; /* requested lease duration */    char *option = NULL;    int response;               /* Accept request? */#define EPOCH      "Thu Jan  1 00:00:00 1970\n"#define BRDCSTSTR  "255.255.255.255"    char datestr[sizeof (EPOCH)];    char addrstr[sizeof (BRDCSTSTR)];    time_t curr_epoch = 0;      /* current epoch */    bzero ((char *) &cid, sizeof (cid));    bcopy (EPOCH, datestr, sizeof (EPOCH));    bcopy (BRDCSTSTR, addrstr, sizeof (BRDCSTSTR));    response = 2;               /* Response not determined. */    if (dhcpTime (&curr_epoch) == -1) {#ifdef DHCPS_DEBUG        logMsg ("Warning: Couldn't get timestamp when processing request.\n", 0, 0, 0, 0, 0, 0);#endif        return (-1);    }    reqlease = get_reqlease (dhcpsMsgIn.dhcp, rdhcplen);    maxoptlen = get_maxoptlen (dhcpsMsgIn.dhcp, rdhcplen);    get_cid (dhcpsMsgIn.dhcp, rdhcplen, &cid);    /* Critical section with dhcpsLeaseEntryAdd(). */    semTake (dhcpsMutexSem, WAIT_FOREVER);    if (get_subnet (dhcpsMsgIn.dhcp, rdhcplen, &cid.subnet, ifp) != 0) {        semGive (dhcpsMutexSem);        return (-1);    }    /*     * Check if this DHCP server is the request destination.      * (Option not present unless client is in SELECTING state).       */    option = pickup_opt (dhcpsMsgIn.dhcp, rdhcplen, _DHCP_SERVER_ID_TAG);    if (option != NULL)        if (htonl (GETHL (OPTBODY (option))) == ifp->ipaddr.s_addr)            reqforme = TRUE;    /*     * Check the previously allocated network address sent by client     * (i.e. - client is in RENEWING or REBINDING state).      */    if (dhcpsMsgIn.dhcp->ciaddr.s_addr != 0) {        /* For client in RENEWING state, no relay agents are used. */        if (get_snmk (dhcpsMsgIn.dhcp, rdhcplen, &netmask, ifp) == 0)            if (dhcpsMsgIn.dhcp->giaddr.s_addr != 0)                /* REBINDING state - check network of client. */                if ((dhcpsMsgIn.dhcp->giaddr.s_addr & netmask.s_addr) !=                    (dhcpsMsgIn.dhcp->ciaddr.s_addr & netmask.s_addr))                    /* goto nak;   *//* Different subnet. */                    response = 0;   /* Send NAK to client. */        if (response != 0) {    /* Response still not determined. */            res = select_wciaddr (&cid, curr_epoch, &nosuchaddr);            if (res == NULL) {                /*                  * If no entry present or manual entry present without a                  * matching binding the request is meant for another server                 * (for renewal request) or cannot be satisfied (for rebinding).                 */                if (nosuchaddr == TRUE) {                    semGive (dhcpsMutexSem);                    return (-1);                }                /* deny request for subnet mismatch, client ID mismatch,                 * expired lease, or missing binding for non-manual allocation.                 * (Missing binding means no DISCOVER received for request).                  */                else                    response = 0;            } else                /* goto ack; */                response = 1;   /* Send ACK to client. */        }    }    if (response == 2) {        /* Response still undetermined. */        /* Requesting client has no IP address (i.e. - initial request         * from SELECTING state or verification of cached lease from          * INIT-REBOOT state).         */        reqip.s_addr = 0;        option = pickup_opt (dhcpsMsgIn.dhcp, rdhcplen, _DHCP_REQUEST_IPADDR_TAG);        if (option != NULL)            reqip.s_addr = htonl (GETHL (OPTBODY (option)));        if (reqip.s_addr != 0) {            if (get_snmk (dhcpsMsgIn.dhcp, rdhcplen, &netmask, ifp) == 0) {                /*                 * Deny request received if client is on the wrong network.                 * (Suggested behavior from RFC 1541).                 */                if (dhcpsMsgIn.dhcp->giaddr.s_addr != 0) {                    /* Deny request received from relay agent if requested IP                      * address is not on agent's subnet.                      */                    if ((dhcpsMsgIn.dhcp->giaddr.s_addr & netmask.s_addr) !=                        (reqip.s_addr & netmask.s_addr))                        response = 0;   /* Send NAK to client. */                } else {                    /* Deny request received directly if requested IP address                     * on different subnet from receiving interface.                      */            

⌨️ 快捷键说明

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