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

📄 dhcps.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    return (NULL);     }/********************************************************************************* select_wreqip - retrieve resource matching IP address** This routine retrieves the dhcp_resource structure which provides the IP* address requested by the client. The requested IP address must be on the* same subnet as the requesting client. The client must also provide a* matching client identifier, if included in the server's database entry.** RETURNS: Matching resource, or NULL if none or not available.** ERRNO: N/A** NOMANUAL*/ static struct dhcp_resource * select_wreqip     (     int msgtype, 		/* DHCP message type */    struct client_id *cid, 	/* pointer to client ID */    time_t curr_epoch 		/* current time, in seconds */    )     {     char *option = NULL; 	/* pointer to access options field */    char tmp [INET_ADDR_LEN]; 	/* temp IP address storage */    struct dhcp_resource *res = NULL; 	/* access to lease descriptor data */    struct in_addr reqip; 		/* value of desired IP address */    bzero (tmp, sizeof (tmp));    bzero ( (char *)&reqip, sizeof (reqip));    option = pickup_opt (dhcpsMsgIn.dhcp, rdhcplen, _DHCP_REQUEST_IPADDR_TAG);    if (option != NULL)         {        reqip.s_addr = htonl (GETHL (OPTBODY (option)));        res = (struct dhcp_resource *)hash_find (&iphashtable,                                                  (char *)&reqip.s_addr,			                         sizeof (u_long), resipcmp,                                                  &reqip);        if (res == NULL)             {#ifdef DHCPS_DEBUG            inet_ntoa_b (reqip, tmp);            logMsg ("IP address %s is not in address pool", tmp,                      0, 0, 0, 0, 0);#endif            return (NULL);            }         else             {               /* check the subnet number */            if (cid->subnet.s_addr !=                 (res->ip_addr.s_addr & res->subnet_mask.s_addr))                 {#ifdef DHCPS_DEBUG                inet_ntoa_b (reqip, tmp);	        logMsg (          "DHCP%s(cid:\"%s\"): subnet mismatch for requested IP address %s.\n",	       (int)((msgtype == DHCPDISCOVER) ? "DISCOVER" : "REQUEST"),	                (int)cidtos (cid, 1), (int)tmp, 0, 0, 0);#endif	        return (NULL);                }            /* is it manual allocation ? */            if (ISSET (res->valid, S_CLIENT_ID))                 {	        /* is there corresponding binding ? */	        if (res->binding == NULL)                     {#ifdef DHCPS_DEBUG                    inet_ntoa_b (reqip, tmp);	            logMsg (                         "DHCP%s(cid:\"%s\"): No corresponding binding for %s",                    (int)((msgtype == DHCPDISCOVER) ? "DISCOVER" : "REQUEST"),                            (int)cidtos (cid, 1), (int)tmp, 0, 0, 0);#endif                     return (NULL);                    }	        /* Check for matching client identifiers. */	        if (cidcmp (&res->binding->cid, cid) != TRUE)                     {#ifdef DHCPS_DEBUG                    inet_ntoa_b (reqip, tmp);	            logMsg (        "DHCP%s(cid:\"%s\"): Client ID mismatch for requested IP address %s.\n",                     (int)((msgtype == DHCPDISCOVER) ? "DISCOVER" : "REQUEST"),                           (int)cidtos (cid, 1), (int)tmp, 0, 0, 0);#endif                    return (NULL);	            }	        /* Check if the address is already in use. */	        if (icmp_check (msgtype, &res->ip_addr) == GOOD) 	            return (res);                else                     {	            turnoff_bind (res->binding);	            return (NULL);	            }                }            /* If not manual allocation, is the requested lease available? */            else if (available_res (res, cid, curr_epoch))                {	       if (icmp_check (msgtype, &res->ip_addr) == GOOD)	           return (res);	       else                   { 	           turnoff_bind (res->binding);	           return (NULL);	           }               }            }        }    return (NULL);    /* No requested IP address present in option list. */    }/********************************************************************************* select_newone - choose an entry from the available resources** This routine retrieves a dhcp_resource structure for a client if no entry* was found based on the requested IP address, if any, or the client * identifier. No addresses which are in use or on a different subnet than * the client are considered. For the remaining entries, it uses the following * criteria:**      First, select entries which were never used in preference to used ones.**      If not found, select the least recently used entry.**      Next, give preference to entries which are unavailable to BOOTP clients.**      Among unused or equally old entries, select the smallest possible *      maximum which exceeds the requested lease length. If not found, *      choose the resource with the largest maximum lease length.**      The previous condition excludes resources with an infinite maximum*      lease whenever possible, unless specifically requested by the client.**      If not found (i.e. - all entries have same maximum lease length), *      select the first available entry in the database.** RETURNS: Matching resource, or NULL if none or not available.** ERRNO: N/A** NOMANUAL*/static struct dhcp_resource * select_newone    (    int msgtype, 		/* DHCP message type */    struct client_id *cid, 	/* pointer to client ID */    time_t curr_epoch, 		/* current time, in seconds */    u_long reqlease 		/* requested lease duration (seconds) */    )    {    struct dhcp_resource *res = NULL;    struct dhcp_resource *best = NULL;    struct hash_member *resptr = NULL;    /* Examine each resource in list constructed from database. */    resptr = reslist;    while (resptr != NULL)        {       res = (struct dhcp_resource *)resptr->data;       if (res->ip_addr.s_addr == 0)      /* Skip dummy entries. */           {           resptr = resptr->next;           continue;           }       /*        * Check the resource subnet and availability. Skip entries which         * are not available or would change the subnet of the client.        */       if (cid->subnet.s_addr ==             (res->ip_addr.s_addr & res->subnet_mask.s_addr) &&	     available_res (res, cid, curr_epoch))            {           /*            * choose the best entry from available resources on the same             * subnet. The criteria are listed in inverse priority order.            */           /* Lowest priority - take first available entry. */           if (best == NULL)                {	       if (icmp_check (msgtype, &res->ip_addr) == GOOD)	           best = res;               else	           turnoff_bind (res->binding);	       resptr = resptr->next;	       continue;               }           /* Select unused entries in preference to used ones. */           if (best->binding == NULL && res->binding != NULL)                {               resptr = resptr->next;               continue;               }           else if (best->binding != NULL && res->binding == NULL)                {               if (icmp_check (msgtype, &res->ip_addr) == GOOD)                   best = res;               else	           turnoff_bind (res->binding);               resptr = resptr->next;               continue;               }            /* Give preference to entries not available to BOOTP clients. */           if (best->allow_bootp == FALSE && res->allow_bootp == TRUE)                {               resptr = resptr->next;               continue;               }           else if (best->allow_bootp == TRUE && res->allow_bootp == FALSE)                {               if (icmp_check(msgtype, &res->ip_addr) == GOOD)                   best = res;               else	           turnoff_bind (res->binding);               resptr = resptr->next;               continue;               }           /*            * Tiebreaker conditionals for preferred entries (either both             * unused or which both qualify as least recently used).             * Overall, these conditionals select the resource whose maximum            * lease exceeds the threshold of the requested lease length by             * the minimum amount. If there is no resource whose maximum lease            * exceeds the requested lease length, the resource with the            * largest maximum lease is chosen.            *            * NOTE: These conditionals also implement a preference for resource            *       entries which do not provide an infinite lease, unless            *       specifically requested by the client.            */           if ( (best->binding == NULL && res->binding == NULL) ||                  (best->binding != NULL && res->binding != NULL &&                   best->binding->expire_epoch == res->binding->expire_epoch))                {               /*                * Select resource with larger maximum lease,                * even if shorter than the requested lease length.                * Combined with the third conditional, the maximum value                * of the maximum lease will be selected, if the lease length                * threshold is not exceeded.                */               if (reqlease >= res->max_lease &&                    res->max_lease > best->max_lease)                    {                   if (icmp_check (msgtype, &res->ip_addr) == GOOD)                       best = res;                   else	               turnoff_bind (res->binding);                   resptr = resptr->next;                   continue;                   }               /*                * Among resources whose maximum lease exceeds                * the requested value, select the minimum.                * This condition is never true until either the                 * previous or next condition evaluated to true.                */               if (reqlease != INFINITY && reqlease <= res->max_lease &&                   res->max_lease < best->max_lease)                    {                   if (icmp_check (msgtype, &res->ip_addr) == GOOD)                       best = res;                   else	               turnoff_bind (res->binding);                   resptr = resptr->next;                   continue;                   }                /*                 * Accept entries longer than both the requested value                  * and the current maximum. This condition evaluates to                 * true at most once. Once it does, neither it or the                 * first conditional will ever evaluate to true again.                 */               if (reqlease != INFINITY && res->max_lease >= reqlease &&                   reqlease > best->max_lease)                    {                   if (icmp_check (msgtype, &res->ip_addr) == GOOD)                       best = res;                   else	               turnoff_bind (res->binding);                   resptr = resptr->next;                   continue;                   }               resptr = resptr->next;               continue;               }            /*            * Among previously used entries, select those which expired             * earlier. (In the aggregate, implements a LRU algorithm).            */           if (best->binding != NULL && res->binding != NULL &&               best->binding->expire_epoch > res->binding->expire_epoch)                {               if (icmp_check (msgtype, &res->ip_addr) == GOOD)                   best = res;               else                   turnoff_bind (res->binding);               resptr = resptr->next;               continue;               }            else               {	       resptr = resptr->next;	       continue;               }           }        resptr = resptr->next;        }    return (best);    }/********************************************************************************* choose_res - select a resource for DHCP client** This routine chooses a resource in response to an incoming DHCP discover * message. If the server database contains a manual entry matching the* client identifier, the corresponding resource is returned. Otherwise,* the database entry which provides the requested IP address, if any, is * chosen. If the discover message does not require a specific entry, the* server selects a new entry using its own internal criteria, or NULL if* no entry is available.** RETURNS: Matching resource, or NULL if none available.** ERRNO: N/A** NOMANUAL*/static struct dhcp_resource * choose_res    (    struct client_id *cid, 	/* pointer to client ID */    time_t curr_epoch, 		/* current time, in seconds */    u_long reqlease 		/* requested lease duration (seconds) */    )    {    struct dhcp_resource *res = NULL;    /* 1. select with client identifier, if  found. */    if ( (res = select_wcid (DHCPDISCOVER, cid, curr_epoch)) != NULL)        return (res);    /* 2. select with requested IP address, if any. */    if ( (res = select_wreqip (DHCPDISCOVER, cid, curr_epoch)) != NULL)        return (res);    /* 3. select an entry using internal criteria. */    res = select_newone (DHCPDISCOVER, cid, curr_epoch, reqlease);    if (res != NULL)        return (res);#ifdef DHCPS_DEBUG    logMsg ("Warning: DHCPDISCOVER - No available addresses in the pool.\n",             0, 0, 0, 0, 0, 0);#endif    return (NULL);    }

⌨️ 快捷键说明

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