📄 dhcps.c
字号:
* ERRNO: N/A** NOMANUAL*/static void get_cid ( struct dhcp *msg, /* pointer to incoming message */ int length, /* length of incoming message */ struct client_id *cid /* pointer to storage for parsed data */ ) { char *option = NULL; option = pickup_opt (msg, length, _DHCP_CLIENT_ID_TAG); if (option != NULL) { cid->idlen = ( (int)DHCPOPTLEN (option)) - 1; /* -1 for ID type */ bcopy (OPTBODY (option) + 1, cid->id, cid->idlen); cid->idtype = *OPTBODY (option); } else { /* haddr is used to substitute for client identifier */ cid->idlen = msg->hlen; cid->idtype = msg->htype; bcopy (msg->chaddr, cid->id, msg->hlen); } return; }/********************************************************************************* get_maxoptlen - Calculate size of options field** This routine determines the number of bytes available for DHCP options* without overloading. For standard length messages of 548 bytes, it returns * the default length of 312 bytes. For longer messages, it returns 312 bytes * plus the excess bytes (beyond 548), unless the DHCP message length exceeds* the MTU size. In that case, it returns the number of bytes in the MTU not* needed for the IP header, UDP header, and the fixed-length portion of the* DHCP messages, which require 264 bytes total.** RETURNS: Size of variable-length options field** ERRNO: N/A** NOMANUAL*/static int get_maxoptlen ( struct dhcp *msg, /* pointer to incoming message */ int length /* length of incoming message */ ) { char *option = NULL; int retval = DFLTOPTLEN; /* Calculate length of options field from maximum message size. */ if ( (option = pickup_opt (msg, length, _DHCP_MAXMSGSIZE_TAG)) != NULL) retval = GETHS (OPTBODY (option)) - IPHL - UDPHL - DFLTDHCPLEN + DFLTOPTLEN; /* * If requested maximum size exceeds largest supported value, return * value equal to portion of buffer not required for message headers * or fixed-size portion of DHCP message. */ if (retval - DFLTOPTLEN + DFLTDHCPLEN + UDPHL + IPHL > dhcpsMaxSize) retval = dhcpsMaxSize - IPHL - UDPHL - DFLTDHCPLEN + DFLTOPTLEN; return (retval); }/********************************************************************************* get_subnet - Retrieve subnet number** This routine determines the subnet number of the requesting client and* stores it in the given structure. This value is determined using the* subnet mask specified by the client, if present. Otherwise, it is formed* from the last known subnet mask, if available, or the subnet mask of the* receiving interface. The server will only issue leases for IP addresses * with the same subnet number as the requesting client.** RETURNS: 0 if subnet number determined, or -1 otherwise.** ERRNO: N/A** NOMANUAL*/static int get_subnet ( struct dhcp *msg, /* pointer to incoming message */ int length, /* length of incoming message */ struct in_addr *subn, /* pointer to storage for parsed data */ struct if_info *ifp /* pointer to receiving interface descriptor */ ) { char *option = NULL; struct relay_acl *acl = NULL; struct dhcp_resource *res = NULL;#ifdef DHCPS_DEBUG char output [INET_ADDR_LEN];#endif if (msg->ciaddr.s_addr != 0) { if ( (option = pickup_opt (msg, length, _DHCP_SUBNET_MASK_TAG)) != NULL) { subn->s_addr = msg->ciaddr.s_addr & htonl (GETHL (OPTBODY (option))); return (0); } else { res = (struct dhcp_resource *) hash_find (&iphashtable, (char *)&msg->ciaddr.s_addr, sizeof (u_long), resipcmp, &msg->ciaddr);#ifdef DHCPS_DEBUG if (res == NULL) logMsg ("get_subnet can't find IP address in hash table.\n", 0, 0, 0, 0, 0, 0);#endif if (res != NULL) { subn->s_addr = msg->ciaddr.s_addr & res->subnet_mask.s_addr; return (0); } } } if (msg->giaddr.s_addr != 0) { if ( (option = pickup_opt (msg, length, _DHCP_SUBNET_MASK_TAG)) != NULL) { subn->s_addr = msg->giaddr.s_addr & htonl (GETHL (OPTBODY (option))); return (0); } else if ( (acl = (struct relay_acl *) hash_find (&relayhashtable, (char *)&msg->giaddr, sizeof (struct in_addr), relayipcmp, &msg->giaddr)) == NULL) {#ifdef DHCPS_DEBUG inet_ntoa_b (msg->giaddr, output); logMsg ("DHCP message sent from invalid relay agent(%s).\n", output, 0, 0, 0, 0, 0);#endif return (-1); } else { subn->s_addr = (acl->relay.s_addr & acl->subnet_mask.s_addr); return (0); } } /* Client doesn't have IP address - form from received interface. */ subn->s_addr = ifp->ipaddr.s_addr & ifp->subnetmask.s_addr; return (0); }/********************************************************************************* get_snmk - Retrieve subnet mask** This routine determines the subnet mask for the requesting client and* stores it in the given structure. This value is determined from the * value specified for the relay agent, if the message was forwarded, or* the subnet mask of the receiving interface. ** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/static int get_snmk ( struct dhcp *msg, /* pointer to incoming message */ int length, /* length of incoming message */ struct in_addr *subn, /* pointer to storage for parsed data */ struct if_info *ifp /* pointer to interface descriptor */ ) { struct relay_acl *acl = NULL;#ifdef DHCPS_DEBUG char output [INET_ADDR_LEN];#endif if (msg->giaddr.s_addr != 0) { acl = (struct relay_acl *)hash_find(&relayhashtable, (char *) &msg->giaddr, sizeof (struct in_addr), relayipcmp, &msg->giaddr); if (acl == NULL) {#ifdef DHCPS_DEBUG inet_ntoa_b (msg->giaddr, output); logMsg ("packet received from invalid relay agent(%s).\n", output, 0, 0, 0, 0, 0);#endif return (-1); } else { subn->s_addr = acl->subnet_mask.s_addr; return (0); } } subn->s_addr = ifp->subnetmask.s_addr; return (0); }/********************************************************************************* available_res - Check resource availability** This routine determines if the resource selected by the server may* be offered to the client. The resource is available if it has not been* assigned or offered to any client (res->binding == NULL), or the lease has * expired (expire_epoch < curr_epoch), or an outstanding offer was not * acknowledged within the time allotted (temp_epoch < curr_epoch). The* resource is also available if it was manually assigned to the given * client (binding->cid matches given client ID).** RETURNS: TRUE if resource available, or FALSE otherwise. ** ERRNO: N/A** NOMANUAL*/static int available_res ( struct dhcp_resource *res, /* pointer to lease descriptor */ struct client_id *cid, /* pointer to client ID */ time_t curr_epoch /* current time, in seconds */ ) { return (res->binding == NULL || (res->binding->expire_epoch != 0xffffffff && res->binding->expire_epoch < curr_epoch && res->binding->temp_epoch < curr_epoch) || cidcmp (&res->binding->cid, cid)); }/********************************************************************************* cidcopy - copy client identifier** This routine copies the <type>:<value> client identifier pair from the* source structure to the destination.** RETURNS: 0, always.** ERRNO: N/A** NOMANUAL*/static int cidcopy ( struct client_id *src, /* source client identifier */ struct client_id *dst /* destiniation client identifier */ ) { dst->subnet.s_addr = src->subnet.s_addr; dst->idtype = src->idtype; dst->idlen = src->idlen; bzero (dst->id, src->idlen); bcopy (src->id, dst->id, src->idlen); return (0); }/********************************************************************************* choose_lease - determine lease duration** This routine selects the lease duration for the offer to the client. If* the resource is client-specific, the lease duration is infinite. Otherwise,* the server provides the duration requested by the client, if available, or * the maximum available lease, whichever is less. If the client does not * request a lease duration, and has no active lease, the default lease value * is returned. For lease renewals or rebinding attempts, or if the lease* has expired, the default lease value is also returned.** RETURNS: Selected lease duration.** ERRNO: N/A** NOMANUAL*/static int choose_lease ( int reqlease, /* requested lease duration (sec) */ time_t curr_epoch, /* current time, in seconds */ struct dhcp_resource *offer_res /* pointer to lease descriptor */ ) { u_long offer_lease = 0; /* Manual allocation - give an infinite lease to client. */ if (ISSET (offer_res->valid, S_CLIENT_ID)) offer_lease = 0xffffffff; /* Give requested lease, or maximum lease if request exceeds that value. */ else if (reqlease != 0) { if (reqlease <= offer_res->max_lease) offer_lease = reqlease; else offer_lease = offer_res->max_lease; } /* Initial request - give default lease. */ else if (offer_res->binding == NULL) offer_lease = offer_res->default_lease; /* Lease renewal or rebinding. */ else { /* "Renew" infinite lease. */ if (offer_res->binding->expire_epoch == 0xffffffff) offer_lease = 0xffffffff; /* * Lease expired (or being renewed) - give new lease * of default duration. */ else offer_lease = offer_res->default_lease; } return (offer_lease); }/********************************************************************************* select_wcid - retrieve manually allocated leases** This routine retrieves the dhcp_resource structure which holds the parameters* from the address pool database specifically allocated to the client with* the given client identifier, if any. These lease types have the highest* priority when the server is selecting a lease for a client in response to* a DHCP discover message.** RETURNS: Manually allocated resource, or NULL if none or not available.** ERRNO: N/A** NOMANUAL*/static struct dhcp_resource * select_wcid ( int msgtype, /* DHCP message type */ struct client_id *cid, /* pointer to client ID */ time_t curr_epoch /* current time, in seconds */ ) { struct dhcp_binding *binding = NULL; binding = (struct dhcp_binding *)hash_find (&cidhashtable, cid->id, cid->idlen, bindcidcmp, cid); if (binding != NULL) { /* * Is the resource used ? */ if (available_res (binding->res, cid, curr_epoch)) { if (icmp_check (msgtype, &binding->res->ip_addr) == GOOD) { return (binding->res); } else { turnoff_bind (binding); return (NULL); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -