database.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:118k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* database.c - DHCP server data retrieval code */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01o,07may02,wap  Put debug messages under DHCPS_DEBUG (SPR #76495)
  8. 01n,29oct01,wap  Fix use of get_integer() with htons()/htonl() (SPR #34808)
  9. 01m,12oct01,rae  merge from truestack ver 01n, base 01j
  10.                  SPRs 69547, 65163, 33576
  11. 01l,24oct00,spm  fixed modification history after tor3_x merge
  12. 01k,23oct00,niq  merged from version 01l of tor3_x branch (base version 01j)
  13. 01j,17dec97,spm  fixed byte order of address-based loop boundaries (SPR #20056)
  14. 01i,04dec97,spm  added code review modifications
  15. 01h,06oct97,spm  added newlines and component labels to default output
  16. 01g,26aug97,spm  modified comments for all routines
  17. 01f,02jun97,spm  added test for optional storage routine and updated man pages
  18. 01e,08may97,spm  corrected use of storage routines, removed memory leak, and
  19.                  documented shutdown of server 
  20. 01d,30apr97,spm  added missing START call to DHCPS_LEASE_HOOK storage routine
  21. 01c,18apr97,spm  added conditional include DHCPS_DEBUG for displayed output
  22. 01b,08apr97,spm  corrected byte ordering when adding MTU plateau table option
  23. 01a,07apr97,spm  created by modifying WIDE project DHCP implementation
  24. */
  25. /*
  26. DESCRIPTION
  27. This library contains the code used by the DHCP server to access permanent
  28. storage through two optional function hooks provided by the user. 
  29. The function specified by dhcpsAddressHookAdd() is used to store and retrieve 
  30. address pool entries which are added by the user with dhcpsLeaseEntryAdd(). 
  31. This capability allows the user to bypass the static table definition and
  32. add entries without recompiling the runtime image. If the storage hook is
  33. not provided, only the address pool entries contained in the static tables
  34. will be retained across server reboots. As a result, any client using other
  35. address pool entries will be unable to renew its lease.
  36. The second storage hook, specified by dhcpsLeaseHookAdd(), is much more 
  37. critical. It is used to store and retrieve the subset of address pool entries 
  38. which have been offered to a client, or are currently in use. If this storage 
  39. hook is not provided, the server might issue network addresses which are 
  40. already in use, causing unpredictable results.
  41. INCLUDE_FILES: dhcpsLib.h
  42. */
  43. /*
  44.  * WIDE Project DHCP Implementation
  45.  * Copyright (c) 1995 Akihiro Tominaga
  46.  * Copyright (c) 1995 WIDE Project
  47.  * All rights reserved.
  48.  *
  49.  * Permission to use, copy, modify and distribute this software and its
  50.  * documentation is hereby granted, provided only with the following
  51.  * conditions are satisfied:
  52.  *
  53.  * 1. Both the copyright notice and this permission notice appear in
  54.  *    all copies of the software, derivative works or modified versions,
  55.  *    and any portions thereof, and that both notices appear in
  56.  *    supporting documentation.
  57.  * 2. All advertising materials mentioning features or use of this software
  58.  *    must display the following acknowledgement:
  59.  *      This product includes software developed by WIDE Project and
  60.  *      its contributors.
  61.  * 3. Neither the name of WIDE Project nor the names of its contributors
  62.  *    may be used to endorse or promote products derived from this software
  63.  *    without specific prior written permission.
  64.  *
  65.  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND WIDE
  66.  * PROJECT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  67.  * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ALSO, THERE
  68.  * IS NO WARRANTY IMPLIED OR OTHERWISE, NOR IS SUPPORT PROVIDED.
  69.  *
  70.  * Feedback of the results generated from any improvements or
  71.  * extensions made to this software would be much appreciated.
  72.  * Any such feedback should be sent to:
  73.  * 
  74.  *  Akihiro Tominaga
  75.  *  WIDE Project
  76.  *  Keio University, Endo 5322, Kanagawa, Japan
  77.  *  (E-mail: dhcp-dist@wide.ad.jp)
  78.  *
  79.  * WIDE project has the rights to redistribute these changes.
  80.  */
  81. /* includes */
  82. #include <stdio.h>
  83. #include <unistd.h>
  84. #include <stdlib.h>
  85. #include <ctype.h>
  86. #include <string.h>
  87. #include <time.h>
  88. #include <sys/types.h>
  89. #include <netinet/in.h>
  90. #include <arpa/inet.h>
  91. #include <inetLib.h>
  92. #include <logLib.h>
  93. #include "dhcp/dhcp.h"
  94. #include "dhcp/common.h"
  95. #include "dhcpsLib.h"
  96. #include "dhcp/hash.h"
  97. #include "dhcp/database.h"
  98. /* global variables for both virtual stack and regular stack */
  99. IMPORT long dhcps_dflt_lease;  /* Default for default lease length. */
  100. IMPORT long dhcps_max_lease;  /* Default for maximum lease length. */
  101. IMPORT DHCPS_LEASE_DESC * pDhcpsLeasePool;
  102. #ifndef VIRTUAL_STACK
  103. /* globals */
  104. struct hash_tbl cidhashtable;
  105. struct hash_tbl iphashtable;
  106. struct hash_tbl nmhashtable;
  107. struct hash_tbl relayhashtable;
  108. struct hash_tbl paramhashtable;
  109. struct hash_member *bindlist;
  110. struct hash_member *reslist;
  111. #else
  112. #include "netinet/vsLib.h"
  113. #include "netinet/vsDhcps.h"
  114. #endif /* VIRTUAL_STACK */
  115. IMPORT void dhcpsFreeResource (struct dhcp_resource *);
  116. /*******************************************************************************
  117. *
  118. * dump_bind_db - write all active bindings to permanent storage
  119. *
  120. * This routine takes a snapshot of the linked list which contains the
  121. * descriptors for each active or pending lease. It calls a hook routine, 
  122. * supplied by the user, to record these entries in permanent storage. This 
  123. * storage is required to maintain the consistency of the server data 
  124. * structures and is the key to the integrity of the entire DHCP protocol. 
  125. *
  126. * RETURNS: N/A
  127. *
  128. * ERRNO: N/A
  129. *
  130. * NOMANUAL
  131. */
  132. void dump_bind_db (void)
  133.     {
  134.     struct hash_member *bindptr = NULL;
  135.     STATUS result;
  136.     if (dhcpsLeaseHookRtn == NULL)
  137.         return;
  138.     result = (* dhcpsLeaseHookRtn) (DHCPS_STORAGE_STOP, NULL, 0);
  139.     if (result != OK) 
  140.          {
  141.          logMsg ("Warning: cannot close the binding database.n", 
  142.                   0, 0, 0, 0, 0, 0);
  143.          return;
  144.          }
  145.     /* Remove old values. */
  146.     result = (* dhcpsLeaseHookRtn) (DHCPS_STORAGE_CLEAR, NULL, 0);
  147.     if (result != OK) 
  148.          {
  149.          logMsg ("Warning: cannot clear the binding database.n",
  150.                   0, 0, 0, 0, 0, 0);
  151.          return;
  152.          }
  153.     result = (* dhcpsLeaseHookRtn) (DHCPS_STORAGE_START, NULL, 0);
  154.     if (result != OK) 
  155.          {
  156.          logMsg ("Warning: cannot open the binding database.n", 
  157.                   0, 0, 0, 0, 0, 0);
  158.          return;
  159.          }
  160.     bindptr = bindlist;
  161.     while (bindptr != NULL) 
  162.         {
  163.         dump_bind_entry(bindptr->data);
  164.         bindptr = bindptr->next;
  165.         }
  166.     return;
  167.     }
  168. /*******************************************************************************
  169. *
  170. * dump_bind_entry - write a binding record to permanent storage
  171. *
  172. * This routine calls a hook routine, supplied by the user, to store the entry 
  173. * for an active lease. The stored entry takes the following form:
  174. *
  175. *    <client ID>:<subnet number>:<H/W address>:<expiration time>:<entry name>
  176. *
  177. * where the entry name identifies the corresponding entry in the address pool.
  178. *
  179. * RETURNS: N/A
  180. *
  181. * ERRNO: N/A
  182. *
  183. * NOMANUAL
  184. */
  185. void dump_bind_entry
  186.     ( 
  187.     struct dhcp_binding * bp /* binding record to add to storage */
  188.     )
  189.     {
  190.     char tmp [30];                /* Maximum length of quoted date string. */
  191.     char new_entry [100];         /* 
  192.                                    * Maximum length of entry -
  193.                                    * type/ID, subnet, hardware address,
  194.                                    * expiration time, and entry name. 
  195.                                    */
  196.     /* 
  197.      * Do not store incomplete or static entries. Incomplete entries result
  198.      * when the corresponding address fails an ICMP check, indicating
  199.      * it is in use by an unknown client. A static binding entry is
  200.      * created for each manual lease in the address pool. Since they
  201.      * implicitly provide an infinite lease to a specific client, storage 
  202.      * of their current state is meaningless. 
  203.      */
  204.     if ( (bp->flag & COMPLETE_ENTRY) == 0 || (bp->flag & STATIC_ENTRY) != 0)
  205.         return;
  206.     /* Convert the data structure into a formatted string. */
  207.     sprintf (new_entry, "%s:", cidtos (&bp->cid, 1));
  208.     sprintf (tmp, "%s:", haddrtos (&bp->haddr));
  209.     strcat (new_entry, tmp);
  210.     if (bp->expire_epoch == 0xffffffff) 
  211.         {
  212.         if (bp->flag & BOOTP_ENTRY)
  213.             sprintf(tmp, ""bootp":");
  214.         else
  215.             sprintf(tmp, ""infinity":");
  216.         }
  217.     else if (bp->expire_epoch == 0)
  218.         sprintf(tmp, """:");
  219.     else 
  220.         {
  221.         sprintf (tmp, ""%s", (char *)ctime (&bp->expire_epoch));
  222.     
  223.         /* Replace 'n' added by ctime() with the closing quote. */
  224.         tmp [strlen (tmp) - 1] = '"';
  225.         strcat (tmp, ":");            /* Append field delimiter. */
  226.         }
  227.     strcat (new_entry, tmp);
  228.     sprintf (tmp, "%sn", bp->res_name);
  229.     strcat (new_entry, tmp);
  230.     /* Call the user-supplied storage hook to save the entry. */
  231.     (* dhcpsLeaseHookRtn) (DHCPS_STORAGE_WRITE, new_entry, strlen (new_entry));
  232.     return;
  233.     }
  234. /*******************************************************************************
  235. *
  236. * finish - cleanup and remove data structures before exiting
  237. *
  238. * This "routine" contains the functions needed for an orderly shutdown of 
  239. * the server task. The dump_bind_db() routine stores a snapshot of all active
  240. * leases and dhcpsCleanup() removes the installed packet filter device and all
  241. * dynamically allocated memory. In the original code, this routine was 
  242. * triggered by SIGTERM or SIGINT. This is not a working example, since
  243. * the server task created at system startup is not removed. The code is not
  244. * included in the DHCP release.
  245. *
  246. * RETURNS: N/A
  247. *
  248. * ERRNO: N/A
  249. *
  250. * NOMANUAL
  251. */
  252. /* void finish (void)
  253.     {
  254.     dump_bind_db ();
  255.     dhcpsCleanup (6);
  256.     /@ Instead of exit(), the entry point of the server task should return. @/
  257.     exit (0); 
  258.     }  
  259. */
  260. /*******************************************************************************
  261. *
  262. * add_bind - record lease offers and active leases
  263. *
  264. * This routine stores the pending offers and active leases in the internal
  265. * linked list. The contents of the list are periodically written to permanent
  266. * storage by the dump_bind_db() routine defined above.
  267. *
  268. * RETURNS: 0 if successful, or -1 on memory allocation error.
  269. *
  270. * ERRNO: N/A
  271. *
  272. * NOMANUAL
  273. */
  274. int add_bind
  275.     (
  276.     struct dhcp_binding * bind /* binding record to store in memory */
  277.     )
  278.     {
  279.     struct hash_member *bindptr;
  280. #ifndef VIRTUAL_STACK
  281.     extern struct hash_member *bindlist;
  282. #endif
  283.     bindptr = (struct hash_member *)calloc (1, sizeof (struct hash_member));
  284.     if (bindptr == NULL) 
  285.         {
  286. #ifdef DHCPS_DEBUG
  287.         logMsg ("Warning: memory allocation error adding binding.n",
  288.                  0, 0, 0, 0, 0, 0);
  289. #endif
  290.         return (-1);
  291.         }
  292.     bindptr->next = bindlist;
  293.     bindptr->data = (hash_datum *)bind;
  294.     bindlist = bindptr;
  295.     nbind++;
  296.     return (0);
  297.     }
  298. /*******************************************************************************
  299. *
  300. * read_idtype - extract identifier type from input string
  301. *
  302. * This routine extracts the single byte which contains the numeric type from 
  303. * a numeric pair of the form <type>:<value>. It is used when parsing entries 
  304. * from the client identifier field of the address pool and binding databases, 
  305. * and for reading from the hardware address field contained in the binding 
  306. * database. Valid values for the ID type are listed in the "Assigned Numbers" 
  307. * RFC under the ARP section. RFC 1700 defined the following types:
  308. *
  309. *  Number Hardware Type (hrd)                 
  310. *  ------ -----------------------------------
  311. *       1 Ethernet (10Mb)
  312. *       2 Experimental Ethernet (3Mb)
  313. *       3 Amateur Radio AX.25
  314. *       4 Proteon ProNET Token Ring
  315. *       5 Chaos
  316. *       6 IEEE 802 Networks
  317. *       7 ARCNET
  318. *       8 Hyperchannel
  319. *       9 Lanstar
  320. *      10 Autonet Short Address
  321. *      11 LocalTalk
  322. *      12 LocalNet (IBM PCNet or SYTEK LocalNET)
  323. *      13 Ultra link
  324. *      14 SMDS
  325. *      15 Frame Relay
  326. *      16 Asynchronous Transmission Mode (ATM)
  327. *      17 HDLC
  328. *      18 Fibre Channel
  329. *      19 Asynchronous Transmission Mode (ATM)
  330. *      20 Serial Line
  331. *      21 Asynchronous Transmission Mode (ATM)
  332. *
  333. * RETURNS: 0 if successful, or -1 on parse error.
  334. *
  335. * ERRNO: N/A
  336. *
  337. * NOMANUAL
  338. */
  339. static int read_idtype
  340.     (
  341.     char **cp,  /* current location in input string */
  342.     u_char *idtype  /* pointer to storage for extracted value */
  343.     )
  344.     {
  345.     char tmpstr [MAXSTRINGLEN];
  346.     int j;
  347.     get_string (cp, tmpstr);
  348.  
  349.     if (sscanf (tmpstr, "%d", &j) != 1) 
  350.         {
  351. #ifdef DHCPS_DEBUG
  352.         logMsg ("Warning: Can't extract type value.n", 0, 0, 0, 0, 0, 0);
  353. #endif
  354.         return (-1);
  355.         }
  356.     *idtype = (u_char) j;
  357.     return (0);
  358.     }
  359. /*******************************************************************************
  360. *
  361. * read_cid - extract identifier value from input string
  362. *
  363. * This routine extracts the client ID value from a numeric pair of the form
  364. * <type>:<value>. It is used when parsing entries from the client identifier 
  365. * field of the address pool and binding databases. The value field is
  366. * represented as a string of characters representing a hexadecimal number,
  367. * preceded by 0x.
  368. *
  369. * RETURNS: 0 if successful, or -1 on parse error.
  370. *
  371. * ERRNO: N/A
  372. *
  373. * NOMANUAL
  374. */
  375. static int read_cid
  376.     (
  377.     char **cp,  /* current location in input string */
  378.     struct client_id *cid  /* pointer to storage for extracted value */
  379.     )
  380.     {
  381.     char tmp [MAXSTRINGLEN];
  382.     int i, j;
  383.     get_string (cp, tmp);
  384.     bzero (cid->id, MAXOPT);
  385.     /* 
  386.      * Determine length of field by ignoring the leading "0x" characters,
  387.      * then dividing for the two characters used for each byte.
  388.      */
  389.     cid->idlen = (strlen (tmp) - 2) / 2; 
  390.     if (cid->idlen == 0)
  391.         return (-1);
  392.     if (cid->idlen > MAXOPT) 
  393.         {
  394.         cid->idlen = MAXOPT;
  395.         logMsg ("Warning: client ID exceeds maximum length. Truncating.n",
  396.                  0, 0, 0, 0, 0, 0);
  397.         }
  398.     bzero (cid->id, cid->idlen);
  399.     /* Interpret characters in string as sequence of hexadecimal bytes. */
  400.     for (i = 0; i < cid->idlen; i++) 
  401.         {
  402.         if (sscanf (&tmp [i * 2  + 2], "%2x", &j) != 1) 
  403.             {
  404. #ifdef DHCPS_DEBUG
  405.             logMsg ("Warning: can't extract client ID.n", 0, 0, 0, 0, 0, 0);
  406. #endif
  407.             return (-1);
  408.             }
  409.         cid->id[i] = (char)j;
  410.         }
  411.     return (0);
  412.     }
  413. /*******************************************************************************
  414. *
  415. * read_haddr - extract client hardware address from input string
  416. *
  417. * This routine extracts the hardware address value from a numeric pair of the 
  418. * form <type>:<value>. It is used when parsing entries from the hardware
  419. * address field of the binding database. If preceded by 0x, the string is
  420. * interpreted as a sequence of hexadecimal numbers. Otherwise, it is copied
  421. * directly, without interpretation.
  422. *
  423. * RETURNS: 0 if successful, or -1 on parse error.
  424. *
  425. * ERRNO: N/A
  426. *
  427. * NOMANUAL
  428. */
  429. static int read_haddr
  430.     (
  431.     char **cp,  /* current location in input string */
  432.     struct chaddr *haddr  /* pointer to storage for extracted value */
  433.     )
  434.     {
  435.     char tmp [MAXSTRINGLEN];
  436.     int i, j;
  437.     get_string (cp, tmp);
  438.     /* Interpret string as hexadecimal number if preceded by 0x. */
  439.     if (tmp[0] != '' && tmp[0] == '0' && (tmp[1] == 'x' || tmp[1] == 'X')) 
  440.         {
  441.         /*
  442.          * Length consists of number of bytes (two characters each) and does
  443.          * not include the leading 0x. 
  444.          */
  445.         haddr->hlen = (strlen (tmp) - 2) / 2;
  446.         if (haddr->hlen > MAX_HLEN) 
  447.             {
  448.     haddr->hlen = MAX_HLEN;
  449.     logMsg ("Hardware address exceeds maximum length. Truncating.n",
  450.                      0, 0, 0, 0, 0, 0);
  451.             }
  452.         bzero (haddr->haddr, haddr->hlen);
  453.         for (i = 0; i < haddr->hlen; i++) 
  454.             {
  455.             if (sscanf (&tmp [i * 2 + 2], "%2x", &j) != 1) 
  456.                 {
  457. #ifdef DHCPS_DEBUG
  458.         logMsg ("Warning: error extracting hardware address.n",
  459.                          0, 0, 0, 0, 0, 0);
  460. #endif
  461.         return (-1);
  462.                 }
  463.             haddr->haddr[i] = (char) j;
  464.             }
  465.         } 
  466.     else 
  467.         {
  468.         haddr->hlen = strlen (tmp);
  469.         if (haddr->hlen > MAX_HLEN)
  470.             {
  471.             haddr->hlen = MAX_HLEN;
  472.     logMsg ("Hardware address exceeds maximum length. Truncating.n",
  473.                      0, 0, 0, 0, 0, 0);
  474.             }
  475.         bzero (haddr->haddr, haddr->hlen);
  476.         bcopy (tmp, haddr->haddr, haddr->hlen); 
  477.         }
  478.     return (0);
  479.     }
  480. /*******************************************************************************
  481. *
  482. * read_subnet - extract subnet number from input string
  483. *
  484. * This routine extracts the subnet number (in dotted decimal format) from the 
  485. * input string into the provided buffer. It is used when parsing entries from 
  486. * the subnet field of the binding database. If a client has changed subnets, 
  487. * the lease recorded in the binding database will not be renewed.
  488. *
  489. * RETURNS: 0 if successful, or -1 on parse error.
  490. *
  491. * ERRNO: N/A
  492. *
  493. * NOMANUAL
  494. */
  495. static int read_subnet
  496.     (
  497.     char **cp,  /* current location in input string */
  498.     struct in_addr *subnet  /* pointer to storage for extracted value */
  499.     )
  500.     {
  501.     char tmpstr [MAXSTRINGLEN];
  502.     char *pTmp;
  503.     STATUS result;
  504.     get_string (cp, tmpstr);
  505.     pTmp = tmpstr;
  506.     result = get_ip (&pTmp, subnet);
  507.     if (result != OK)
  508.         {
  509. #ifdef DHCPS_DEBUG
  510.         logMsg ("Warning: can't extract subnet number.n", 
  511.                  0, 0, 0, 0, 0, 0);
  512. #endif
  513.         return (-1);
  514.         }
  515.     return (0);
  516.     }
  517. /*******************************************************************************
  518. *
  519. * read_bind_db - extract offered and active leases from permanent storage
  520. *
  521. * This routine calls a hook routine, supplied by the user, to retrieve the 
  522. * entries for each active or pending lease. It builds the list of these 
  523. * entries and updates the internal data storage to prevent re-assignment of 
  524. * IP addresses already in use. It is called once on server startup.
  525. *
  526. * RETURNS: OK if data update completed, or ERROR otherwise.
  527. *
  528. * ERRNO: N/A
  529. *
  530. * NOMANUAL
  531. */
  532. STATUS read_bind_db (void)
  533.     {
  534.     char buffer [MAXSTRINGLEN];
  535.     char tmp [MAXSTRINGLEN];
  536.     char *bufptr = NULL;
  537.     unsigned buflen = 0;
  538.     struct dhcp_binding *binding = NULL;
  539.     STATUS result;
  540.     if (dhcpsLeaseHookRtn == NULL)
  541.         return (OK);
  542.     result = (* dhcpsLeaseHookRtn) (DHCPS_STORAGE_START, NULL, 0);
  543.     if (result != OK)
  544.          {
  545.          logMsg ("Warning: cannot open the binding database.n",
  546.                   0, 0, 0, 0, 0, 0);
  547.          return (ERROR);
  548.          }
  549.   /*
  550.    * Read binding information from entries with the following format:
  551.    *
  552.    *         idtype:id:subnet:htype:haddr:"expire_date":resource_name
  553.    */
  554.     FOREVER
  555.         {
  556.         buflen = sizeof (buffer);
  557.         /* Extract single entry from storage as NULL-terminated string. */
  558.         read_entry (buffer, &buflen);
  559.         if (buflen == 0) 
  560.             break;
  561.         bufptr = buffer;
  562.         if (buffer[0] == '')
  563.             return (OK);
  564.         /* Create linked list element. */
  565.     
  566.         binding = (struct dhcp_binding *)
  567.                       calloc (1, sizeof (struct dhcp_binding));
  568.         if (binding == NULL) 
  569.             {
  570. #ifdef DHCPS_DEBUG
  571.             logMsg("Error: Couldn't allocate memory in read_bind_dbn", 
  572.                     0, 0, 0, 0, 0, 0);
  573. #endif
  574.             return (ERROR); 
  575.             }
  576.         /* read client identifier type */
  577.         if (read_idtype (&bufptr, &binding->cid.idtype) != 0)
  578.             {
  579.             free (binding);
  580.             return (ERROR); 
  581.             }
  582.         /* read client identifier value */
  583.         adjust (&bufptr);
  584.         if (read_cid (&bufptr, &binding->cid) != 0)
  585.             {
  586.             free (binding);
  587.             return (ERROR); 
  588.             }
  589.         /* read subnet number of client */
  590.         adjust (&bufptr);
  591.         if (read_subnet (&bufptr, &binding->cid.subnet) != 0)
  592.             {
  593.             free (binding);
  594.             return (ERROR);
  595.             }
  596.         /* read hardware address type (e.g. "1" for 10 MB ethernet). */
  597.         adjust (&bufptr);
  598.         if (read_idtype (&bufptr, &binding->haddr.htype) != 0)
  599.             {
  600.             free (binding);
  601.             return (ERROR);
  602.             }
  603.         /* read client hardware address */
  604.         adjust (&bufptr);
  605.         if (read_haddr (&bufptr, &binding->haddr) != 0)
  606.             {
  607.             free (binding);
  608.             return (ERROR);
  609.             }
  610.         /* read expiration time for lease */
  611.         adjust (&bufptr);
  612.         get_string (&bufptr, tmp);
  613.         if (strcmp (tmp, "infinity") == 0 || strcmp(tmp, "bootp") == 0) 
  614.             binding->expire_epoch = 0xffffffff;
  615.         else
  616.             binding->expire_epoch = strtotime (tmp);
  617.         /* read name of lease descriptor */
  618.         adjust (&bufptr);
  619.         get_string (&bufptr, tmp);
  620.         if (strlen (tmp) > MAX_NAME)
  621.             {
  622.             bcopy (tmp, binding->res_name, MAX_NAME);
  623.             binding->res_name [MAX_NAME] = '';
  624.             }
  625.         else
  626.             {
  627.             bcopy (tmp, binding->res_name, strlen (tmp));
  628.             binding->res_name [strlen (tmp)] = '';
  629.             }
  630.         /* Find lease descriptor with given name. */
  631.         binding->res = (struct dhcp_resource *) hash_find ( &nmhashtable, 
  632.                                                             binding->res_name, 
  633.                                                     strlen (binding->res_name),
  634.                                            resnmcmp, 
  635.                                                            binding->res_name);
  636.         if (binding->res == NULL) 
  637.             {
  638. #ifdef DHCPS_DEBUG
  639.             logMsg ("Warning: can't find the resource "%s"", 
  640.                      (int)binding->res_name, 0, 0, 0, 0, 0);
  641. #endif
  642.             /* free binding info */
  643.             free (binding);
  644.             continue;
  645.             }
  646.         /* Link lease record to lease descriptor and store in hash table. */
  647.         binding->res->binding = binding;
  648.         binding->flag |= COMPLETE_ENTRY;
  649.         if (hash_ins (&cidhashtable, binding->cid.id, binding->cid.idlen,
  650.       bindcidcmp, &binding->cid, binding) < 0) 
  651.             {
  652. #ifdef DHCPS_DEBUG
  653.             logMsg ("Error: Couldn't add client identifier to hash table.n", 
  654.                      0, 0, 0, 0, 0, 0);
  655. #endif
  656.             free (binding);
  657.             return (ERROR); 
  658.             }
  659.   
  660.         /* Add lease record to linked list. */
  661.         if (add_bind (binding) != 0)
  662.             {
  663.             free (binding);
  664.             return (ERROR); 
  665.             }
  666.         }
  667. #ifdef DHCPS_DEBUG
  668.     logMsg ("dhcps: read %d entries from binding and addr-pool database.n", 
  669.             nbind, 0, 0, 0, 0, 0);
  670. #endif
  671.     return (OK);
  672.     }
  673. /*******************************************************************************
  674. *
  675. * read_relay_db - parse relay agent database
  676. *
  677. * This routine creates the list of available relay agents. The DHCP server
  678. * will accept messages forwarded from other subnets if they are delivered
  679. * by a relay agent contained in the list.
  680. *
  681. * RETURNS: OK if list created, or ERROR otherwise.
  682. *
  683. * ERRNO: N/A
  684. *
  685. * NOMANUAL
  686. */
  687. void read_relay_db 
  688.     (
  689.     int dbsize  /* number of relay agents in database */
  690.     )
  691.     {
  692.     char relayIP [INET_ADDR_LEN];
  693.     char subnet_mask [INET_ADDR_LEN];
  694.     int nrelay = 0;
  695.     int loop;
  696.     int result;
  697.     struct relay_acl *acl = NULL;
  698.     /*
  699.      * Read database entries, which contain relay agent's IP address and 
  700.      * subnet number. If it finds a NULL entry for pAddress it will stop
  701.      * processing the table.
  702.      */
  703.     for (loop = 0; (loop < dbsize) &&
  704.  (pDhcpsRelaySourceTbl [loop].pAddress); loop++)
  705.         {
  706.         sprintf (relayIP, "%s", pDhcpsRelaySourceTbl [loop].pAddress);
  707.         sprintf (subnet_mask, "%s", pDhcpsRelaySourceTbl [loop].pMask);
  708.         acl = (struct relay_acl *)calloc (1, sizeof (struct relay_acl));
  709.         if (acl == NULL) 
  710.             {
  711. #ifdef DHCPS_DEBUG
  712.             logMsg ("Memory allocation error reading relay agent database.n", 
  713.                      0, 0, 0, 0, 0, 0);
  714. #endif
  715.             break;
  716.             }
  717.    
  718.         acl->relay.s_addr = inet_addr (relayIP);
  719.         acl->subnet_mask.s_addr = inet_addr (subnet_mask);
  720.         if (acl->relay.s_addr == -1 || acl->subnet_mask.s_addr == -1) 
  721.             {
  722. #ifdef DHCPS_DEBUG
  723.             logMsg ("Conversion error reading relay database.n",
  724.                      0, 0, 0, 0, 0, 0);
  725. #endif
  726.             free (acl);
  727.             continue;
  728.             }
  729.         /* Store entry in hash table, keyed on relay agent IP address. */
  730.         result = hash_ins (&relayhashtable, (char *)&acl->relay, 
  731.                            sizeof (struct in_addr), relayipcmp, 
  732.                            &acl->relay, acl);
  733.         if (result < 0) 
  734.             {
  735. #ifdef DHCPS_DEBUG
  736.             logMsg ("hash insertion failed in read_relay_db()", 
  737.                     0, 0, 0, 0, 0, 0);
  738. #endif
  739.             free (acl);
  740.             break; 
  741.             }
  742.         nrelay++;
  743.         }
  744. #ifdef DHCPS_DEBUG
  745.     logMsg ("dhcps: read %d entries from relay agent database.n", nrelay, 
  746.              0, 0, 0, 0, 0);
  747. #endif
  748.     return;
  749.     }
  750. /*******************************************************************************
  751. *
  752. * strtotime - parse lease expiration time
  753. *
  754. * This routine converts the lease expiration time stored in the binding
  755. * database into the internal calendar time. That field has the following
  756. * format:
  757. *                "Wed Feb 19 14:17:39 1997"
  758. *
  759. * On generic VxWorks systems, the internal calendar time is the number of 
  760. * seconds since system startup. For correct operation of DHCP, it should be 
  761. * the number of seconds since some absolute base time, such as 00:00:00 GMT, 
  762. * Jan. 1, 1970, which is the base value used on Unix systems. Adding this
  763. * functionality to VxWorks requires BSP modifications. Without this feature, 
  764. * rebooting the server automatically extends all leases. This behavior will 
  765. * reduce protocol efficiency, since the server will not re-assign addresses 
  766. * that (incorrectly) are recorded as still in use, but it will not cause 
  767. * duplicate IP address assignment.
  768. *
  769. * RETURNS: Calendar time, or 0 if not available.
  770. *
  771. * ERRNO: N/A
  772. *
  773. * NOMANUAL
  774. */
  775. static time_t strtotime
  776.     (
  777.     char *date_str  /* String containing lease expiration time. */
  778.     )
  779.     {
  780.     struct tm   tmval;
  781.     char week[4];
  782.     char month[4];
  783.     int year = 0; 
  784.     int i = 0;
  785.     struct map 
  786.         {
  787.         char symbol[4];
  788.         int code;
  789.         };
  790.     struct map week_list[7];
  791.     struct map month_list[12];
  792.     if (*date_str == '')
  793.         return (0);
  794.     /* Initialize days of week and months of year. */
  795.     week_list[0].code = 0;
  796.     strcpy (week_list[0].symbol, "Sun");
  797.     week_list[1].code = 1;
  798.     strcpy (week_list[1].symbol, "Mon");
  799.     week_list[2].code = 2;
  800.     strcpy (week_list[2].symbol, "Tue");
  801.     week_list[3].code = 3;
  802.     strcpy (week_list[3].symbol, "Wed");
  803.     week_list[4].code = 4;
  804.     strcpy (week_list[4].symbol, "Thu");
  805.     week_list[5].code = 5;
  806.     strcpy (week_list[5].symbol, "Fri");
  807.     week_list[6].code = 6;
  808.     strcpy (week_list[6].symbol, "Sat");
  809.     month_list[0].code = 0;
  810.     strcpy (month_list[0].symbol, "Jan");
  811.     month_list[1].code = 1;
  812.     strcpy (month_list[1].symbol, "Feb");
  813.     month_list[2].code = 2;
  814.     strcpy (month_list[2].symbol, "Mar");
  815.     month_list[3].code = 3;
  816.     strcpy (month_list[3].symbol, "Apr");
  817.     month_list[4].code = 4;
  818.     strcpy (month_list[4].symbol, "May");
  819.     month_list[5].code = 5;
  820.     strcpy (month_list[5].symbol, "Jun");
  821.     month_list[6].code = 6;
  822.     strcpy (month_list[6].symbol, "Jul");
  823.     month_list[7].code = 7;
  824.     strcpy (month_list[7].symbol, "Aug");
  825.     month_list[8].code = 8;
  826.     strcpy (month_list[8].symbol, "Sep");
  827.     month_list[9].code = 9;
  828.     strcpy (month_list[9].symbol, "Oct");
  829.     month_list[10].code = 10;
  830.     strcpy (month_list[10].symbol, "Nov");
  831.     month_list[11].code = 11;
  832.     strcpy (month_list[11].symbol, "Dec");
  833.     bzero ( (char *)&tmval, sizeof (tmval));
  834.     bzero (week, sizeof (week));
  835.     bzero (month, sizeof (month));
  836.     /*
  837.      * Parse date string into separate fields. Day of month, hour, 
  838.      * minute, and second are in format used by mktime() below. 
  839.      */
  840.     sscanf (date_str, "%s %s %u %u:%u:%u %u", week, month, &(tmval.tm_mday),
  841.               &(tmval.tm_hour), &(tmval.tm_min), &(tmval.tm_sec), 
  842.                       &year);
  843.     /* Adjust entry for base year. */
  844.     tmval.tm_year = year - 1900;
  845.     /* Store value for day of week. (Sunday = 0). */
  846.   
  847.     for (i = 0; i < 7; i++) 
  848.         if (strcmp(week_list[i].symbol, week) == 0)
  849.     break;
  850.     if (i < 7) 
  851.         tmval.tm_wday = week_list[i].code;
  852.     else 
  853.         return (0);
  854.     /* Store value for month of year. (January = 0, December = 11). */
  855.     for (i = 0; i < 12; i++)
  856.          if (strcmp (month_list[i].symbol, month) == 0)
  857.              break;
  858.     if (i < 12) 
  859.         tmval.tm_mon = month_list[i].code;
  860.     else
  861.          return (0);
  862.     return (mktime (&tmval));
  863.     }
  864. /*******************************************************************************
  865. *
  866. * get_ip - extract numbers in IP address format
  867. *
  868. * This routine extracts IP addresses and subnet masks (in dotted decimal 
  869. * format) from the input string into the provided structure. It is used when 
  870. * retrieving entries from the address pool and binding databases.
  871. *
  872. * RETURNS: OK if successful, or ERROR otherwise.
  873. *
  874. * ERRNO: N/A
  875. *
  876. * NOMANUAL
  877. */
  878. static STATUS get_ip
  879.     (
  880.     char **src,  /* current location in input string */
  881.     struct in_addr *target /* pointer to storage for extracted value */
  882.     )
  883.     {
  884.     if (prs_inaddr (src, &target->s_addr) != 0) 
  885.         return (ERROR);
  886.     return (OK);
  887.     }
  888. /*******************************************************************************
  889. *
  890. * resipcmp - verify IP addresses for address pool entries
  891. *
  892. * This routine compares a hash table key against the IP address of a address 
  893. * pool entry. It is used when storing and retrieving lease descriptors with 
  894. * the internal hash tables.
  895. *
  896. * RETURNS: TRUE if addresses match, or FALSE otherwise.
  897. *
  898. * ERRNO: N/A
  899. *
  900. * NOMANUAL
  901. */
  902. int resipcmp
  903.     (
  904.     struct in_addr *  key,  /* pointer to hash table key */
  905.     struct dhcp_resource *  rp /* pointer to lease resource */
  906.     )
  907.     {
  908.     return (key->s_addr == rp->ip_addr.s_addr);
  909.     }
  910. /*******************************************************************************
  911. *
  912. * relayipcmp - verify IP addresses for relay agent entries
  913. *
  914. * This routine compares a hash table key against the IP address of a relay
  915. * agent. It is used when storing and retrieving relay agent entries in the 
  916. * internal hash table.
  917. *
  918. * RETURNS: TRUE if addresses match, or FALSE otherwise.
  919. *
  920. * ERRNO: N/A
  921. *
  922. * NOMANUAL
  923. */
  924. int relayipcmp
  925.     (
  926.     struct in_addr *  key,  /* pointer to hash table key */
  927.     struct relay_acl *  aclp    /* pointer to relay agent entry */
  928.     )
  929.     {
  930.     return (key->s_addr == aclp->relay.s_addr);
  931.     }
  932. /*******************************************************************************
  933. *
  934. * paramcidcmp - verify client identifiers for additional parameters
  935. *
  936. * This routine compares a hash table key against the client identifier 
  937. * contained in a lease descriptor to verify matching types and values. It 
  938. * also checks the recorded subnet against the actual subnet. It is used to
  939. * verify client information when accessing the parameters hash table.
  940. *
  941. * RETURNS: TRUE if entries OK, or FALSE otherwise.
  942. *
  943. * ERRNO: N/A
  944. *
  945. * NOMANUAL
  946. */
  947. int paramcidcmp
  948.     (
  949.     struct client_id *  key,  /* pointer to hash table key */
  950.     struct dhcp_resource *  rp /* pointer to lease descriptor */
  951.     )
  952.     {
  953.     return (rp != NULL && rp->binding != NULL &&
  954.             key->idtype == rp->binding->cid.idtype && 
  955.             key->idlen == rp->binding->cid.idlen &&
  956.             bcmp (key->id, rp->binding->cid.id, key->idlen) == 0);
  957.     }
  958. /*******************************************************************************
  959. *
  960. * bindcidcmp - verify client identifiers for active or offered leases
  961. *
  962. * This routine compares a hash table key against the client identifier 
  963. * contained in a lease record to verify matching types and values. It also 
  964. * checks the recorded subnet against the actual subnet. It is used to verify 
  965. * client information when establishing or renewing leases in response to DHCP
  966. * request messages.
  967. *
  968. * RETURNS: TRUE if entries OK, or FALSE otherwise.
  969. *
  970. * ERRNO: N/A
  971. *
  972. * NOMANUAL
  973. */
  974. int bindcidcmp
  975.     (
  976.     struct client_id *  key,  /* pointer to hash table key */
  977.     struct dhcp_binding *  bp  /* pointer to lease record */
  978.     )
  979.     {
  980.     return (bp != NULL &&
  981.             key->subnet.s_addr == bp->cid.subnet.s_addr &&
  982.             key->idtype == bp->cid.idtype && key->idlen == bp->cid.idlen &&
  983.             bcmp (key->id, bp->cid.id, key->idlen) == 0);
  984.     }
  985. /*******************************************************************************
  986. *
  987. * set_default - provide values for mandatory configuration parameters
  988. *
  989. * This routine provides default values for fields in a lease descriptor if
  990. * not specified by the administrator in the corresponding address pool entry. 
  991. * It ensures that every lease descriptor includes a default and maximum lease
  992. * length, and a subnet mask. Additionally, it makes entries which contain a 
  993. * client identifier available for BOOTP clients, and resets the maximum lease 
  994. * for all such entries to infinity.
  995. *
  996. * RETURNS: TRUE if entries OK, or FALSE otherwise.
  997. *
  998. * ERRNO: N/A
  999. *
  1000. * NOMANUAL
  1001. */
  1002. void set_default
  1003.     (
  1004.     struct dhcp_resource *  rp /* pointer to lease descriptor */
  1005.     )
  1006.     {
  1007.     if (ISCLR (rp->valid, S_DEFAULT_LEASE))
  1008.         {
  1009.         SETBIT (rp->valid, S_DEFAULT_LEASE);
  1010.         rp->default_lease = dhcps_dflt_lease;
  1011.         }
  1012.     if (ISCLR (rp->valid, S_MAX_LEASE)) 
  1013.         {
  1014.         SETBIT (rp->valid, S_MAX_LEASE);
  1015.         rp->max_lease = dhcps_max_lease;
  1016.         }
  1017.     if (ISSET (rp->valid, S_CLIENT_ID)) 
  1018.         {
  1019.         SETBIT (rp->valid, S_ALLOW_BOOTP);
  1020.         rp->allow_bootp = TRUE;
  1021.         }
  1022.     if (ISSET (rp->valid, S_ALLOW_BOOTP) && rp->allow_bootp == TRUE) 
  1023.         {
  1024.         SETBIT(rp->valid, S_MAX_LEASE);
  1025.         rp->max_lease = 0xffffffff;   /* infinity */
  1026.         }
  1027.     if (ISCLR(rp->valid, S_SUBNET_MASK)) 
  1028.         {
  1029.         SETBIT (rp->valid, S_SUBNET_MASK);
  1030.         default_netmask (&rp->ip_addr, &rp->subnet_mask);
  1031.         }
  1032.   return;
  1033. }
  1034. /*******************************************************************************
  1035. *
  1036. * default_netmask - determine the subnet for an IP address
  1037. *
  1038. * This routine assigns a netmask for the given IP address based on the IP 
  1039. * class value. It is called if no netmask was specified in the corresponding 
  1040. * address pool entry. It makes no provision for subnetting. The DHCP server 
  1041. * will not issue an address to a client if it is not on the client's subnet. 
  1042. * Therefore, if subnetting is used, the netmask for each address pool entry 
  1043. * must be specified explicitly.
  1044. *
  1045. * RETURNS: N/A
  1046. *
  1047. * ERRNO: N/A
  1048. *
  1049. * NOMANUAL
  1050. */
  1051. static void default_netmask
  1052.     (
  1053.     struct in_addr *ipaddr,  /* pointer to IP address */
  1054.     struct in_addr *dfltnetmask /* pointer to storage for extracted value */
  1055.     )
  1056.     {
  1057.     int top = 0;
  1058.     top = ntohl (ipaddr->s_addr) >> 30;
  1059.     switch (top) 
  1060.         {
  1061.         case 0:  /* class A */
  1062. case 1:  /* class A */
  1063.             dfltnetmask->s_addr = htonl (0xff000000);
  1064.             break;
  1065.         case 2:  /* class B */
  1066.             dfltnetmask->s_addr = htonl (0xffff0000);
  1067.             break;
  1068.         case 3:  /* class C */
  1069.             dfltnetmask->s_addr = htonl (0xffffff00);
  1070.             break;
  1071.         default:
  1072.             dfltnetmask->s_addr = 0xffffffff;
  1073.             break;
  1074.         }
  1075.     return;
  1076.     }
  1077. /*******************************************************************************
  1078. *
  1079. * proc_sname - extract the DHCP server name
  1080. *
  1081. * This routine sets the TFTP server name field of the lease descriptor to the
  1082. * value specified by a "snam" field in the address pool database. The field 
  1083. * is cleared when "snam@", specifying deletion, is encountered.
  1084. *
  1085. * RETURNS: 0, always.
  1086. *
  1087. * ERRNO: N/A
  1088. *
  1089. * NOMANUAL
  1090. */
  1091. int proc_sname
  1092.     (
  1093.     int code,  /* resource code for address pool field */
  1094.     int optype,  /* operation type (addition or deletion) */
  1095.     char **symbol,  /* current location in input string */
  1096.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  1097.     )
  1098.     {
  1099.     char tmpstr [MAXSTRINGLEN];
  1100.     if (optype == OP_ADDITION) 
  1101.         {
  1102.         get_string (symbol, tmpstr);
  1103.         if (strlen (tmpstr) > MAX_SNAME)
  1104.             {
  1105.             bcopy (tmpstr, rp->sname, MAX_SNAME);
  1106.             rp->sname [MAX_SNAME] = '';
  1107.             }
  1108.         else
  1109.             {
  1110.             bcopy (tmpstr, rp->sname, strlen (tmpstr));
  1111.             rp->sname [strlen (tmpstr)] = '';
  1112.             }
  1113.         } 
  1114.     else 
  1115.         rp->sname[0] = '';
  1116.     return (0);
  1117.     }
  1118. /*******************************************************************************
  1119. *
  1120. * proc_file - extract the boot image filename
  1121. *
  1122. * This routine sets the bootfile name field of the lease descriptor to the
  1123. * value specified by a "file" field in the address pool database. The
  1124. * field is cleared when "file@", specifying deletion, is encountered.
  1125. *
  1126. * RETURNS: 0, always.
  1127. *
  1128. * ERRNO: N/A
  1129. *
  1130. * NOMANUAL
  1131. */
  1132. int proc_file
  1133.     (
  1134.     int code,  /* resource code for address pool field */
  1135.     int optype,  /* operation type (addition or deletion) */
  1136.     char **symbol,  /* current location in input string */
  1137.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  1138.     )
  1139.     {
  1140.     char tmpstr [MAXSTRINGLEN];
  1141.     if (optype == OP_ADDITION) 
  1142.         {
  1143.         get_string (symbol, tmpstr);
  1144.         if (strlen (tmpstr) > MAX_FILE)
  1145.             {
  1146.             bcopy (tmpstr, rp->file, MAX_FILE);
  1147.             rp->file [MAX_FILE] = '';
  1148.             }
  1149.         else
  1150.             {
  1151.             bcopy (tmpstr, rp->file, strlen (tmpstr));
  1152.             rp->file [strlen (tmpstr)] = '';
  1153.             }
  1154.         } 
  1155.     else
  1156.         rp->file[0] = '';
  1157.     return (0);
  1158.     }
  1159. /*******************************************************************************
  1160. *
  1161. * proc_clid - handle the client identifier
  1162. *
  1163. * This routine updates the lease descriptor and internal data structures 
  1164. * after extracting a client identifier from "clid" or "pmid" entries in 
  1165. * the address pool database. The "clid" symbol specifies a manual lease 
  1166. * which will only be issued to a specific client on the appropriate subnet. 
  1167. * The "pmid" symbol is included in a lease descriptor specifying additional 
  1168. * parameters to be provided to a specific client along with a dynamic lease. 
  1169. *
  1170. * RETURNS: 0 if update completed, or -1 on error.
  1171. *
  1172. * ERRNO: N/A
  1173. *
  1174. * NOMANUAL
  1175. */
  1176. int proc_clid
  1177.     (
  1178.     int code,  /* resource code for address pool field */
  1179.     int optype,  /* operation type (addition or deletion) */
  1180.     char **symbol,  /* current location in input string */
  1181.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  1182.     )
  1183.     {
  1184.     char bufptr[MAXSTRINGLEN];
  1185.     struct in_addr tmpsubnet;
  1186.     struct dhcp_binding *binding;
  1187.     char *target;
  1188.     int result;
  1189.     /* For client ID (manual lease), return immediately if no IP address. */
  1190.     if (code == S_CLIENT_ID && rp->ip_addr.s_addr == 0)
  1191.         return (-1);
  1192.     /* For parameter ID, return error if client or class already specified. */
  1193.     
  1194.     if (ISSET (rp->valid, S_PARAM_ID) || ISSET (rp->valid, S_CLASS_ID))
  1195.         return (-1); 
  1196.     if (rp->binding != NULL)
  1197.         return (-1);
  1198.     /* Create a lease record to store the identifier information. */
  1199.     binding = (struct dhcp_binding *)calloc (1, sizeof (struct dhcp_binding));
  1200.     if (binding == NULL) 
  1201.         {
  1202. #ifdef DHCPS_DEBUG
  1203.         logMsg ("Warning: memory allocation error reading identifier.n",
  1204.                  0, 0, 0, 0, 0, 0);
  1205. #endif
  1206.         return (-1);
  1207.         }
  1208.     target = (char *)bufptr;
  1209.     get_string (symbol, target);
  1210.     if (bufptr[0] == '') 
  1211.         {
  1212.         if (code == S_CLIENT_ID)
  1213.             free (binding);
  1214.         return (-1);
  1215.         }
  1216.     /* read client identifier type */
  1217.     if (read_idtype (&target, &binding->cid.idtype) != 0)
  1218.         {
  1219.         free (binding);
  1220.         return (-1);
  1221.         }
  1222.     /* read client identifier value */
  1223.     adjust (&target);
  1224.     if (read_cid (&target, &binding->cid) != 0)
  1225.         {
  1226.         free (binding);
  1227.         return (-1);
  1228.         }
  1229.     /* For manual leases, fill all fields in associated lease record. */
  1230.     if (code == S_CLIENT_ID)
  1231.         {
  1232.         /* get subnet number */
  1233.         if (rp->subnet_mask.s_addr != 0)
  1234.             binding->cid.subnet.s_addr =
  1235.                                 rp->ip_addr.s_addr & rp->subnet_mask.s_addr;  
  1236.         else 
  1237.             {
  1238.             default_netmask (&rp->ip_addr, &tmpsubnet);
  1239.             binding->cid.subnet.s_addr = rp->ip_addr.s_addr & tmpsubnet.s_addr;
  1240.             }
  1241.         /* hardware address is unknown, so use client identifer */
  1242.         binding->haddr.htype = binding->cid.idtype;
  1243.         if (binding->cid.idlen > MAX_HLEN)
  1244.             {
  1245.             binding->haddr.hlen = MAX_HLEN;
  1246.             bcopy (binding->cid.id, binding->haddr.haddr, MAX_HLEN);
  1247.             }
  1248.         else
  1249.             {
  1250.             binding->haddr.hlen = binding->cid.idlen;
  1251.             bcopy (binding->cid.id, binding->haddr.haddr, binding->cid.idlen);
  1252.             }
  1253.         /* Expiration is meaningless for client-specific leases. */
  1254.         binding->expire_epoch = 0xffffffff;
  1255.         /* Store name of associated lease descriptor. */
  1256.         bcopy (rp->entryname, binding->res_name, strlen (rp->entryname));
  1257.         binding->res_name [strlen (rp->entryname)] = '';
  1258.         }
  1259.     /* Link identifier record to lease descriptor. */
  1260.     binding->res = rp;
  1261.     binding->res->binding = binding;
  1262.     /* Add entry for manual lease descriptor to appropriate hash table. */
  1263.     if (code == S_CLIENT_ID) 
  1264.         {
  1265.         binding->flag = (COMPLETE_ENTRY | STATIC_ENTRY);
  1266.         result = hash_ins (&cidhashtable, binding->cid.id, binding->cid.idlen,
  1267.                    bindcidcmp, &binding->cid, binding);
  1268.         if (result < 0) 
  1269.             {
  1270. #ifdef DHCPS_DEBUG
  1271.             logMsg ("Warning: hash table insertion failed for client ID.n",
  1272.                      0, 0, 0, 0, 0, 0);
  1273. #endif
  1274.             free (binding);
  1275.             return (-1);
  1276.             }
  1277.         result = add_bind (binding);
  1278.         if (result != 0)
  1279.             {
  1280.             free (binding);
  1281.             return (-1);
  1282.             }
  1283.         }
  1284.     else     /* For "pmid", insert into parameters hash table */
  1285.         {
  1286.         result = hash_ins (&paramhashtable, 
  1287.                            binding->cid.id, binding->cid.idlen,
  1288.                    paramcidcmp, &binding->cid, rp);
  1289.         if (result < 0) 
  1290.             {
  1291. #ifdef DHCPS_DEBUG
  1292.             logMsg ("Warning: hash table insertion failed for client ID.n",
  1293.                      0, 0, 0, 0, 0, 0);
  1294. #endif
  1295.             free (binding);
  1296.             return (-1);
  1297.             }
  1298.         }
  1299.     return (0);
  1300.     }
  1301. /*******************************************************************************
  1302. *
  1303. * proc_class - handle the class identifier
  1304. *
  1305. * This routine updates the lease descriptor and internal data structures after
  1306. * extracting a class identifier from "clas" field in the address pool database.
  1307. * The class identifier is included in an address pool entry specifying 
  1308. * additional parameters to be provided to any client which is a member of the 
  1309. * class.
  1310. *
  1311. * RETURNS: 0 if update completed, or -1 on error.
  1312. *
  1313. * ERRNO: N/A
  1314. *
  1315. * NOMANUAL
  1316. */
  1317. int proc_class
  1318.     (
  1319.     int code,  /* resource code for address pool field */
  1320.     int optype,  /* operation type (always OP_ADDITION) */
  1321.     char **symbol,  /* current location in input string */
  1322.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  1323.     )
  1324.     {
  1325.     char buffer[MAXSTRINGLEN];
  1326.     struct dhcp_binding *binding;
  1327.     char *target;
  1328.     int result;
  1329.     /* Return error if descriptor already has client or class parameters. */
  1330.     if (ISSET (rp->valid, S_PARAM_ID) || ISSET (rp->valid, S_CLASS_ID))
  1331.         return (-1);
  1332.     if (rp->binding != NULL)
  1333.         return (-1);
  1334.     target = (char *)buffer;
  1335.     get_string (symbol, target);
  1336.     /* Create a lease record to store the identifier information. */
  1337.     binding = (struct dhcp_binding *)calloc (1, sizeof (struct dhcp_binding));
  1338.     if (binding == NULL) 
  1339.         {
  1340. #ifdef DHCPS_DEBUG
  1341.         logMsg ("Warning: memory allocation error reading identifier.n",
  1342.                  0, 0, 0, 0, 0, 0);
  1343. #endif
  1344.         return (-1);
  1345.         }
  1346.     target = (char *)buffer;
  1347.     get_string (symbol, target);
  1348.     /*
  1349.      * Record class identifier. The type remains 0, which is unused by
  1350.      * client identifiers.
  1351.      */
  1352.     if (strlen (buffer) > MAXOPT - 1)
  1353.         {
  1354.         binding->cid.idlen = MAXOPT - 1; 
  1355.         bcopy (buffer, binding->cid.id, MAXOPT - 1);
  1356.         binding->cid.id[MAXOPT - 1] = '';
  1357.         }
  1358.     else
  1359.         {
  1360.         binding->cid.idlen = strlen (buffer);
  1361.         bcopy (buffer, binding->cid.id, strlen (buffer));
  1362.         binding->cid.id [strlen (buffer)] = '';
  1363.         }
  1364.     /* Link identifier record to lease descriptor. */
  1365.     binding->res = rp;
  1366.     binding->res->binding = binding;
  1367.     /* Add entry to parameters hash table. */
  1368.     result = hash_ins (&paramhashtable, 
  1369.                        binding->cid.id, binding->cid.idlen,
  1370.                        paramcidcmp, &binding->cid, rp);
  1371.     if (result < 0) 
  1372.         {
  1373. #ifdef DHCPS_DEBUG
  1374.         logMsg ("Warning: hash table insertion failed for client ID.n",
  1375.                  0, 0, 0, 0, 0, 0);
  1376. #endif
  1377.         free (binding);
  1378.         return (-1);
  1379.         }
  1380.     return (0);
  1381.     }
  1382. /*******************************************************************************
  1383. *
  1384. * proc_tblc - handle inclusion of address pool entries
  1385. *
  1386. * This routine processes entry quotation specified by a "tblc" (table
  1387. * continuation) entry in the address pool database. After retrieving the
  1388. * named descriptor, any values in the existing entry not already specified in
  1389. * the database are copied from the quoted entry.
  1390. *
  1391. * RETURNS: 0 if quotation completed, or -1 if matching entry not found.
  1392. *
  1393. * ERRNO: N/A
  1394. *
  1395. * NOMANUAL
  1396. */
  1397. int proc_tblc
  1398.     (
  1399.     int code,  /* resource code for address pool field */
  1400.     int optype,  /* operation type (always OP_ADDITION) */
  1401.     char **symbol,  /* current location in input string */
  1402.     struct dhcp_resource *rp1 /* pointer to lease descriptor */
  1403.     )
  1404.     {
  1405.     struct dhcp_resource *rp2 = NULL;
  1406.     char tmpstr [MAXSTRINGLEN];
  1407.     char *pTmp;
  1408.     int i = 0;
  1409.     get_string (symbol, tmpstr);
  1410.     pTmp = tmpstr;
  1411.     rp2 = (struct dhcp_resource *) hash_find (&nmhashtable, pTmp,
  1412.                                               strlen (pTmp), resnmcmp, pTmp);
  1413.     if (rp2 == NULL) 
  1414.         {
  1415. #ifdef DHCPS_DEBUG
  1416.         logMsg ("Warning: Can't find table entry "%s"n", (int)tmpstr,
  1417.                  0, 0, 0, 0, 0);
  1418. #endif
  1419.         return (-1);
  1420.         }
  1421.     if (ISCLR (rp1->valid, S_SNAME)) 
  1422.         strcpy (rp1->sname, rp2->sname);
  1423.     if (ISCLR (rp1->valid, S_FILE)) 
  1424.         strcpy (rp1->file, rp2->file);
  1425.     if (ISCLR (rp1->valid, S_SIADDR))
  1426.         rp1->siaddr = rp2->siaddr;
  1427.     if (ISCLR (rp1->valid, S_ALLOW_BOOTP)) 
  1428.         rp1->allow_bootp = rp2->allow_bootp;
  1429.     if (ISCLR (rp1->valid, S_IP_ADDR)) 
  1430.         rp1->ip_addr = rp2->ip_addr;
  1431.     if (ISCLR (rp1->valid, S_MAX_LEASE)) 
  1432.         rp1->max_lease = rp2->max_lease;
  1433.     if (ISCLR (rp1->valid, S_DEFAULT_LEASE)) 
  1434.         rp1->default_lease = rp2->default_lease;
  1435.     if (ISCLR (rp1->valid, S_SUBNET_MASK)) 
  1436.         rp1->subnet_mask = rp2->subnet_mask;
  1437.     if (ISCLR (rp1->valid, S_TIME_OFFSET)) 
  1438.         rp1->time_offset = rp2->time_offset;
  1439.     if (ISCLR (rp1->valid, S_ROUTER)) 
  1440.         {
  1441.         rp1->router.addr = calloc (rp2->router.num, sizeof (struct in_addr));
  1442.         if (rp1->router.addr != NULL)
  1443.             {
  1444.             rp1->router.num = rp2->router.num;
  1445.             bcopy ((char *)rp2->router.addr, (char *)rp1->router.addr,
  1446.                    rp2->router.num * sizeof (struct in_addr));
  1447.             }
  1448.         }
  1449.     if (ISCLR (rp1->valid, S_TIME_SERVER)) 
  1450.         {
  1451.         rp1->time_server.addr = calloc (rp2->time_server.num, 
  1452.                                         sizeof (struct in_addr));
  1453.         if (rp1->time_server.addr != NULL)
  1454.             {
  1455.             rp1->time_server.num = rp2->time_server.num;
  1456.             bcopy ((char *)rp2->time_server.addr, (char *)rp1->time_server.addr,
  1457.                    rp2->time_server.num * sizeof (struct in_addr));
  1458.             }
  1459.         }
  1460.     if (ISCLR (rp1->valid, S_NAME_SERVER)) 
  1461.         {
  1462.         rp1->name_server.addr = calloc (rp2->name_server.num, 
  1463.                                         sizeof (struct in_addr));
  1464.         if (rp1->name_server.addr != NULL)
  1465.             {
  1466.             rp1->name_server.num = rp2->name_server.num;
  1467.             bcopy ((char *)rp2->name_server.addr, (char *)rp1->name_server.addr,
  1468.                    rp2->name_server.num * sizeof (struct in_addr));
  1469.             }
  1470.         }
  1471.     if (ISCLR (rp1->valid, S_DNS_SERVER)) 
  1472.         {
  1473.         rp1->dns_server.addr = calloc (rp2->dns_server.num, 
  1474.                                        sizeof (struct in_addr));
  1475.         if (rp1->dns_server.addr != NULL)
  1476.             {
  1477.             rp1->dns_server.num = rp2->dns_server.num;
  1478.             bcopy ((char *)rp2->dns_server.addr, (char *)rp1->dns_server.addr,
  1479.                    rp2->dns_server.num * sizeof (struct in_addr));
  1480.             }
  1481.         }
  1482.     if (ISCLR (rp1->valid, S_LOG_SERVER)) 
  1483.         {
  1484.         rp1->log_server.addr = calloc (rp2->log_server.num, 
  1485.                                        sizeof (struct in_addr));
  1486.         if (rp1->log_server.addr != NULL)
  1487.             {
  1488.             rp1->log_server.num = rp2->log_server.num;
  1489.             bcopy ((char *)rp2->log_server.addr, (char *)rp1->log_server.addr,
  1490.                    rp2->log_server.num * sizeof (struct in_addr));
  1491.             }
  1492.         }
  1493.     if (ISCLR (rp1->valid, S_COOKIE_SERVER)) 
  1494.         {
  1495.         rp1->cookie_server.addr = calloc (rp2->cookie_server.num, 
  1496.                                           sizeof (struct in_addr));
  1497.         if (rp1->cookie_server.addr != NULL)
  1498.             {
  1499.             rp1->cookie_server.num = rp2->cookie_server.num;
  1500.             bcopy ((char *)rp2->cookie_server.addr, 
  1501.                    (char *)rp1->cookie_server.addr,
  1502.                    rp2->cookie_server.num * sizeof (struct in_addr));
  1503.             }
  1504.         }
  1505.     if (ISCLR (rp1->valid, S_LPR_SERVER)) 
  1506.         {
  1507.         rp1->lpr_server.addr = calloc (rp2->lpr_server.num, 
  1508.                                        sizeof (struct in_addr));
  1509.         if (rp1->lpr_server.addr != NULL)
  1510.             {
  1511.             rp1->lpr_server.num = rp2->lpr_server.num;
  1512.             bcopy ((char *)rp2->lpr_server.addr, (char *)rp1->lpr_server.addr,
  1513.                    rp2->lpr_server.num * sizeof (struct in_addr));
  1514.             }
  1515.         }
  1516.     if (ISCLR (rp1->valid, S_IMPRESS_SERVER))
  1517.         {
  1518.         rp1->impress_server.addr = calloc (rp2->impress_server.num, 
  1519.                                            sizeof (struct in_addr));
  1520.         if (rp1->impress_server.addr != NULL)
  1521.             {
  1522.             rp1->impress_server.num = rp2->impress_server.num;
  1523.             bcopy ((char *)rp2->impress_server.addr, 
  1524.                    (char *)rp1->impress_server.addr,
  1525.                    rp2->impress_server.num * sizeof (struct in_addr));
  1526.             }
  1527.         }
  1528.     if (ISCLR (rp1->valid, S_RLS_SERVER)) 
  1529.         {
  1530.         rp1->rls_server.addr = calloc (rp2->rls_server.num, 
  1531.                                        sizeof (struct in_addr));
  1532.         if (rp1->rls_server.addr != NULL)
  1533.             {
  1534.             rp1->rls_server.num = rp2->rls_server.num;
  1535.             bcopy ((char *)rp2->rls_server.addr, (char *)rp1->rls_server.addr,
  1536.                    rp2->rls_server.num * sizeof (struct in_addr));
  1537.             }
  1538.         }
  1539.     if (ISCLR (rp1->valid, S_HOSTNAME)) 
  1540.         strcpy (rp1->hostname, rp2->hostname);
  1541.     if (ISCLR (rp1->valid, S_BOOTSIZE)) 
  1542.         rp1->bootsize = rp2->bootsize;
  1543.     if (ISCLR (rp1->valid, S_MERIT_DUMP))
  1544.         strcpy (rp1->merit_dump, rp2->merit_dump);
  1545.     if (ISCLR (rp1->valid, S_DNS_DOMAIN)) 
  1546.         strcpy (rp1->dns_domain, rp2->dns_domain);
  1547.     if (ISCLR (rp1->valid, S_SWAP_SERVER)) 
  1548.         rp1->swap_server = rp2->swap_server;
  1549.     if (ISCLR (rp1->valid, S_ROOT_PATH)) 
  1550.         strcpy (rp1->root_path, rp2->root_path);
  1551.     if (ISCLR (rp1->valid, S_EXTENSIONS_PATH))
  1552.         strcpy (rp1->extensions_path, rp2->extensions_path);
  1553.     if (ISCLR (rp1->valid, S_IP_FORWARD)) 
  1554.         rp1->ip_forward = rp2->ip_forward;
  1555.     if (ISCLR (rp1->valid, S_NONLOCAL_SRCROUTE))
  1556.         rp1->nonlocal_srcroute = rp2->nonlocal_srcroute;
  1557.     if (ISCLR (rp1->valid, S_POLICY_FILTER)) 
  1558.         {
  1559.         rp1->policy_filter.addr1 = calloc (rp2->policy_filter.num, 
  1560.                                            sizeof (struct in_addr));
  1561.         if (rp1->policy_filter.addr1 != NULL)
  1562.             {
  1563.             rp1->policy_filter.addr2 = calloc (rp2->policy_filter.num, 
  1564.                                                sizeof (struct in_addr));
  1565.             if (rp1->policy_filter.addr2 != NULL)
  1566.                 {
  1567.                 rp1->policy_filter.num = rp2->policy_filter.num;
  1568.                 bcopy ((char *)rp2->policy_filter.addr1, 
  1569.                        (char *)rp1->policy_filter.addr1,
  1570.                        rp2->policy_filter.num * sizeof (struct in_addr));
  1571.                 bcopy ((char *)rp2->policy_filter.addr1, 
  1572.                        (char *)rp1->policy_filter.addr1,
  1573.                        rp2->policy_filter.num * sizeof (struct in_addr));
  1574.                 }
  1575.             else 
  1576.                 free (rp1->policy_filter.addr1);
  1577.             }
  1578.         }
  1579.     if (ISCLR (rp1->valid, S_MAX_DGRAM_SIZE)) 
  1580.         rp1->max_dgram_size = rp2->max_dgram_size;
  1581.     if (ISCLR (rp1->valid, S_DEFAULT_IP_TTL))
  1582.         rp1->default_ip_ttl = rp2->default_ip_ttl;
  1583.     if (ISCLR (rp1->valid, S_MTU_AGING_TIMEOUT))
  1584.          rp1->mtu_aging_timeout = rp2->mtu_aging_timeout;
  1585.     if (ISCLR (rp1->valid, S_MTU_PLATEAU_TABLE))
  1586.         {
  1587.         rp1->mtu_plateau_table.shorts = calloc (rp2->mtu_plateau_table.num,
  1588.                                                 sizeof (u_short));
  1589.         if (rp1->mtu_plateau_table.shorts != NULL)
  1590.             {
  1591.             rp1->mtu_plateau_table.num = rp2->mtu_plateau_table.num;
  1592.             bcopy ((char *)rp2->mtu_plateau_table.shorts, 
  1593.                    (char *)rp1->mtu_plateau_table.shorts,
  1594.                    rp2->mtu_plateau_table.num * sizeof (u_short));
  1595.             }
  1596.         }
  1597.     if (ISCLR (rp1->valid, S_IF_MTU)) 
  1598.         rp1->intf_mtu = rp2->intf_mtu;
  1599.     if (ISCLR (rp1->valid, S_ALL_SUBNET_LOCAL))
  1600.         rp1->all_subnet_local = rp2->all_subnet_local;
  1601.     if (ISCLR (rp1->valid, S_BRDCAST_ADDR)) 
  1602.         rp1->brdcast_addr = rp2->brdcast_addr;
  1603.     if (ISCLR (rp1->valid, S_MASK_DISCOVER)) 
  1604.         rp1->mask_discover = rp2->mask_discover;
  1605.     if (ISCLR (rp1->valid, S_MASK_SUPPLIER)) 
  1606.         rp1->mask_supplier = rp2->mask_supplier;
  1607.     if (ISCLR (rp1->valid, S_ROUTER_DISCOVER))
  1608.         rp1->router_discover = rp2->router_discover;
  1609.     if (ISCLR (rp1->valid, S_ROUTER_SOLICIT))
  1610.         rp1->router_solicit = rp2->router_solicit;
  1611.     if (ISCLR (rp1->valid, S_STATIC_ROUTE)) 
  1612.         {
  1613.         rp1->static_route.addr1 = calloc (rp2->static_route.num, 
  1614.                                           sizeof (struct in_addr));
  1615.         if (rp1->static_route.addr1 != NULL)
  1616.             {
  1617.             rp1->static_route.addr2 = calloc (rp2->static_route.num, 
  1618.                                               sizeof (struct in_addr));
  1619.             if (rp1->static_route.addr2 != NULL)
  1620.                 {
  1621.                 rp1->static_route.num = rp2->static_route.num;
  1622.                 bcopy ( (char *)rp2->static_route.addr1, 
  1623.                         (char *)rp1->static_route.addr1,
  1624.                        rp2->static_route.num * sizeof (struct in_addr));
  1625.                 bcopy ( (char *)rp2->static_route.addr1, 
  1626.                         (char *)rp1->static_route.addr1,
  1627.                        rp2->static_route.num * sizeof (struct in_addr));
  1628.                 }
  1629.             else 
  1630.                 free (rp1->static_route.addr1);
  1631.             }
  1632.         }
  1633.     if (ISCLR (rp1->valid, S_TRAILER)) 
  1634.         rp1->trailer = rp2->trailer;
  1635.     if (ISCLR (rp1->valid, S_ARP_CACHE_TIMEOUT))
  1636.         rp1->arp_cache_timeout = rp2->arp_cache_timeout;
  1637.     if (ISCLR (rp1->valid, S_ETHER_ENCAP)) 
  1638.         rp1->ether_encap = rp2->ether_encap;
  1639.     if (ISCLR (rp1->valid, S_DEFAULT_TCP_TTL))
  1640.         rp1->default_tcp_ttl = rp2->default_tcp_ttl;
  1641.     if (ISCLR (rp1->valid, S_KEEPALIVE_INTER))
  1642.         rp1->keepalive_inter = rp2->keepalive_inter;
  1643.     if (ISCLR (rp1->valid, S_KEEPALIVE_GARBA))
  1644.         rp1->keepalive_garba = rp2->keepalive_garba;
  1645.     if (ISCLR (rp1->valid, S_NIS_DOMAIN))
  1646.         strcpy (rp1->nis_domain, rp2->nis_domain);
  1647.     if (ISCLR (rp1->valid, S_NIS_SERVER)) 
  1648.         {
  1649.         rp1->nis_server.addr = calloc (rp2->nis_server.num, 
  1650.                                        sizeof (struct in_addr));
  1651.         if (rp1->nis_server.addr != NULL)
  1652.             {
  1653.             rp1->nis_server.num = rp2->nis_server.num;
  1654.             bcopy ((char *)rp2->nis_server.addr, (char *)rp1->nis_server.addr,
  1655.                    rp2->nis_server.num * sizeof (struct in_addr));
  1656.             }
  1657.         }
  1658.     if (ISCLR (rp1->valid, S_NTP_SERVER)) 
  1659.         {
  1660.         rp1->ntp_server.addr = calloc (rp2->ntp_server.num, 
  1661.                                        sizeof (struct in_addr));
  1662.         if (rp1->ntp_server.addr != NULL)
  1663.             {
  1664.             rp1->ntp_server.num = rp2->ntp_server.num;
  1665.             bcopy ((char *)rp2->ntp_server.addr, (char *)rp1->ntp_server.addr,
  1666.                    rp2->ntp_server.num * sizeof (struct in_addr));
  1667.             }
  1668.         }
  1669.     if (ISCLR (rp1->valid, S_NBN_SERVER)) 
  1670.         {
  1671.         rp1->nbn_server.addr = calloc (rp2->nbn_server.num, 
  1672.                                        sizeof (struct in_addr));
  1673.         if (rp1->nbn_server.addr != NULL)
  1674.             {
  1675.             rp1->nbn_server.num = rp2->nbn_server.num;
  1676.             bcopy ((char *)rp2->nbn_server.addr, (char *)rp1->nbn_server.addr,
  1677.                    rp2->nbn_server.num * sizeof (struct in_addr));
  1678.             }
  1679.         }
  1680.     if (ISCLR (rp1->valid, S_NBDD_SERVER)) 
  1681.         {
  1682.         rp1->nbdd_server.addr = calloc (rp2->nbdd_server.num, 
  1683.                                         sizeof (struct in_addr));
  1684.         if (rp1->nbdd_server.addr != NULL)
  1685.             {
  1686.             rp1->nbdd_server.num = rp2->nbdd_server.num;
  1687.             bcopy ((char *)rp2->nbdd_server.addr, (char *)rp1->nbdd_server.addr,
  1688.                    rp2->nbdd_server.num * sizeof (struct in_addr));
  1689.             }
  1690.         }
  1691.     if (ISCLR (rp1->valid, S_NB_NODETYPE)) 
  1692.         rp1->nb_nodetype = rp2->nb_nodetype;
  1693.     if (ISCLR (rp1->valid, S_NB_SCOPE)) 
  1694.         strcpy (rp1->nb_scope, rp2->nb_scope);
  1695.     if (ISCLR (rp1->valid, S_XFONT_SERVER)) 
  1696.         {
  1697.         rp1->xfont_server.addr = calloc (rp2->xfont_server.num, 
  1698.                                          sizeof (struct in_addr));
  1699.         if (rp1->xfont_server.addr != NULL)
  1700.             {
  1701.             rp1->xfont_server.num = rp2->xfont_server.num;
  1702.             bcopy ((char *)rp2->xfont_server.addr, 
  1703.                    (char *)rp1->xfont_server.addr,
  1704.                    rp2->xfont_server.num * sizeof (struct in_addr));
  1705.             }
  1706.         }
  1707.     if (ISCLR (rp1->valid, S_XDISPLAY_MANAGER))
  1708.         {
  1709.         rp1->xdisplay_manager.addr = calloc (rp2->xdisplay_manager.num, 
  1710.                                              sizeof (struct in_addr));
  1711.         if (rp1->xdisplay_manager.addr != NULL)
  1712.             {
  1713.             rp1->xdisplay_manager.num = rp2->xdisplay_manager.num;
  1714.             bcopy ((char *)rp2->xdisplay_manager.addr, 
  1715.                    (char *)rp1->xdisplay_manager.addr,
  1716.                    rp2->xdisplay_manager.num * sizeof (struct in_addr));
  1717.             }
  1718.         }
  1719.     if (ISCLR (rp1->valid, S_DHCP_T1)) 
  1720.         rp1->dhcp_t1 = rp2->dhcp_t1;
  1721.     if (ISCLR (rp1->valid, S_DHCP_T2)) 
  1722.         rp1->dhcp_t2 = rp2->dhcp_t2;
  1723.     if (ISCLR (rp1->valid, S_NISP_DOMAIN)) 
  1724.         strcpy (rp1->nisp_domain, rp2->nisp_domain);
  1725.     if (ISCLR (rp1->valid, S_NISP_SERVER)) 
  1726.         {
  1727.         rp1->nisp_server.addr = calloc (rp2->nisp_server.num, 
  1728.                                         sizeof (struct in_addr));
  1729.         if (rp1->nisp_server.addr != NULL)
  1730.             {
  1731.             rp1->nisp_server.num = rp2->nisp_server.num;
  1732.             bcopy ((char *)rp2->nisp_server.addr, (char *)rp1->nisp_server.addr,
  1733.                    rp2->nisp_server.num * sizeof (struct in_addr));
  1734.             }
  1735.         }
  1736.     if (ISCLR (rp1->valid, S_MOBILEIP_HA)) 
  1737.         {
  1738.         rp1->mobileip_ha.addr = calloc (rp2->mobileip_ha.num, 
  1739.                                         sizeof (struct in_addr));
  1740.         if (rp1->mobileip_ha.addr != NULL)
  1741.             {
  1742.             rp1->mobileip_ha.num = rp2->mobileip_ha.num;
  1743.             bcopy ((char *)rp2->mobileip_ha.addr, (char *)rp1->mobileip_ha.addr,
  1744.                    rp2->mobileip_ha.num * sizeof (struct in_addr));
  1745.             }
  1746.         }
  1747.     if (ISCLR (rp1->valid, S_SMTP_SERVER)) 
  1748.         {
  1749.         rp1->smtp_server.addr = calloc (rp2->smtp_server.num, 
  1750.                                         sizeof (struct in_addr));
  1751.         if (rp1->smtp_server.addr != NULL)
  1752.             {
  1753.             rp1->smtp_server.num = rp2->smtp_server.num;
  1754.             bcopy ((char *)rp2->smtp_server.addr, (char *)rp1->smtp_server.addr,
  1755.                    rp2->smtp_server.num * sizeof (struct in_addr));
  1756.             }
  1757.         }
  1758.     if (ISCLR (rp1->valid, S_POP3_SERVER)) 
  1759.         {
  1760.         rp1->pop3_server.addr = calloc (rp2->pop3_server.num, 
  1761.                                         sizeof (struct in_addr));
  1762.         if (rp1->pop3_server.addr != NULL)
  1763.             {
  1764.             rp1->pop3_server.num = rp2->pop3_server.num;
  1765.             bcopy ((char *)rp2->pop3_server.addr, (char *)rp1->pop3_server.addr,
  1766.                    rp2->pop3_server.num * sizeof (struct in_addr));
  1767.             }
  1768.         }
  1769.     if (ISCLR (rp1->valid, S_NNTP_SERVER)) 
  1770.         {
  1771.         rp1->nntp_server.addr = calloc (rp2->nntp_server.num, 
  1772.                                         sizeof (struct in_addr));
  1773.         if (rp1->nntp_server.addr != NULL)
  1774.             {
  1775.             rp1->nntp_server.num = rp2->nntp_server.num;
  1776.             bcopy ((char *)rp2->nntp_server.addr, (char *)rp1->nntp_server.addr,
  1777.                    rp2->nntp_server.num * sizeof (struct in_addr));
  1778.             }
  1779.         }
  1780.     if (ISCLR (rp1->valid, S_DFLT_WWW_SERVER))
  1781.         {
  1782.         rp1->dflt_www_server.addr = calloc (rp2->dflt_www_server.num, 
  1783.                                             sizeof (struct in_addr));
  1784.         if (rp1->dflt_www_server.addr != NULL)
  1785.             {
  1786.             rp1->dflt_www_server.num = rp2->dflt_www_server.num;
  1787.             bcopy ((char *)rp2->dflt_www_server.addr, 
  1788.                    (char *)rp1->dflt_www_server.addr,
  1789.                    rp2->dflt_www_server.num * sizeof (struct in_addr));
  1790.             }
  1791.         }
  1792.     if (ISCLR (rp1->valid, S_DFLT_FINGER_SERVER))
  1793.         {
  1794.         rp1->dflt_finger_server.addr = calloc (rp2->dflt_finger_server.num, 
  1795.                                                sizeof (struct in_addr));
  1796.         if (rp1->dflt_finger_server.addr != NULL)
  1797.             {
  1798.             rp1->dflt_finger_server.num = rp2->dflt_finger_server.num;
  1799.             bcopy ((char *)rp2->dflt_finger_server.addr, 
  1800.                    (char *)rp1->dflt_finger_server.addr,
  1801.                    rp2->dflt_finger_server.num * sizeof (struct in_addr));
  1802.             }
  1803.         }
  1804.     if (ISCLR (rp1->valid, S_DFLT_IRC_SERVER))
  1805.         {
  1806.         rp1->dflt_irc_server.addr = calloc (rp2->dflt_irc_server.num, 
  1807.                                             sizeof (struct in_addr));
  1808.         if (rp1->dflt_irc_server.addr != NULL)
  1809.             {
  1810.             rp1->dflt_irc_server.num = rp2->dflt_irc_server.num;
  1811.             bcopy ((char *)rp2->dflt_irc_server.addr, 
  1812.                    (char *)rp1->dflt_irc_server.addr,
  1813.                    rp2->dflt_irc_server.num * sizeof (struct in_addr));
  1814.             }
  1815.         }
  1816.     if (ISCLR (rp1->valid, S_STREETTALK_SERVER))
  1817.         {
  1818.         rp1->streettalk_server.addr = calloc (rp2->streettalk_server.num, 
  1819.                                               sizeof (struct in_addr));
  1820.         if (rp1->streettalk_server.addr != NULL)
  1821.             {
  1822.             rp1->streettalk_server.num = rp2->streettalk_server.num;
  1823.             bcopy ((char *)rp2->streettalk_server.addr, 
  1824.                    (char *)rp1->streettalk_server.addr,
  1825.                    rp2->streettalk_server.num * sizeof (struct in_addr));
  1826.             }
  1827.         }
  1828.     if (ISCLR (rp1->valid, S_STDA_SERVER)) 
  1829.         {
  1830.         rp1->stda_server.addr = calloc (rp2->stda_server.num, 
  1831.                                         sizeof (struct in_addr));
  1832.         if (rp1->stda_server.addr != NULL)
  1833.             {
  1834.             rp1->stda_server.num = rp2->stda_server.num;
  1835.             bcopy ((char *)rp2->stda_server.addr, (char *)rp1->stda_server.addr,
  1836.                    rp2->stda_server.num * sizeof (struct in_addr));
  1837.             }
  1838.         }
  1839.     for (i = 0; i < VALIDSIZE; i++) 
  1840.         {
  1841.         /* 
  1842.          * Set active and valid flags for all values provided by quoted
  1843.          * entry. The valid flag for an entry is always set if the 
  1844.          * corresponding active flag is set.
  1845.          */
  1846.         rp1->active[i] |= (~rp1->valid[i] & rp2->active[i]);
  1847.         rp1->valid[i] |= rp2->valid[i];
  1848.         }
  1849.     return(0);
  1850.     }
  1851. /*******************************************************************************
  1852. *
  1853. * proc_mtpt - extract the MTU plateau table values
  1854. *
  1855. * This routine sets the mtu_plateau_table field of a lease descriptor to the 
  1856. * values specified by a "mtpt" entry in the address pool database. The
  1857. * structure field is cleared when "mtpt@", specifying deletion, is encountered.
  1858. *
  1859. * RETURNS: 0, always.
  1860. *
  1861. * ERRNO: N/A
  1862. *
  1863. * NOMANUAL
  1864. */
  1865. int proc_mtpt
  1866.     (
  1867.     int code,  /* resource code for address pool field */
  1868.     int optype,  /* operation type (addition or deletion) */
  1869.     char **symbol,  /* current location in input string */
  1870.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  1871.     )
  1872.     {
  1873.     int i = 0;
  1874.     unsigned short tmpnum [MAX_MTUPLTSZ];
  1875.     if (optype == OP_ADDITION) 
  1876.         {
  1877.         for (i = 0; i <= MAX_MTUPLTSZ; i++) 
  1878.             {
  1879.             while (**symbol && isspace ( (int) **symbol)) 
  1880.                 {
  1881.         (*symbol)++;
  1882.                 }
  1883.             if (! **symbol) 
  1884.                 {                        /* Quit if nothing more */
  1885.         break;
  1886.                 }
  1887.             if (isdigit ( (int) **symbol))
  1888.                 tmpnum[i] = (u_short)get_integer (symbol);
  1889.             else 
  1890.                 break;
  1891.             }
  1892.         if (i == 0) 
  1893.             {
  1894. #ifdef DHCPS_DEBUG
  1895.             logMsg ("Warning: invalid MTU plateau table value.n", 
  1896.                      0, 0, 0, 0, 0, 0);
  1897. #endif
  1898.             return (-1);
  1899.             }
  1900.         rp->mtu_plateau_table.num = i;
  1901.         if (rp->mtu_plateau_table.shorts != NULL)
  1902.             free (rp->mtu_plateau_table.shorts);
  1903.         rp->mtu_plateau_table.shorts = (u_short *)calloc (i, sizeof (u_short));
  1904.         if (rp->mtu_plateau_table.shorts == NULL) 
  1905.             {
  1906. #ifdef DHCPS_DEBUG
  1907.             logMsg ("Warning: memory allocation error reading MTU plateau.n",
  1908.                      0, 0, 0, 0, 0, 0);
  1909. #endif
  1910.             return (-1);
  1911.             }
  1912.         for (i = 0; i < rp->mtu_plateau_table.num; i++) 
  1913.             rp->mtu_plateau_table.shorts[i] = htons (tmpnum[i]);
  1914.         } 
  1915.     else 
  1916.         {
  1917.         rp->mtu_plateau_table.num = 0;
  1918.         if (rp->mtu_plateau_table.shorts != NULL)
  1919.             free (rp->mtu_plateau_table.shorts);
  1920.         rp->mtu_plateau_table.shorts = NULL;
  1921.         }
  1922.     return (0);
  1923.     }
  1924. /*******************************************************************************
  1925. *
  1926. * proc_ip - process single IP addresses
  1927. *
  1928. * This routine sets the fields of the lease descriptor containing single IP 
  1929. * address values. It is called in response to any "siad", "ipad", "snmk", 
  1930. * "swsv", "brda", or "rtsl" entries in the address pool database. When an "@" 
  1931. * mark is appended to any of the above specifiers, the corresponding field is 
  1932. * cleared.
  1933. *
  1934. * RETURNS: 0 if processing completed, or -1 on parse error.
  1935. *
  1936. * ERRNO: N/A
  1937. *
  1938. * NOMANUAL
  1939. */
  1940. int proc_ip
  1941.     (
  1942.     int code,  /* resource code for address pool field */
  1943.     int optype,  /* operation type (addition or deletion) */
  1944.     char **symbol,  /* current location in input string */
  1945.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  1946.     )
  1947.     {
  1948.     struct in_addr *ipp = NULL;
  1949.     STATUS result;
  1950.     switch (code) 
  1951.         {
  1952.         case S_SIADDR:
  1953.             ipp = &rp->siaddr;
  1954.             break;
  1955.         case S_IP_ADDR:
  1956.             ipp = &rp->ip_addr;
  1957.             break;
  1958.         case S_SUBNET_MASK:
  1959.             ipp = &rp->subnet_mask;
  1960.             break;
  1961.         case S_SWAP_SERVER:
  1962.             ipp = &rp->swap_server;
  1963.             break;
  1964.         case S_BRDCAST_ADDR:
  1965.             ipp = &rp->brdcast_addr;
  1966.             break;
  1967.         case S_ROUTER_SOLICIT:
  1968.             ipp = &rp->router_solicit;
  1969.             break;
  1970.         }
  1971.     if (optype == OP_ADDITION) 
  1972.         {
  1973.         result = get_ip (symbol, ipp);
  1974.         if (result != OK)
  1975.             {
  1976. #ifdef DHCPS_DEBUG
  1977.             logMsg ("Warning: Invalid or missing IP address.n",
  1978.                      0, 0, 0, 0, 0, 0);
  1979. #endif
  1980.             return (-1);
  1981.             }
  1982.         } 
  1983.     else 
  1984.         bzero ( (char *)ipp, sizeof (struct in_addr));
  1985.   
  1986.     return (0);
  1987.     }
  1988. /*******************************************************************************
  1989. *
  1990. * proc_ips - process multiple IP addresses
  1991. *
  1992. * This routine sets the fields of the lease descriptor containing lists of 
  1993. * IP addresses. These entries are indicated by names such as "rout" or "tmsv" 
  1994. * in the address pool database. When an "@" mark is appended to any of the 
  1995. * corresponding specifiers, the matching field is cleared.
  1996. *
  1997. * RETURNS: 0 if processing completed, or -1 on error.
  1998. *
  1999. * ERRNO: N/A
  2000. *
  2001. * NOMANUAL
  2002. */
  2003. int proc_ips
  2004.     (
  2005.     int code,  /* resource code for address pool field */
  2006.     int optype,  /* operation type (addition or deletion) */
  2007.     char **symbol,  /* current location in input string */
  2008.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2009.     )
  2010.     {
  2011.     struct in_addrs *ipp = NULL;
  2012.     int i = 0;
  2013.     struct in_addr tmpaddr[MAX_IPS];
  2014.     STATUS result;
  2015.     switch (code) 
  2016.         {
  2017.         case S_ROUTER:
  2018.             ipp = &rp->router;
  2019.             break;
  2020.         case S_TIME_SERVER:
  2021.             ipp = &rp->time_server;
  2022.             break;
  2023.         case S_NAME_SERVER:
  2024.             ipp = &rp->name_server;
  2025.             break;
  2026.         case S_DNS_SERVER:
  2027.             ipp = &rp->dns_server;
  2028.             break;
  2029.         case S_LOG_SERVER:
  2030.             ipp = &rp->log_server;
  2031.             break;
  2032.         case S_COOKIE_SERVER:
  2033.             ipp = &rp->cookie_server;
  2034.             break;
  2035.         case S_LPR_SERVER:
  2036.             ipp = &rp->lpr_server;
  2037.             break;
  2038.         case S_IMPRESS_SERVER:
  2039.             ipp = &rp->impress_server;
  2040.             break;
  2041.         case S_RLS_SERVER:
  2042.             ipp = &rp->rls_server;
  2043.             break;
  2044.         case S_NIS_SERVER:
  2045.             ipp = &rp->nis_server;
  2046.             break;
  2047.         case S_NTP_SERVER:
  2048.             ipp = &rp->ntp_server;
  2049.             break;
  2050.         case S_NBN_SERVER:
  2051.             ipp = &rp->nbn_server;
  2052.             break;
  2053.         case S_NBDD_SERVER:
  2054.             ipp = &rp->nbdd_server;
  2055.             break;
  2056.         case S_XFONT_SERVER:
  2057.             ipp = &rp->xfont_server;
  2058.             break;
  2059.         case S_XDISPLAY_MANAGER:
  2060.             ipp = &rp->xdisplay_manager;
  2061.             break;
  2062.         case S_NISP_SERVER:
  2063.             ipp = &rp->nisp_server;
  2064.             break;
  2065.         case S_MOBILEIP_HA:
  2066.             ipp = &rp->mobileip_ha;
  2067.             break;
  2068.         case S_SMTP_SERVER:
  2069.             ipp = &rp->smtp_server;
  2070.             break;
  2071.         case S_POP3_SERVER:
  2072.             ipp = &rp->pop3_server;
  2073.             break;
  2074.         case S_NNTP_SERVER:
  2075.             ipp = &rp->nntp_server;
  2076.             break;
  2077.         case S_DFLT_WWW_SERVER:
  2078.             ipp = &rp->dflt_www_server;
  2079.             break;
  2080.         case S_DFLT_FINGER_SERVER:
  2081.             ipp = &rp->dflt_finger_server;
  2082.             break;
  2083.         case S_DFLT_IRC_SERVER:
  2084.             ipp = &rp->dflt_irc_server;
  2085.             break;
  2086.         case S_STREETTALK_SERVER:
  2087.             ipp = &rp->streettalk_server;
  2088.             break;
  2089.         case S_STDA_SERVER:
  2090.             ipp = &rp->stda_server;
  2091.             break;
  2092.         }
  2093.     if (optype == OP_ADDITION) 
  2094.         {
  2095.         for (i = 0; i <= MAX_IPS; i++) 
  2096.              {
  2097.              while (**symbol && isspace( (int) **symbol)) 
  2098.                  {
  2099.          (*symbol)++;
  2100.                  }
  2101.              if (! **symbol)
  2102.          break;
  2103.              result = get_ip (symbol, &tmpaddr[i]);
  2104.              if (result != OK)
  2105.                  break;
  2106.              }
  2107.         if (i == 0) 
  2108.             {
  2109. #ifdef DHCPS_DEBUG
  2110.             logMsg ("Warning: Invalid or missing IP address.n", 
  2111.                      0, 0, 0, 0, 0, 0);
  2112. #endif
  2113.             return (-1);
  2114.             }
  2115.         ipp->num = i;
  2116.         ipp->addr = (struct in_addr *)calloc (i, sizeof (struct in_addr));
  2117.         if (ipp->addr == NULL) 
  2118.             {
  2119. #ifdef DHCPS_DEBUG
  2120.             logMsg ("Warning: Memory allocation error reading IP addresses.n",
  2121.                      0, 0, 0, 0, 0, 0);
  2122. #endif
  2123.             return (-1);
  2124.             }
  2125.         for (i = 0; i < ipp->num; i++) 
  2126.             ipp->addr[i] = tmpaddr[i];
  2127.         } 
  2128.     else
  2129.         {
  2130.         ipp->num = 0;
  2131.         if (ipp->addr != NULL)
  2132.             free (ipp->addr);
  2133.         ipp->addr = NULL;
  2134.         }
  2135.     return (0);
  2136.     }
  2137. /*******************************************************************************
  2138. *
  2139. * proc_ippairs - process multiple IP address pairs
  2140. *
  2141. * This routine sets the fields of the lease descriptor containing one or more 
  2142. * IP pairs. It is called in response to any "plcy" or "strt", entries in the 
  2143. * address pool database.  When an "@" mark is appended to either of the above
  2144. * specifiers, the corresponding field is cleared.
  2145. *
  2146. * RETURNS: 0 if processing completed, or -1 on error.
  2147. *
  2148. * ERRNO: N/A
  2149. *
  2150. * NOMANUAL
  2151. */
  2152. int proc_ippairs
  2153.     (
  2154.     int code,  /* resource code for address pool field */
  2155.     int optype,  /* operation type (addition or deletion) */
  2156.     char **symbol,  /* current location in input string */
  2157.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2158.     )
  2159.     {
  2160.     struct ip_pairs *ipp = NULL;
  2161.     int i = 0;
  2162.     struct in_addr tmpaddr1 [MAX_IPPAIR], tmpaddr2 [MAX_IPPAIR];
  2163.     STATUS result;
  2164.  
  2165.     switch (code) 
  2166.         {
  2167.         case S_POLICY_FILTER:
  2168.             ipp = &rp->policy_filter;
  2169.             break;
  2170.         case S_STATIC_ROUTE:
  2171.             ipp = &rp->static_route;
  2172.             break;
  2173.         }
  2174.     if (optype == OP_ADDITION)
  2175.         {
  2176.         for (i = 0; i <= MAX_IPPAIR; i++) 
  2177.             {
  2178.             /* Skip whitespace before first IP address. */
  2179.             while (**symbol && isspace ( (int)**symbol)) 
  2180.                    (*symbol)++;
  2181.             if (! **symbol)
  2182.                 break;
  2183.             result = get_ip(symbol, &tmpaddr1[i]);
  2184.             if (result != OK)
  2185.         break;
  2186.             /* Skip whitespace before second IP address. */
  2187.             while (**symbol && isspace ( (int) **symbol))
  2188.        (*symbol)++;
  2189.             if (! **symbol)
  2190.                 {
  2191. #ifdef DHCPS_DEBUG
  2192.         logMsg ("Warning: Second IP address in pair is missing.n",
  2193.                          0, 0, 0, 0, 0, 0);
  2194. #endif
  2195.         break;
  2196.                 }
  2197.             result = get_ip(symbol, &tmpaddr2[i]);
  2198.             if (result != OK) 
  2199.                 {
  2200. #ifdef DHCPS_DEBUG
  2201.         logMsg ("Warning: Second IP address invalid or missing.n",
  2202.                          0, 0, 0, 0, 0, 0);
  2203. #endif
  2204.         break;
  2205.                 }
  2206.             }
  2207.         if (i == 0) 
  2208.             {
  2209. #ifdef DHCPS_DEBUG
  2210.             logMsg ("Warning: No valid IP addresses found.n", 
  2211.                      0, 0, 0, 0, 0, 0);
  2212. #endif
  2213.             return (-1);
  2214.             }
  2215.         ipp->num = i;
  2216.         ipp->addr1 = (struct in_addr *)calloc (i, sizeof (struct in_addr));
  2217.         if (ipp->addr1 == NULL) 
  2218.             {
  2219. #ifdef DHCPS_DEBUG
  2220.             logMsg ("Warning: Memory allocation error reading IP addresses.n",
  2221.                      0, 0, 0, 0, 0, 0);
  2222. #endif
  2223.             return (-1);
  2224.             }
  2225.         ipp->addr2 = (struct in_addr *)calloc (i, sizeof (struct in_addr));
  2226.         if (ipp->addr2 == NULL) 
  2227.             {
  2228. #ifdef DHCPS_DEBUG
  2229.             logMsg ("Warning: Memory allocation error reading IP addresses.n",
  2230.                      0, 0, 0, 0, 0, 0);
  2231. #endif
  2232.             free (ipp->addr1);
  2233.             return (-1);
  2234.             }
  2235.         for (i = 0; i < ipp->num; i++) 
  2236.             {
  2237.             ipp->addr1[i] = tmpaddr1[i];
  2238.             ipp->addr2[i] = tmpaddr2[i];
  2239.             }
  2240.         } 
  2241.     else 
  2242.         {
  2243.         ipp->num = 0;
  2244.         if (ipp->addr1 != NULL)
  2245.             free (ipp->addr1);
  2246.         if (ipp->addr2 != NULL)
  2247.             free (ipp->addr2);
  2248.         }
  2249.     return (0);
  2250.     }
  2251. /*******************************************************************************
  2252. *
  2253. * proc_hl - store long (4 byte) numeric values in host byte order
  2254. *
  2255. * This routine sets the fields of the lease descriptor containing four byte 
  2256. * numeric entries which have no corresponding fields in the DHCP message 
  2257. * structure. These entries are indicated by "maxl" or "dfll" in the address 
  2258. * pool database, and are stored in host byte order. When an "@" mark is 
  2259. * appended to either of the corresponding specifiers, the matching field is 
  2260. * cleared.
  2261. *
  2262. * RETURNS: 0, always.
  2263. *
  2264. * ERRNO: N/A
  2265. *
  2266. * NOMANUAL
  2267. */
  2268. int proc_hl
  2269.     (
  2270.     int code,  /* resource code for address pool field */
  2271.     int optype,  /* operation type (addition or deletion) */
  2272.     char **symbol,  /* current location in input string */
  2273.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2274.     )
  2275.     {
  2276.     u_long *lp = NULL;
  2277.     switch (code) 
  2278.         {
  2279.         case S_MAX_LEASE:
  2280.             lp = &rp->max_lease;
  2281.             break;
  2282.         case S_DEFAULT_LEASE:
  2283.             lp = &rp->default_lease;
  2284.             break;
  2285.         }
  2286.     if (optype == OP_ADDITION) 
  2287.         *lp = get_integer(symbol);
  2288.     else
  2289.         *lp = 0;
  2290.     return (0);
  2291.     }
  2292. /*******************************************************************************
  2293. *
  2294. * proc_hs - store short (2 byte) numeric values in host byte order
  2295. *
  2296. * This routine sets the fields of the lease descriptor containing two byte 
  2297. * numeric entries which have no corresponding fields in the DHCP message 
  2298. * structure. These  entries are indicated by "dht1" or "dht2" in the address 
  2299. * pool database, and are stored in host byte order. When an "@" mark is 
  2300. * appended to either of the corresponding specifiers, the matching field 
  2301. * is cleared.
  2302. *
  2303. * RETURNS: 0, always.
  2304. *
  2305. * ERRNO: N/A
  2306. *
  2307. * NOMANUAL
  2308. */
  2309. int proc_hs
  2310.     (
  2311.     int code,  /* resource code for address pool field */
  2312.     int optype,  /* operation type (addition or deletion) */
  2313.     char **symbol,  /* current location in input string */
  2314.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2315.     )
  2316.     {
  2317.     u_short *sp = NULL;
  2318.     switch (code) 
  2319.         {
  2320.         case S_DHCP_T1:
  2321.             sp = &rp->dhcp_t1;
  2322.             break;
  2323.         case S_DHCP_T2:
  2324.             sp = &rp->dhcp_t2;
  2325.             break;
  2326.         }
  2327.     if (optype == OP_ADDITION) 
  2328.         *sp = (short)get_integer (symbol);
  2329.     else 
  2330.         *sp = 0;
  2331.     return (0); 
  2332.     }
  2333. /*******************************************************************************
  2334. *
  2335. * proc_nl - store long (4 byte) numeric values in network byte order
  2336. *
  2337. * This routine sets the fields of the lease descriptor containing four byte 
  2338. * numeric entries which are sent directly to the client. These entries are 
  2339. * indicated by "maxl" or "dfll" in the address pool database, and are stored 
  2340. * in network byte order. When an "@" mark is appended to either of the 
  2341. * corresponding specifiers, the matching field is cleared.
  2342. *
  2343. * RETURNS: 0, always.
  2344. *
  2345. * ERRNO: N/A
  2346. *
  2347. * NOMANUAL
  2348. */
  2349. int proc_nl
  2350.     (
  2351.     int code,  /* resource code for address pool field */
  2352.     int optype,  /* operation type (addition or deletion) */
  2353.     char **symbol,  /* current location in input string */
  2354.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2355.     )
  2356.     {
  2357.     u_long *lp = NULL;
  2358.     u_long tmp;
  2359.     switch (code) 
  2360.         {
  2361.         case S_TIME_OFFSET:
  2362.             lp = (u_long *) &rp->time_offset;
  2363.             break;
  2364.         case S_MTU_AGING_TIMEOUT:
  2365.             lp = &rp->mtu_aging_timeout;
  2366.             break;
  2367.         case S_ARP_CACHE_TIMEOUT:
  2368.             lp = &rp->arp_cache_timeout;
  2369.             break;
  2370.         case S_KEEPALIVE_INTER:
  2371.             lp = &rp->keepalive_inter;
  2372.             break;
  2373.         }
  2374.     if (optype == OP_ADDITION)
  2375.         {
  2376.         tmp = get_integer (symbol);
  2377.         *lp = htonl (tmp);
  2378.         }
  2379.     else 
  2380.         *lp = 0;
  2381.     return (0);
  2382.     }
  2383. /*******************************************************************************
  2384. *
  2385. * proc_ns - store short (2 byte) numeric values in network byte order
  2386. *
  2387. * This routine sets the fields of the lease descriptor containing two byte 
  2388. * numeric entries which are sent directly to the client. These entries are 
  2389. * indicated by "btsz", "mdgs", or "ifmt" in the address pool database, and 
  2390. * are stored in network byte order. When an "@" mark is appended to any of 
  2391. * the corresponding specifiers, the matching field is cleared.
  2392. *
  2393. * RETURNS: 0, always.
  2394. *
  2395. * ERRNO: N/A
  2396. *
  2397. * NOMANUAL
  2398. */
  2399. int proc_ns
  2400.     (
  2401.     int code,  /* resource code for address pool field */
  2402.     int optype,  /* operation type (addition or deletion) */
  2403.     char **symbol,  /* current location in input string */
  2404.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2405.     )
  2406.     {
  2407.     u_short *sp = NULL;
  2408.     u_short tmp;
  2409.     switch (code) 
  2410.         {
  2411.         case S_BOOTSIZE:
  2412.             sp = &rp->bootsize;
  2413.             break;
  2414.         case S_MAX_DGRAM_SIZE:
  2415.             sp = &rp->max_dgram_size;
  2416.             break;
  2417.         case S_IF_MTU:
  2418.             sp = &rp->intf_mtu;
  2419.             break;
  2420.         }
  2421.     if (optype == OP_ADDITION)
  2422.         {
  2423.         tmp = (short) get_integer (symbol);
  2424.         *sp = htons (tmp);
  2425.         }
  2426.     else
  2427.         *sp = 0;
  2428.     return (0);
  2429.     }
  2430. /*******************************************************************************
  2431. *
  2432. * proc_octet - store 1 byte numeric values
  2433. *
  2434. * This routine sets the fields of the lease descriptor containing single byte 
  2435. * numeric entries. These entries are indicated by "ditl", "dttl", or "nbnt" 
  2436. * in the address pool database. When an "@" mark is appended to any of the 
  2437. * corresponding specifiers, the matching field is cleared.
  2438. *
  2439. * RETURNS: 0, always.
  2440. *
  2441. * ERRNO: N/A
  2442. *
  2443. * NOMANUAL 
  2444. */
  2445. int proc_octet
  2446.     (
  2447.     int code,  /* resource code for address pool field */
  2448.     int optype,  /* operation type (addition or deletion) */
  2449.     char **symbol,  /* current location in input string */
  2450.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2451.     )
  2452.     {
  2453.     u_char *cp = NULL;
  2454.     switch (code) 
  2455.         {
  2456.         case S_DEFAULT_IP_TTL:
  2457.             cp = &rp->default_ip_ttl;
  2458.             break;
  2459.         case S_DEFAULT_TCP_TTL:
  2460.             cp = &rp->default_tcp_ttl;
  2461.             break;
  2462.         case S_NB_NODETYPE:
  2463.             cp = &rp->nb_nodetype;
  2464.             break;
  2465.         }
  2466.     if (optype == OP_ADDITION)
  2467.         *cp = (u_char) get_integer(symbol);
  2468.     else
  2469.         *cp = 0;
  2470.     return (0);
  2471.     }
  2472. /*******************************************************************************
  2473. *
  2474. * proc_str - store string values
  2475. *
  2476. * This routine sets the fields of the lease descriptor containing string 
  2477. * entries. These entries are indicated by identifiers such as "hstn" and 
  2478. * "mdmp" in the address pool database. When an "@" mark is appended to any 
  2479. * of the corresponding specifiers, the matching field is cleared.
  2480. *
  2481. * RETURNS: 0, always.
  2482. *
  2483. * ERRNO: N/A
  2484. *
  2485. * NOMANUAL
  2486. */
  2487. int proc_str
  2488.     (
  2489.     int code,  /* resource code for address pool field */
  2490.     int optype,  /* operation type (addition or deletion) */
  2491.     char **symbol,  /* current location in input string */
  2492.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2493.     )
  2494.     {
  2495.     char *cp = NULL;
  2496.     char tmpstr [MAXSTRINGLEN];
  2497.     switch (code) 
  2498.         {
  2499.         case S_HOSTNAME:
  2500.             cp = rp->hostname;
  2501.             break;
  2502.         case S_MERIT_DUMP:
  2503.             cp = rp->merit_dump;
  2504.             break;
  2505.         case S_DNS_DOMAIN:
  2506.             cp = rp->dns_domain;
  2507.             break;
  2508.         case S_ROOT_PATH:
  2509.             cp = rp->root_path;
  2510.             break;
  2511.         case S_EXTENSIONS_PATH:
  2512.             cp = rp->extensions_path;
  2513.             break;
  2514.         case S_NIS_DOMAIN:
  2515.             cp = rp->nis_domain;
  2516.             break;
  2517.         case S_NB_SCOPE:
  2518.             cp = rp->nb_scope;
  2519.             break;
  2520.         case S_NISP_DOMAIN:
  2521.             cp = rp->nisp_domain;
  2522.             break;
  2523.         }
  2524.     if (optype == OP_ADDITION) 
  2525.         {
  2526.         get_string (symbol, tmpstr);
  2527.         if (strlen (tmpstr) > MAXOPT)
  2528.             {
  2529.             bcopy (tmpstr, cp, MAXOPT);
  2530.             cp [MAXOPT] = '';
  2531.             }
  2532.         else
  2533.             {
  2534.             bcopy (tmpstr, cp, strlen (tmpstr));
  2535.             rp->sname [strlen (tmpstr)] = '';
  2536.             }
  2537.         }
  2538.     else 
  2539.         cp[0] = '';
  2540.     return (0);
  2541.     }
  2542. /*******************************************************************************
  2543. *
  2544. * proc_bool - process boolean values
  2545. *
  2546. * This routine sets the fields of the lease descriptor containing boolean 
  2547. * entries. These entries are indicated by identifiers such as "albp"
  2548. * and "ipfd" in the address pool database. When an "@" mark is appended
  2549. * to any of the corresponding specifiers, the matching field is cleared.
  2550. *
  2551. * RETURNS: 0, always.
  2552. *
  2553. * ERRNO: N/A
  2554. *
  2555. * NOMANUAL
  2556. */
  2557. int proc_bool
  2558.     (
  2559.     int code,  /* resource code for address pool field */
  2560.     int optype,  /* operation type (addition or deletion) */
  2561.     char **symbol,  /* current location in input string */
  2562.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  2563.     )
  2564.     {
  2565.     char tmpstr [MAXSTRINGLEN];
  2566.     char *cp = NULL;
  2567.     switch (code) 
  2568.         {
  2569.         case S_ALLOW_BOOTP:
  2570.             cp = &rp->allow_bootp;
  2571.             break;
  2572.         case S_IP_FORWARD:
  2573.             cp = &rp->ip_forward;
  2574.             break;
  2575.         case S_NONLOCAL_SRCROUTE:
  2576.             cp = &rp->nonlocal_srcroute;
  2577.             break;
  2578.         case S_ALL_SUBNET_LOCAL:
  2579.             cp = &rp->all_subnet_local;
  2580.             break;
  2581.         case S_MASK_DISCOVER:
  2582.             cp = &rp->mask_discover;
  2583.             break;
  2584.         case S_MASK_SUPPLIER:
  2585.             cp = &rp->mask_supplier;
  2586.             break;
  2587.         case S_ROUTER_DISCOVER:
  2588.             cp = &rp->router_discover;
  2589.             break;
  2590.         case S_TRAILER:
  2591.             cp = &rp->trailer;
  2592.             break;
  2593.         case S_ETHER_ENCAP:
  2594.             cp = &rp->ether_encap;
  2595.             break;
  2596.         case S_KEEPALIVE_GARBA:
  2597.             cp = &rp->keepalive_garba;
  2598.             break;
  2599.         }
  2600.     if (optype == OP_ADDITION) 
  2601.         {
  2602.         get_string (symbol, tmpstr);
  2603.         if (strcmp (tmpstr, "true") == 0)
  2604.             *cp = TRUE;
  2605.         else if (strcmp (tmpstr, "false") == 0)
  2606.             *cp = FALSE;
  2607.         else 
  2608.             {
  2609. #ifdef DHCPS_DEBUG
  2610.             logMsg("Warning: Invalid boolean value.n", 0, 0, 0, 0, 0, 0);
  2611. #endif
  2612.             *cp = FALSE;
  2613.             return (-1);
  2614.             }
  2615.         }
  2616.     else 
  2617.         *cp = 0;
  2618.     return (0);
  2619.     }
  2620. /*******************************************************************************
  2621. *
  2622. * read_addrpool_file - extract runtime address pool entries
  2623. *
  2624. * This routine calls an optional hook routine, supplied by the user. It
  2625. * retrieves any address pool entries added with dhcpsLeaseEntryAdd() after 
  2626. * DHCP server startup from permanent storage. If no storage hook was provided,
  2627. * any entries in the binding database referencing the runtime address entries 
  2628. * will be discarded. The corresponding leases will not be renewed.
  2629. *
  2630. * This routine is called once on server startup.
  2631. *
  2632. * RETURNS: OK if data update completed, or ERROR otherwise.
  2633. *
  2634. * ERRNO: N/A
  2635. *
  2636. * NOMANUAL
  2637. */
  2638. STATUS read_addrpool_file (void)
  2639.     {
  2640.     struct dhcp_resource *rp = NULL;
  2641.     DHCPS_ENTRY_DESC newEntry;
  2642.     struct hash_member *resptr = NULL;
  2643.     STATUS result = OK;
  2644.     char tmp [10];  /* sizeof ("tblc=dlft") for host requirements defaults. */
  2645.     char entryName [BASE_NAME + 1];   /* User-given name for address range. */
  2646.     char newName [MAX_NAME + 1];    /* Unique name for each entry in range. */
  2647.     char startAddress [INET_ADDR_LEN];
  2648.     char endAddress [INET_ADDR_LEN];
  2649.     char newAddress [INET_ADDR_LEN];
  2650.     char params [MAXENTRYLEN];
  2651.     struct in_addr nextAddr;
  2652.     int length;
  2653.     char *pTmp;
  2654.     u_long start = 0;
  2655.     u_long end = 0;
  2656.     u_long loop;
  2657.     u_long limit;
  2658.     int nresource = 0;
  2659.     if (dhcpsAddressHookRtn == NULL)
  2660.         return (OK);
  2661.     result = (* dhcpsAddressHookRtn) (DHCPS_STORAGE_START,
  2662.                                       NULL, NULL, NULL, NULL); 
  2663.     if (result == ERROR)
  2664.         {
  2665.         /* Fatal error - close address cache before server exits. */
  2666.         logMsg ("Unable to access address pool cache.n", 0, 0, 0, 0, 0, 0);
  2667.         (* dhcpsAddressHookRtn) (DHCPS_STORAGE_STOP, NULL, NULL, NULL, NULL);
  2668.         return (ERROR);
  2669.         }
  2670.     newEntry.pName = newName;
  2671.     newEntry.pAddress = newAddress;
  2672.     newEntry.pParams = params;
  2673.     FOREVER
  2674.         {
  2675.         result = (* dhcpsAddressHookRtn) (DHCPS_STORAGE_READ, entryName,
  2676.                                           startAddress, endAddress, params);
  2677.         if (result == ERROR)         /* No more data. */
  2678.             {
  2679.             result = OK;
  2680.             break;
  2681.             }
  2682.         /* check resource entry name */
  2683.         length = strlen (entryName);
  2684.         if (length == 0)
  2685.             {
  2686.             logMsg ("Error extracting entry name for entry %d.n",
  2687.                      nresource + 1, 0, 0, 0, 0, 0);
  2688.             continue;
  2689.             }
  2690.         /* check IP addresses */
  2691.         start = inet_addr (startAddress);
  2692.         end = inet_addr (endAddress);
  2693.         if (start == ERROR || end == ERROR)
  2694.             {
  2695.             logMsg ("Invalid address for entry %d.n", nresource + 1,
  2696.                      0, 0, 0, 0, 0);
  2697.             continue;
  2698.             }
  2699.         limit = ntohl (end);
  2700.         for (loop = ntohl (start); loop <= limit; loop++)
  2701.             {           
  2702.             rp = (struct dhcp_resource *)calloc (1, 
  2703.                                                 sizeof (struct dhcp_resource));
  2704.             if (rp == NULL)
  2705.                 {
  2706. #ifdef DHCPS_DEBUG
  2707.                 logMsg ("Memory allocation error in read_addrpool_file",
  2708.                          0, 0, 0, 0, 0, 0);
  2709. #endif
  2710.                 result = ERROR;
  2711.                 break;
  2712.                 }
  2713.             /* Generate a unique name by appending IP address value. */
  2714.             sprintf (newEntry.pName, "%s%lx", entryName, loop);
  2715.             /* Assign current IP address in range. */
  2716.             nextAddr.s_addr = htonl (loop);
  2717.             inet_ntoa_b (nextAddr, newEntry.pAddress);
  2718.             if (process_entry (rp, &newEntry) < 0)
  2719.                 {
  2720.                 logMsg ("Error processing file entry %d.n", nresource + 1,
  2721.                          0, 0, 0, 0, 0);
  2722.                 dhcpsFreeResource (rp);
  2723.                 break;
  2724.                 }
  2725.             /* 
  2726.              * Add Host Requirements defaults to resource entry. Do not add
  2727.              * to entries containing client-specific or class-specific 
  2728.              * parameters. 
  2729.              */
  2730.             if (ISCLR (rp->valid, S_PARAM_ID) && ISCLR (rp->valid, S_CLASS_ID))
  2731.                 { 
  2732.                 sprintf (tmp, "%s", "tblc=dflt");
  2733.                 pTmp = tmp;
  2734.                 eval_symbol (&pTmp, rp); 
  2735.                 }
  2736.             /* Set default values for entry, if not already assigned. */
  2737.             if (ISSET (rp->valid, S_IP_ADDR))
  2738.                 set_default (rp);
  2739.             /*
  2740.              * Append entries to lease descriptor list. Exclude entries which 
  2741.              * specify additional client- or class-specific parameters.
  2742.              */
  2743.             if (ISCLR (rp->valid, S_PARAM_ID) && ISCLR (rp->valid, S_CLASS_ID))
  2744.                 { 
  2745.                 resptr = reslist;
  2746.                 while (resptr->next != NULL)
  2747.                     resptr = resptr->next;
  2748.                 resptr->next = 
  2749.                    (struct hash_member *)calloc (1, 
  2750.                                                  sizeof (struct hash_member));
  2751.                 if (resptr->next == NULL)
  2752.                     {
  2753. #ifdef DHCPS_DEBUG
  2754.                     logMsg ("Memory allocation error in read_addrpool_file",
  2755.                              0, 0, 0, 0, 0, 0);
  2756. #endif
  2757.                     dhcpsFreeResource (rp);
  2758.                     result = ERROR;
  2759.                     break;
  2760.                     }
  2761.                 resptr = resptr->next;
  2762.                 resptr->next = NULL;
  2763.                 resptr->data = (void *)rp;
  2764.                 if (ISSET (rp->valid, S_IP_ADDR))
  2765.                     if (hash_ins (&iphashtable, (char *)&rp->ip_addr.s_addr,
  2766.                                   sizeof (u_long), resipcmp, &rp->ip_addr, rp) 
  2767.                         < 0)
  2768.                         {
  2769. #ifdef DHCPS_DEBUG
  2770.                         logMsg ("Hash table error reading address cache.n",
  2771.                                  0, 0, 0, 0, 0, 0);
  2772. #endif
  2773.                         result = ERROR;
  2774.                         break;
  2775.                         }
  2776.                 /* Add entryname to appropriate hash table. */
  2777.                 result = hash_ins (&nmhashtable, rp->entryname, 
  2778.                                    strlen (rp->entryname), resnmcmp, 
  2779.                                    rp->entryname, rp);
  2780.                 if (result < 0)
  2781.                     {
  2782. #ifdef DHCPS_DEBUG
  2783.                     logMsg ("Hash table error reading address cache.n",
  2784.                              0, 0, 0, 0, 0, 0);
  2785. #endif
  2786.                     result = ERROR;
  2787.                     break;
  2788.                     }
  2789.                 }
  2790.             nresource++;
  2791.             }
  2792.         if (result == ERROR)
  2793.             break;
  2794.         }
  2795.     if (result == OK)
  2796.         {
  2797. #ifdef DHCPS_DEBUG
  2798.         logMsg ("dhcps: read %d entries from address pool cache", nresource, 
  2799.                  0, 0, 0, 0, 0);
  2800. #endif
  2801.         }
  2802.     else
  2803.         {
  2804.         /* Fatal error - close address cache before server exits. */
  2805.         (* dhcpsAddressHookRtn) (DHCPS_STORAGE_STOP, NULL, NULL, NULL, NULL);
  2806.         } 
  2807.     return (result);
  2808.     }
  2809. /*
  2810.  *   The following code portions are Copyright (c) 1988 by Carnegie Mellon.
  2811.  *   Modified by Akihiro Tominaga, 1994. 
  2812.  *   Ported to VxWorks by Stephen Macmanus, 1996.
  2813.  */
  2814. /*
  2815.  * Copyright (c) 1988 by Carnegie Mellon.
  2816.  *
  2817.  * Permission to use, copy, modify, and distribute this program for any
  2818.  * purpose and without fee is hereby granted, provided that this copyright
  2819.  * and permission notice appear on all copies and supporting documentation,
  2820.  * the name of Carnegie Mellon not be used in advertising or publicity
  2821.  * pertaining to distribution of the program without specific prior
  2822.  * permission, and notice be given in supporting documentation that copying
  2823.  * and distribution is by permission of Carnegie Mellon and Stanford
  2824.  * University.  Carnegie Mellon makes no representations about the
  2825.  * suitability of this software for any purpose.  It is provided "as is"
  2826.  * without express or implied warranty.
  2827.  */
  2828. /*******************************************************************************
  2829. *
  2830. * read_addrpool_db - extract address entries from compiled image
  2831. *
  2832. * This routine retrieves the address pool entries hard-coded into usrNetwork.c
  2833. * as dhcpsLeaseTbl[] and creates the necessary descriptors to assign leases
  2834. * to DHCP or BOOTP clients.
  2835. *
  2836. * RETURNS: OK if database read successfully, or ERROR otherwise.
  2837. *
  2838. * ERRNO: N/A
  2839. *
  2840. * NOMANUAL
  2841. */
  2842. STATUS read_addrpool_db 
  2843.     (
  2844.     int poolsize  /* number of entries in hard-coded table */
  2845.     )
  2846.     {
  2847.     struct dhcp_resource *rp = NULL;
  2848.     DHCPS_ENTRY_DESC entryData;
  2849.     struct hash_member *resptr = NULL;
  2850.     char newName [MAX_NAME + 1];
  2851.     char entryName [BASE_NAME + 1];
  2852.     int len;
  2853.     char newAddress [INET_ADDR_LEN];
  2854.     char *  pStartAddr;
  2855.     char *  pEndAddr;
  2856.     struct in_addr newAddr;
  2857.     char tmp [10];
  2858.     char *pTmp;
  2859.     int nresource = 0;
  2860.     int loop;
  2861.     int result;
  2862.     u_long start;
  2863.     u_long end;
  2864.     u_long loop2;
  2865.     u_long limit;
  2866.     entryData.pName = newName;
  2867.     entryData.pAddress = newAddress;
  2868.  
  2869.     for (loop = 0; loop < poolsize; loop++)
  2870.         {
  2871.         pStartAddr = pDhcpsLeasePool [loop].pStartIp;
  2872.         pEndAddr = pDhcpsLeasePool [loop].pEndIp;
  2873.         /* Ignore bad values for range. */
  2874.         if (pStartAddr != NULL && pEndAddr == NULL)
  2875.             continue; 
  2876.         if (pStartAddr == NULL && pEndAddr != NULL)
  2877.             continue; 
  2878.         /* If no address specified, just process parameters once. */
  2879.         if (pStartAddr == NULL && pEndAddr == NULL)
  2880.             {
  2881.             start = 0;
  2882.             end = 0;
  2883.             }
  2884.         else
  2885.             {
  2886.             start = inet_addr (pStartAddr);
  2887.             end = inet_addr (pEndAddr);
  2888.             if (start == ERROR || end == ERROR)
  2889.                 continue;
  2890.             }
  2891.         entryData.pParams = pDhcpsLeasePool [loop].pParams;
  2892.         len = strlen (pDhcpsLeasePool[loop].pName);
  2893.         if (len > BASE_NAME)
  2894.             {
  2895.             bcopy (pDhcpsLeasePool[loop].pName, entryName, BASE_NAME);
  2896.             entryName [BASE_NAME] = '';
  2897.             }
  2898.         else
  2899.             {
  2900.             bcopy (pDhcpsLeasePool[loop].pName, entryName, len);
  2901.             entryName [len] = '';
  2902.             }
  2903.  
  2904.         limit = ntohl (end); 
  2905.         for (loop2 = ntohl (start); loop2 <= limit; loop2++)
  2906.             {
  2907.             rp = 
  2908.              (struct dhcp_resource *)calloc (1, sizeof (struct dhcp_resource));
  2909.             if (rp == NULL) 
  2910.                 {
  2911. #ifdef DHCPS_DEBUG
  2912.                 logMsg ("Memory allocation error in read_addrpool_db", 
  2913.                          0, 0, 0, 0, 0, 0);
  2914. #endif
  2915.                 return (ERROR);
  2916.                 }
  2917.             /* Generate a unique name for each entry in range. */
  2918.            if (loop == 0)  /* Don't modify name of default entry. */
  2919.                sprintf (entryData.pName, "%s", entryName);
  2920.            else
  2921.                sprintf (entryData.pName, "%s%lx", entryName, loop2);
  2922.             /* Store current IP address in range. */
  2923.             newAddr.s_addr = htonl (loop2);
  2924.             inet_ntoa_b (newAddr, entryData.pAddress);
  2925.             /* Add new entry to address pool. */
  2926.             if (process_entry (rp, &entryData) < 0) 
  2927.                 {
  2928.                 logMsg ("Error processing table entry %d.n", loop + 1, 
  2929.                          0, 0, 0, 0, 0);
  2930.                 dhcpsFreeResource (rp);
  2931.                 break;
  2932.                 }
  2933.             /* Add host requirements defaults to all lease entries. */
  2934.             if (loop != 0)     /* Ignore first entry, which holds defaults. */
  2935.                 {
  2936.                 /* Add Host Requirements Defaults to resource entry. Do not
  2937.                  * add to entries containing client-specific or class-specific
  2938.                  * parameters.
  2939.                  */ 
  2940.                 if (ISCLR (rp->valid, S_PARAM_ID) && 
  2941.                       ISCLR (rp->valid, S_CLASS_ID))
  2942.                     {
  2943.                     sprintf (tmp, "%s", "tblc=dflt");
  2944.                     pTmp = tmp;
  2945.                     eval_symbol (&pTmp, rp);
  2946.                     }
  2947.                 }
  2948.             /* Set default values for entry, if not assigned in table. */
  2949.             if (ISSET (rp->valid, S_IP_ADDR))
  2950.                 set_default (rp);
  2951.             /*
  2952.              * make resource list for lease entries. Exclude entries which 
  2953.              * specify additional client- or class-specific parameters.
  2954.              */
  2955.             if (ISCLR (rp->valid, S_PARAM_ID) && ISCLR (rp->valid, S_CLASS_ID))
  2956.                 { 
  2957.                 if (reslist == NULL) 
  2958.                     {
  2959.                     resptr = reslist = 
  2960.                         (struct hash_member *)calloc (1, 
  2961.                                                   sizeof (struct hash_member));
  2962.                     if (resptr == NULL) 
  2963.                         {
  2964. #ifdef DHCPS_DEBUG
  2965.                         logMsg ("Memory allocation error in read_addrpool_db", 
  2966.                                  0, 0, 0, 0, 0, 0);
  2967. #endif
  2968.                         dhcpsFreeResource (rp);
  2969.                         return (ERROR);
  2970.                         }
  2971.                     } 
  2972.                 else 
  2973.                     {
  2974.                     /* not first time */
  2975.                     resptr->next = 
  2976.                        (struct hash_member *)calloc (1, 
  2977.                                                   sizeof (struct hash_member));
  2978.                     if (resptr->next == NULL) 
  2979.                         {
  2980. #ifdef DHCPS_DEBUG
  2981.                         logMsg ("Memory allocation error in read_addrpool_db", 
  2982.                                  0, 0, 0, 0, 0, 0);
  2983. #endif
  2984.                         dhcpsFreeResource (rp);
  2985.                         return (ERROR);
  2986.                         }
  2987.                     resptr = resptr->next;
  2988.                     }
  2989.                 resptr->next = NULL;
  2990.                 resptr->data = (hash_datum *)rp;
  2991.                 /* Store entry in hash table with IP address as key. */
  2992.                 if (ISSET (rp->valid, S_IP_ADDR))
  2993.                     if (hash_ins (&iphashtable, (char *)&rp->ip_addr.s_addr,
  2994.                   sizeof (u_long), resipcmp, &rp->ip_addr, rp) 
  2995.                         < 0) 
  2996.                         {
  2997. #ifdef DHCPS_DEBUG
  2998.                         logMsg ("Hash table error reading address database.n", 
  2999.                                  0, 0, 0, 0, 0, 0);
  3000. #endif
  3001.                         return (ERROR); 
  3002.                         }
  3003.                 }
  3004.             /* Store entry in hash table with resource entryname as key. */
  3005.             result = hash_ins (&nmhashtable, rp->entryname, 
  3006.                                strlen (rp->entryname), resnmcmp, 
  3007.                                rp->entryname, rp);
  3008.             if (result < 0) 
  3009.                 {
  3010. #ifdef DHCPS_DEBUG
  3011.                 logMsg ("Hash table error reading address database.n", 
  3012.                          0, 0, 0, 0, 0, 0);
  3013. #endif
  3014.                 return (ERROR); 
  3015.                 }
  3016.             nresource++;
  3017.             }
  3018.         }
  3019. #ifdef DHCPS_DEBUG
  3020.     logMsg ("dhcps: read %d entries from addr-pool database.n", nresource, 
  3021.              0, 0, 0, 0, 0);
  3022. #endif
  3023.     return (OK);
  3024.     }
  3025. /*******************************************************************************
  3026. *
  3027. * read_entry - retrieve database entries from permanent storage
  3028. *
  3029. * This routine calls a hook routine, supplied by the user, to retrieve entries
  3030. * from the binding database. Each entry consists of a string with the following
  3031. * format:
  3032. *         idtype:id:subnet:htype:haddr:"expire_date":resource_name
  3033. *
  3034. * The colon delimited fields may contain quoted strings. The '' character is 
  3035. * used to embed special characters, such as a colon or double quote.
  3036. *
  3037. * RETURNS: N/A
  3038. *
  3039. * ERRNO: N/A
  3040. *
  3041. * NOMANUAL
  3042. */
  3043. static void read_entry
  3044.     (
  3045.     char *buffer,  /* buffer to store extracted data */
  3046.     unsigned *bufsiz  /* number of characters retrieved */
  3047.     )
  3048.     {
  3049.     int c = ' ';          /* Whitespace character. */
  3050.     int length = 0;
  3051.     int index = 0;
  3052.     char data [MAXSTRINGLEN];
  3053.     BOOL finished = FALSE;
  3054.     BOOL termfound = FALSE;   /* Terminator flag for special characters. */
  3055.     STATUS result;
  3056.     result = (* dhcpsLeaseHookRtn) (DHCPS_STORAGE_READ, data, MAXSTRINGLEN);
  3057.     if (result == ERROR)
  3058.         {
  3059.         buffer[0] = ''; /* Empty string */
  3060.         *bufsiz = 0;
  3061.         return; 
  3062.         }
  3063.     /*
  3064.      * read binding information 
  3065.      *
  3066.      * idtype:id:subnet:htype:haddr:"expire_date":resource_name
  3067.      */
  3068.     c = data[index++];
  3069.     while (c != '')
  3070.         { 
  3071.         /* Store the entry in the data buffer, processing special characters 
  3072.          * like double quotes (") and backslashes ().
  3073.          */
  3074.         switch (c) 
  3075.             {
  3076.             case '\':       /* Backslash - read a new character. */
  3077.                 c = data[index++];
  3078.                 *buffer++ = c;      /* Store the literal character */
  3079.                 length++;
  3080.                 if (length >= *bufsiz - 1) 
  3081.                     finished = TRUE; 
  3082.                 break;
  3083.             case '"':
  3084.                 *buffer++ = '"';        /* Store double-quote */
  3085.                 length++;
  3086.                 if (length >= *bufsiz - 1) 
  3087.                     {
  3088.                     finished = TRUE;
  3089.                     break;
  3090.                     }
  3091.                 termfound = FALSE;
  3092.                 c = data[index++];
  3093.                 while (c != '')       /* Special quote processing loop */
  3094.                     {
  3095.                     switch (c) 
  3096.                         {
  3097.                         case '"':
  3098.                     *buffer++ = '"';  /* Store matching quote */
  3099.                     length++;
  3100.                     if (length < *bufsiz - 1) 
  3101.                         termfound = TRUE;
  3102.                             else
  3103.                         finished = TRUE;
  3104.                             break;  
  3105.                         case '\':
  3106.                             c = data[index++];    /* Fall-through */
  3107.                         default:
  3108.                     *buffer++ = c;    /* Other character, store it */
  3109.                     length++;
  3110.                     if (length >= *bufsiz - 1) 
  3111.                                 finished = TRUE;   
  3112.                             break;
  3113.                         } 
  3114.                     if (finished || termfound)
  3115.                         break; 
  3116.                     c = data[index++];
  3117.                     }
  3118.                 if (c == '')      /* Missing close quote. */
  3119.                     finished = TRUE;
  3120.                 break;
  3121.             default:
  3122.                 *buffer++ = c; /* Store other characters */
  3123.                 length++;
  3124.                 if (length >= *bufsiz - 1) 
  3125.                     finished = TRUE;
  3126.                 break;
  3127.             }
  3128.         if (finished)    /* Buffer limit reached - stop reading. */
  3129.             break;
  3130.         c = data[index++];
  3131.         }    
  3132.     *buffer = ''; /* Terminate string */
  3133.     *bufsiz = length; /* Tell the caller its length */
  3134.     }
  3135. /*******************************************************************************
  3136. *
  3137. * process_entry - parse address pool entries  
  3138. *
  3139. * This routine forms lease descriptors from the address pool entries 
  3140. * retrieved from permanent storage or the compiled image. Each lease descriptor
  3141. * contains three strings: the entry name, the IP address, and a parameter list.
  3142. * The parameter list contains a colon-separated list of entries. The contents 
  3143. * of the parameter list determine the type of lease assignment. That type is 
  3144. * used by the server to select the priority with which lease entries are 
  3145. * issued to clients.
  3146. *
  3147. * RETURNS: 0 if processed successfully, or -1 otherwise. 
  3148. *
  3149. * ERRNO: N/A
  3150. *
  3151. * NOMANUAL
  3152. */
  3153. int process_entry
  3154.     (
  3155.     struct dhcp_resource *rp,  /* pointer to lease descriptor */
  3156.     DHCPS_ENTRY_DESC *  leaseData  /* pointer to address pool entry */
  3157.     )
  3158.     {
  3159.     char buffer[MAXENTRYLEN];
  3160.     char *src;
  3161.     if (!rp)
  3162.        return(-1);
  3163.     if (strlen (leaseData->pName) > MAX_NAME)
  3164.         {
  3165.         bcopy (leaseData->pName, rp->entryname, MAX_NAME);
  3166.         rp->entryname [MAX_NAME] = '';
  3167.         }
  3168.     else
  3169.         {
  3170.         bcopy (leaseData->pName, rp->entryname, strlen (leaseData->pName));
  3171.         rp->entryname [strlen (leaseData->pName)] = '';
  3172.         }
  3173.     if (leaseData->pAddress != NULL)
  3174.         {
  3175.         rp->ip_addr.s_addr = inet_addr (leaseData->pAddress);
  3176.         if (rp->ip_addr.s_addr != ERROR && rp->ip_addr.s_addr != 0)
  3177.             {
  3178.             SETBIT (rp->valid, S_IP_ADDR);
  3179.             SETBIT (rp->active, S_IP_ADDR);     /* Pass value to client. */
  3180.             }
  3181.         }
  3182.     sprintf (buffer, ":%s", leaseData->pParams);
  3183.     src = (char *)buffer;
  3184.     FOREVER 
  3185.         {
  3186.         adjust (&src);
  3187.         switch (eval_symbol (&src, rp)) 
  3188.             {
  3189.             case E_END_OF_ENTRY:    /* No more fields in entry. */
  3190.                 return(0);
  3191.                 break;
  3192.             case SUCCESS:           /* Continue processing fields. */
  3193.                 break;
  3194.             default:
  3195.                 return(-1);         /* Error in parameter entry. */
  3196.                 break;
  3197.             }
  3198.         }
  3199.     return (0);                   /* Not reached. */
  3200.     }
  3201. /*******************************************************************************
  3202. *
  3203. * adjust - update pointer to access individual parameters
  3204. *
  3205. * This routine adjusts the caller's pointer to point just past the colon which
  3206. * separates address pool parameters. If it encounters a null character, the
  3207. * pointer update stops.
  3208. *
  3209. * RETURNS: N/A
  3210. *
  3211. * ERRNO: N/A
  3212. *
  3213. * NOMANUAL
  3214. */
  3215. static void adjust
  3216.     (
  3217.     char **s  /* current location in input string */
  3218.     )
  3219.     {
  3220.     FAST char *t = NULL;
  3221.     t = *s;
  3222.     while (*t && (*t != ':')) 
  3223.         t++;
  3224.     if (*t) 
  3225.        t++;
  3226.     *s = t;
  3227.     return;
  3228.     }
  3229. /*******************************************************************************
  3230. *
  3231. * eval_symbol - process individual parameter entries
  3232. *
  3233. * This routine parses individual parameter entries. Each entry has one of
  3234. * two formats. Parameters may be added by including a string of the form
  3235. * <name>=<value> in the parameter field. Parameters may be deleted by
  3236. * including a parameter name followed by the "@" sign. This routine extracts
  3237. * the four character parameter name and uses it to determine the appopriate 
  3238. * processing function, named proc_* and defined above.
  3239. *
  3240. * Finally, parameter names may be preceded by the "!" character. This indicates
  3241. * that the added parameter is active. This designation is used to identify
  3242. * parameters with values which differ from those specified in the Host 
  3243. * Requirements RFC. Parameters designated as active are always sent to the
  3244. * DHCP client, which would otherwise use the Host Requirements values.
  3245. * RETURNS: 0 if processed successfully, or -1 otherwise.
  3246. *
  3247. * ERRNO: N/A
  3248. *
  3249. * NOMANUAL
  3250. */
  3251. int eval_symbol
  3252.     (
  3253.     char **symbol,  /* current location in input string */
  3254.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  3255.     )
  3256.     {
  3257.     struct symbolmap *symbolptr = NULL;
  3258.     int i = 0;
  3259.     int result;
  3260.     int optype = 0;         /* Indicates boolean, addition, or deletion */
  3261.     int active = 0;
  3262.     if ( (*symbol)[0] == '') 
  3263.         return(E_END_OF_ENTRY);
  3264.     if ( (*symbol)[0] == ':') 
  3265.         return (SUCCESS);
  3266.   
  3267.     eat_whitespace (symbol);
  3268.   
  3269.     /*
  3270.      * Is it active parameter? 
  3271.      * (this parameter is not default of Host Requirements RFC)
  3272.      */
  3273.     if ( (*symbol)[0] == '!')
  3274.         {
  3275.         active = TRUE;
  3276.         (*symbol)++;
  3277.         }
  3278.     else 
  3279.         active = FALSE;
  3280.     /* Determine the type of operation to be done on this symbol */
  3281.     switch ( (*symbol)[4]) 
  3282.         {
  3283.         case '=':
  3284.             optype = OP_ADDITION;
  3285.             break;
  3286.         case '@':
  3287.             optype = OP_DELETION;
  3288.             break;
  3289.         default:
  3290.             logMsg ("Warning: Unknown operation in resource database.n",
  3291.                      0, 0, 0, 0, 0, 0);
  3292.             return (-1);
  3293.         }
  3294.   
  3295.     symbolptr = symbol_list;
  3296.     for (i = 0; i <= S_LAST_OPTION; i++) 
  3297.         {
  3298.         if ( ( (symbolptr->symbol)[0] == (*symbol)[0]) &&
  3299.      ( (symbolptr->symbol)[1] == (*symbol)[1]) &&
  3300.      ( (symbolptr->symbol)[2] == (*symbol)[2]) &&
  3301.      ( (symbolptr->symbol)[3] == (*symbol)[3])) 
  3302.             break;
  3303.         symbolptr++;
  3304.         }
  3305.     if (i > S_LAST_OPTION) 
  3306.         {
  3307.         logMsg ("Warning: unknown symbol "%c%c%c%c" in "%s"", 
  3308.                  (*symbol)[0], (*symbol)[1], (*symbol)[2], (*symbol)[3], 
  3309.                  (int)rp->entryname, 0);
  3310.         return (-1);
  3311.         }
  3312.   
  3313.     /*
  3314.      * Skip past the = or @ character (to point to the data) if this
  3315.      * isn't a boolean operation.  For boolean operations, just skip
  3316.      * over the two-character tag symbol (and nothing else. . . .).
  3317.      */
  3318.     (*symbol) += 5;
  3319.     if (symbolptr->func != NULL) 
  3320.         {
  3321.         result = (*symbolptr->func) (symbolptr->code, optype, symbol, rp);
  3322.         if (symbolptr->code != S_TABLE_CONT) 
  3323.             {
  3324.             if (optype == OP_DELETION || result != 0) 
  3325.                 {
  3326.         CLRBIT (rp->valid, symbolptr->code);
  3327.         CLRBIT (rp->active, symbolptr->code);
  3328.                 } 
  3329.             else 
  3330.                 {
  3331.         SETBIT (rp->valid, symbolptr->code);
  3332.         if (active)
  3333.                     SETBIT (rp->active, symbolptr->code);
  3334.                 else
  3335.                     CLRBIT (rp->active, symbolptr->code);
  3336.                 }
  3337.             }
  3338.         return (result);
  3339.         } 
  3340.     else 
  3341.         {
  3342. #ifdef DHCPS_DEBUG
  3343.         logMsg ("Warning: No processing function for symbol.n", 
  3344.                  0, 0, 0, 0, 0, 0); 
  3345. #endif
  3346.         return (-1);
  3347.         }
  3348.     }
  3349. /*******************************************************************************
  3350. *
  3351. * eat_whitespace - update pointer to access meaningful characters
  3352. *
  3353. * This routine adjusts the caller's pointer to point past excess whitespace.
  3354. * If it encounters a null character, the pointer update stops.
  3355. *
  3356. * RETURNS: N/A
  3357. *
  3358. * ERRNO: N/A
  3359. *
  3360. * NOMANUAL
  3361. */
  3362. static void eat_whitespace
  3363.     (
  3364.     char **s /* current location in input string */
  3365.     )
  3366.     {
  3367.     FAST char *t = NULL;
  3368.     t = *s;
  3369.     while (*t && isspace ( (int) *t)) 
  3370.         t++;
  3371.     *s = t;
  3372.     }
  3373. /*******************************************************************************
  3374. *
  3375. * get_string - retrieve characters from input until delimiter reached
  3376. *
  3377. * This routine copies up to MAXSTRINGLEN characters into the provided buffer
  3378. * until the NULL character or a colon delimiter is encountered. The input
  3379. * pointer is also updated to point past the last character retrieved.
  3380. * It handles special characters preceded by "" as well as quoted substrings.
  3381. * Before returning, trailing whitespace is removed from the extracted string.
  3382. * RETURNS: N/A
  3383. *
  3384. * ERRNO: N/A
  3385. *
  3386. * NOMANUAL
  3387. */
  3388. static void get_string
  3389.     (
  3390.     char **src,  /* current location in input string */
  3391.     char *target  /* pointer to storage for extracted characters */
  3392.     )
  3393.     {
  3394.     int n = 0; 
  3395.     int len = 0; 
  3396.     int quoteflag = 0;
  3397.     char * tmpp = NULL;
  3398.     bzero (target, MAXSTRINGLEN);
  3399.     tmpp = target;
  3400.     quoteflag = FALSE;
  3401.     n = 0;
  3402.     len = MAXSTRINGLEN - 1;
  3403.     /* Extract characters until EOS or a colon delimiter is reached. */
  3404.     while ((n < MAXSTRINGLEN - 1) && (**src)) 
  3405.        {
  3406.        if (!quoteflag && (**src == ':')) 
  3407.            {
  3408.            break;
  3409.            }
  3410.        if (**src == '"') 
  3411.            {
  3412.            (*src)++;
  3413.            quoteflag = !quoteflag;
  3414.            continue;
  3415.            }
  3416.        if (**src == '\') 
  3417.            {
  3418.            (*src)++;
  3419.            if (! **src) 
  3420.                {
  3421.        break;
  3422.                }
  3423.            }
  3424.        *tmpp++ = *(*src)++;
  3425.        n++;
  3426.        }
  3427.   
  3428.     /* Remove that troublesome trailing whitespace. . .  */
  3429.     while ((n > 0) && isspace( (int) tmpp[-1])) 
  3430.        {
  3431.        tmpp--;
  3432.        n--;
  3433.        }
  3434.     *tmpp = '';
  3435.     return;
  3436.     }
  3437. /*******************************************************************************
  3438. *
  3439. * get_integer - retrieve numeric value from input until delimiter reached
  3440. *
  3441. * This routine converts the input string into a numeric value until NULL or 
  3442. * a non-digit character is reached. Hexadecimal numbers are specified by a 
  3443. * leading 0x and octal numbers by a leading 0. The input pointer is updated
  3444. * to indicate the first non-digit character.
  3445. *
  3446. * RETURNS: Extracted value, or 0 if none.
  3447. *
  3448. * ERRNO: N/A
  3449. *
  3450. * NOMANUAL
  3451. */
  3452. static long get_integer
  3453.     (
  3454.     char **src  /* current location in input string */
  3455.     )
  3456.     {
  3457.     FAST long value = 0;
  3458.     FAST long base = 0;
  3459.     int invert = 1;
  3460.     char c = 0;
  3461.     /*
  3462.      * Collect number up to first illegal character.  Values are specified
  3463.      * as for C:  0x=hex, 0=octal, other=decimal.
  3464.      */
  3465.     value = 0;
  3466.     base = 10;
  3467.     if (**src == '-') 
  3468.         {
  3469.         invert = -1;
  3470.         (*src)++;
  3471.         }
  3472.     if (**src == '0') 
  3473.         {
  3474.         base = 8;
  3475.         (*src)++;
  3476.         }
  3477.     if (**src == 'x' || **src == 'X') 
  3478.         {
  3479.         base = 16;
  3480.         (*src)++;
  3481.         }
  3482.     while ( (c = **src)) 
  3483.         {
  3484.         if (isdigit ( (int) c)) 
  3485.             {
  3486.             value = (value * base) + (c - '0');
  3487.             (*src)++;
  3488.             continue;
  3489.             }
  3490.         if (base == 16 && isxdigit ( (int)c)) 
  3491.             {
  3492.             /* Convert hex alpha digits to uppercase, then to numeric value. */
  3493.             value = (value << 4) + ((c & ~32) + 10 - 'A');
  3494.             (*src)++;
  3495.             continue;
  3496.             }
  3497.         break;
  3498.         }
  3499.     return (invert * value);
  3500.     }
  3501. /*******************************************************************************
  3502. *
  3503. * prs_inaddr - retrieve numeric value for IP address until delimiter reached
  3504. *
  3505. * This routine converts the dot notation input string into a numeric value,
  3506. * and stores the result (in network byte order) in the provided parameter.
  3507. * The input pointer is updated to indicate the next character in the string.
  3508. *
  3509. * RETURNS: 0 if successful, or -1 for bad format. 
  3510. *
  3511. * ERRNO: N/A
  3512. *
  3513. * NOMANUAL
  3514. */
  3515. static int prs_inaddr
  3516.     (
  3517.     char **src,  /* current location in input string */
  3518.     u_long *result  /* pointer to storage for extracted value */
  3519.     )
  3520.     {
  3521.     FAST u_long value = 0;
  3522.     u_long parts[4]; 
  3523.     u_long * pp = parts;
  3524.     int n;
  3525.   
  3526.     if (!isdigit ( (int) **src)) 
  3527.         return (-1);
  3528.     FOREVER
  3529.         {
  3530.         value = get_integer (src);
  3531.         if (**src == '.') 
  3532.             {
  3533.             /*
  3534.              * Internet format:
  3535.              *      a.b.c.d
  3536.              *      a.b.c      (with c treated as 16-bits)
  3537.              *      a.b        (with b treated as 24 bits)
  3538.              */
  3539.             if (pp >= parts + 4) 
  3540.                 return (-1);
  3541.             *pp++ = value;
  3542.             (*src)++;
  3543.             continue;
  3544.             }
  3545.         break;
  3546.         }
  3547.     /*
  3548.      * Check for trailing characters.
  3549.      */
  3550.     if (**src && ! (isspace ( (int) **src) || (**src == ':'))) 
  3551.         return (-1);
  3552.     *pp++ = value;
  3553.     /* Construct the address according to the number of parts specified.  */
  3554.     n = pp - parts;
  3555.     switch (n) 
  3556.         {
  3557.         case 1:        /* a -- 32 bits */
  3558.             value = parts[0];
  3559.             break;
  3560.         case 2:        /* a.b -- 8.24 bits */
  3561.             value = (parts[0] << 24) | (parts[1] & 0xFFFFFF);
  3562.             break;
  3563.         case 3:        /* a.b.c -- 8.8.16 bits */
  3564.             value = (parts[0] << 24) | ((parts[1] & 0xFF) << 16) |
  3565.                     (parts[2] & 0xFFFF);
  3566.             break;
  3567.         case 4:        /* a.b.c.d -- 8.8.8.8 bits */
  3568.             value = (parts[0] << 24) | ( (parts[1] & 0xFF) << 16) |
  3569.                      ( (parts[2] & 0xFF) << 8) | (parts[3] & 0xFF);
  3570.             break;
  3571.         default:
  3572.             return (-1);
  3573.         }
  3574.     *result = htonl(value);
  3575.     return (0);
  3576.     }
  3577. /*******************************************************************************
  3578. *
  3579. * resnmcmp - verify resource name for address pool entries
  3580. *
  3581. * This routine compares a hash table key against the entry name of a 
  3582. * lease descriptor. It is used when storing and retrieving lease
  3583. * descriptors with the internal hash tables.
  3584. *
  3585. * RETURNS: TRUE if names match, or FALSE otherwise.
  3586. *
  3587. * ERRNO: N/A
  3588. *
  3589. * NOMANUAL
  3590. */
  3591. int resnmcmp
  3592.     (
  3593.     char *name,  /* pointer to hash table key */
  3594.     struct dhcp_resource *rp  /* pointer to lease descriptor */
  3595.     )
  3596.     {
  3597.     return !strcmp (name, rp->entryname);
  3598.     }