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

VxWorks

开发平台:

C/C++

  1. /* dhcpsLib.c - Dynamic Host Configuration Protocol (DHCP) server library */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc.  */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01v,16nov01,spm  fixed modification history
  8. 01u,29oct01,wap  Correct typo in documentation (SPR #34808)
  9. 01t,15oct01,rae  merge from truestack ver 01x, base 01p (VIRTUAL_STACK)
  10. 01s,17nov00,spm  added support for BSD Ethernet devices
  11. 01r,24oct00,spm  fixed modification history after merge from tor3_0_x branch;
  12.                  corrected pathname in library description
  13. 01q,23oct00,niq  merged from version 01t of tor3_0_x branch (base version 01p);
  14.                  upgrade to BPF replaces tagged frames support
  15. 01p,17jan98,kbw  removed NOMANUAL restriction from init function
  16. 01o,17dec97,spm  fixed byte order of address-based loop boundaries (SPR #20056)
  17. 01n,14dec97,kbw  made minor man page fixes
  18. 01m,10dec97,kbw  made minor man page fixes
  19. 01l,04dec97,spm  added code review modifications
  20. 01k,25oct97,kbw  made minor man page fixes
  21. 01j,06oct97,spm  removed reference to deleted endDriver global; replaced with
  22.                  support for dynamic driver type detection
  23. 01i,25sep97,gnn  SENS beta feedback fixes
  24. 01h,26aug97,spm  added code review fixes and support for UDP port selection
  25. 01g,12aug97,gnn  changes necessitated by MUX/END update.
  26. 01f,30jul97,kbw  fixed man page problems found in beta review
  27. 01e,15jul97,spm  allowed startup without lease storage; changed module title
  28. 01d,02jun97,spm  updated man pages and added ERRNO entries
  29. 01c,06may97,spm  changed memory access to align IP header on four byte
  30.                  boundary and corrected cleanup routine
  31. 01b,17apr97,kbw  fixed man page format, changed wording, spell checked doc
  32. 01a,07apr97,spm  created by modifying WIDE project DHCP implementation
  33. */
  34. /*
  35. DESCRIPTION
  36. This library implements the server side of the Dynamic Host Configuration
  37. Protocol (DHCP).  DHCP is an extension of BOOTP.  Like BOOTP, it allows a
  38. target to configure itself dynamically by using the network to get 
  39. its IP address, a boot file name, and the DHCP server's address.  Additionally,
  40. DHCP provides for automatic reuse of network addresses by specifying
  41. individual leases as well as many additional options.  The compatible
  42. message format allows DHCP participants to interoperate with BOOTP
  43. participants.  The dhcpsInit() routine links this library into the VxWorks 
  44. image.  This happens automatically if INCLUDE_DHCPS is defined when the image 
  45. is built.
  46. PRIMARY INTERFACE
  47. The dhcpsInit() routine initializes the server.  It reads the hard-coded server 
  48. configuration data that is stored in three separate tables.
  49. The first table contains entries as follows:
  50. .CS
  51. DHCPS_LEASE_DESC dhcpsLeaseTbl [] =
  52.     {
  53.     {"sample1", "90.11.42.24", "90.11.42.24", "clid=e"1:0x08003D21FE90e""},
  54.     {"sample2", "90.11.42.25", "90.11.42.28", "maxl=90:dfll=60"},
  55.     {"sample3", "90.11.42.29", "90.11.42.34", "maxl=0xffffffff:file=/vxWorks"},
  56.     {"sample4", "90.11.42.24", "90.11.42.24", "albp=true:file=/vxWorks"}
  57.     };
  58. .CE
  59. Each entry contains a name of up to eight characters, the starting and ending 
  60. IP addresses of a range, and the parameters associated with the lease.  The
  61. four samples shown demonstrate the four types of leases. 
  62. Manual leases contain a specific client ID, and are issued only to that client, 
  63. with an infinite duration.  The example shown specifies a MAC address, which is 
  64. the identifier type used by the VxWorks DHCP client.
  65. Dynamic leases specify a finite maximum length, and can be issued to any
  66. requesting client.  These leases allow later re-use of the assigned IP address.
  67. If not explicitly specified in the parameters field, these leases use the 
  68. values of DHCPS_MAX_LEASE and DHCPS_DFLT_LEASE to determine the lease length.
  69. Automatic leases are implied by the infinite maximum length.  Their IP addresses
  70. are assigned permanently to any requesting client.
  71. The last sample demonstrates a lease that is also available to BOOTP clients.
  72. The infinite maximum length is implied, and any timing-related parameters are
  73. ignored. 
  74. The DHCP server supplies leases to DHCP clients according to the lease type in
  75. the order shown above.  Manual leases have the highest priority and leases 
  76. available to BOOTP clients the lowest.
  77. Entries in the parameters field may be one of these types:
  78. .IP `bool' 8
  79. Takes values of "true" or "false", for example, ipfd=true.  Unrecognized 
  80. values default to false. 
  81. .IP 'str'
  82. Takes a character string as a value, for example, hstn="clapton".
  83. If the string includes a delimiter character, such as a colon, it 
  84. should be enclosed in quotation marks.
  85. .IP 'octet'
  86. Takes an 8-bit integer in decimal, octal, or hexadecimal, for example,
  87. 8, 070, 0xff.
  88. .IP 'short'
  89. Takes a 16-bit integer.
  90. .IP 'long'
  91. Takes a 32-bit integer.
  92. .IP 'ip'
  93. Takes a string that is interpreted 
  94. as a 32-bit IP address.  One of the following formats is
  95. expected: a.b.c.d, a.b.c or a.b.  In the second
  96. format, c is interpreted as a 16-bit value.  In
  97. the third format, b is interpreted as a 24-bit
  98. value, for example siad=90.11.42.1.  
  99. .IP 'iplist'
  100. Takes a list of IP addresses, separated by
  101. white space, for example, rout=133.4.31.1 133.4.31.2 133.4.31.3.
  102. .IP 'ippairs'
  103. Takes a list of IP address pairs.  Each IP
  104. address is separated by white space and grouped
  105. in pairs, for example, strt=133.4.27.0  133.4.31.1
  106. 133.4.36.0 133.4.31.1.
  107. .IP 'mtpt'
  108. Takes a list of 16 bit integers,
  109. separated by white space, for example, mtpt=1 2 3 4 6 8.
  110. .IP 'clid'
  111. Takes a client identifier as a value.
  112. Client identifiers are represented by the quoted
  113. string "<type>:<data>", where <type> is an
  114. integer from 0 to 255, as defined by the IANA,
  115. and <data> is a sequence of 8-bit values in hexadecimal.
  116. The client ID is usually a MAC address, for example, 
  117. clid="1:0x08004600e5d5".
  118. .LP
  119. The following table lists the option specifiers and descriptions for
  120. every possible entry in the parameter list.  When available, the option
  121. code from RFC 2132 is included.
  122. .TS
  123. tab(|);
  124. lf3 lf3 lf3 lf3
  125. l   l   l   l.
  126. Name | Code | Type    | Description
  127. _
  128. snam | -    | str     | Optional server name.
  129. file | -    | str     | Name of file containing the boot image.
  130. siad | -    | ip      | Address of server that offers the boot image.
  131. albp | -    | bool    | If true, this entry is also available
  132.      |      |         | to BOOTP clients.  For entries using
  133.      |      |         | static allocation, this value becomes
  134.      |      |         | true by default and <maxl> becomes
  135.      |      |         | infinity.
  136. maxl | -    | long    | Maximum lease duration in seconds. 
  137. dfll | -    | long    | Default lease duration in seconds.  If a
  138.      |      |         | client does not request a specific lease
  139.      |      |         | duration, the server uses this value.
  140. clid | -    | clid    | This specifies a client identifier for
  141.      |      |         | manual leases.  The VxWorks client uses
  142.      |      |         | a MAC address as the client identifier.
  143. pmid | -    | clid    | This specifies a client identifier for
  144.      |      |         | client-specific parameters to be included
  145.      |      |         | in a lease.  It should be present in separate
  146.      |      |         | entries without IP addresses.
  147. clas | -    | str     | This specifies a class identifier for
  148.      |      |         | class-specific parameters to be included in 
  149.      |      |         | a lease.  It should be present in separate entries
  150.      |      |         | without IP addresses.
  151. snmk | 1    | ip      | Subnet mask of the IP address to be
  152.      |      |         | allocated.  The default is a natural mask
  153.      |      |         | corresponding to the IP address.  The
  154.      |      |         | server will not issue IP addresses to 
  155.      |      |         | clients on different subnets.
  156. tmof | 2    | long    | Time offset from UTC in seconds.
  157. rout | 3    | iplist  | A list of routers on the same subnet as
  158.      |      |         | the client.
  159. tmsv |  4   | iplist  | A list of time servers (RFC 868).
  160. nmsv |  5   | iplist  | A list of name servers (IEN 116).
  161. dnsv |  6   | iplist  | A list of DNS servers (RFC 1035).
  162. lgsv |  7   | iplist  | A list of MIT-LCS UDP log servers.
  163. cksv |  8   | iplist  | A list of Cookie servers (RFC 865).
  164. lpsv |  9   | iplist  | A list of LPR servers (RFC 1179).
  165. imsv |  10  | iplist  | A list of Imagen Impress servers.
  166. rlsv |  11  | iplist  | A list of Resource Location servers (RFC 887).
  167. hstn |  12  | str     | Hostname of the client.
  168. btsz |  13  | short   | Size of boot image.
  169. mdmp |  14  | str     | Path name to which client dumps core.
  170. dnsd |  15  | str     | Domain name for DNS.
  171. swsv |  16  | ip      | IP address of swap server.
  172. rpth |  17  | str     | Path name of root disk of the client.
  173. epth |  18  | str     | Extensions Path (See RFC 1533).
  174. ipfd |  19  | bool    | If true, the client performs IP
  175.      |      |         | forwarding.
  176. nlsr |  20  | bool    | If true, the client can perform non-local
  177.      |      |         | source routing.
  178. plcy |  21  | ippairs | Policy filter for non-local source
  179.      |      |         | routing.  A list of pairs of
  180.      |      |         | (Destination IP, Subnet mask).
  181. mdgs |  22  | short   | Maximum size of IP datagram that the
  182.      |      |         | client should be able to reassemble.
  183. ditl |  23  | octet   | Default IP TTL.
  184. mtat |  24  | long    | Aging timeout (in seconds) to be used
  185.      |      |         | with Path MTU discovery (RFC 1191).
  186. mtpt |  25  | mtpt    | A table of MTU sizes to be used with
  187.      |      |         | Path MTU Discovery.
  188. ifmt |  26  | short   | MTU to be used on an interface.
  189. asnl |  27  | bool    | If true, the client assumes that all
  190.      |      |         | subnets to which the client is connected
  191.      |      |         | use the same MTU.
  192. brda |  28  | ip      | Broadcast address in use on the client's
  193.      |      |         | subnet.  The default is calculated from
  194.      |      |         | the subnet mask and the IP address.
  195. mskd |  29  | bool    | If true, the client should perform subnet
  196.      |      |         | mask discovery using ICMP.
  197. msks |  30  | bool    | If true, the client should respond to
  198.      |      |         | subnet mask requests using ICMP.
  199. rtrd |  31  | bool    | If true, the client should solicit
  200.      |      |         | routers using Router Discovery defined
  201.      |      |         | in RFC 1256.
  202. rtsl |  32  | ip      | Destination IP address to which the
  203.      |      |         | client sends router solicitation
  204.      |      |         | requests.
  205. strt |  33  | ippairs | A table of static routes for the client,
  206.      |      |         | which are pairs of (Destination, Router).
  207.      |      |         | It is illegal to specify default route
  208.      |      |         | as a destination.
  209. trlr |  34  | bool    | If true, the client should negotiate
  210.      |      |         | the use of trailers with ARP (RFC 893).
  211. arpt |  35  | long    | Timeout in seconds for ARP cache.
  212. encp |  36  | bool    | If false, the client uses RFC 894
  213.      |      |         | encapsulation.  If true, it uses
  214.      |      |         | RFC 1042 (IEEE 802.3) encapsulation.
  215. dttl |  37  | octet   | Default TTL of TCP.
  216. kain |  38  | long    | Interval of the client's TCP keepalive
  217.      |      |         | in seconds.
  218. kagb |  39  | bool    | If true, the client should send TCP
  219.      |      |         | keepalive messages with a octet of
  220.      |      |         | garbage for compatibility.
  221. nisd |  40  | str     | Domain name for NIS.
  222. nisv |  41  | iplist  | A list of NIS servers.
  223. ntsv |  42  | iplist  | A list of NTP servers.
  224. nnsv |  44  | iplist  | A list of NetBIOS name server.
  225.      |      |         | (RFC 1001, 1002)
  226. ndsv |  45  | iplist  | A list of NetBIOS datagram distribution
  227.      |      |         | servers (RFC 1001, 1002).
  228. nbnt |  46  | octet   | NetBIOS node type (RFC 1001, 1002).
  229. nbsc |  47  | str     | NetBIOS scope (RFC 1001, 1002).
  230. xfsv |  48  | iplist  | A list of font servers of X Window system.
  231. xdmn |  49  | iplist  | A list of display managers of X Window
  232.      |      |         | system.
  233. dht1 |  58  | short   | This value specifies when the client should
  234.      |      |         | start RENEWING.  The default of 500 means
  235.      |      |         | the client starts RENEWING after 50% of the
  236.      |      |         | lease duration passes.
  237. dht2 |  59  | short   | This value specifies when the client should
  238.      |      |         | start REBINDING.  The default of 875 means
  239.      |      |         | the client starts REBINDING after 87.5% of
  240.      |      |         | the lease duration passes.
  241. .TE
  242. .LP
  243. Finally, to function correctly, the DHCP server requires access to some form
  244. of permanent storage.  The DHCPS_LEASE_HOOK constant specifies the name of a 
  245. storage routine with the following interface:
  246. .CS
  247.     STATUS dhcpsStorageHook (int op, char *buffer, int datalen);
  248. .CE
  249. The storage routine is installed by a call to the dhcpsLeaseHookAdd() routine
  250. The manual pages for dhcpsLeaseHookAdd() describe the parameters and required 
  251. operation of the storage routine.
  252. SECONDARY INTERFACE
  253. In addition to the hard-coded entries, address entries may be added after the 
  254. server has started by calling the following routine:
  255. .CS
  256.     STATUS dhcpsLeaseEntryAdd (char *name, char *start, char *end, char *config);
  257. .CE
  258. The parameters specify an entry name, starting and ending values for a block 
  259. of IP addresses, and additional configuration information in the same format 
  260. as shown above for the hard-coded entries.  Each parameter must be formatted 
  261. as a NULL-terminated string. 
  262. The DHCPS_ADDRESS_HOOK constant specifies the name of a storage routine, used 
  263. to preserve address entries added after startup, which has the following 
  264. prototype:
  265. .CS
  266.     STATUS dhcpsAddressStorageHook (int op,
  267.     char *name, char *start, char *end, 
  268.     char *params);
  269. .CE
  270. The storage routine is installed with the dhcpsAddressHookAdd() routine, and 
  271. is fully described in the manual pages for that function.
  272. OPTIONAL INTERFACE
  273. The DHCP server can also receive messages forwarded from different subnets
  274. by a relay agent.  To provide addresses to clients on different subnets, the
  275. appropriate relay agents must be listed in the provided table in usrNetwork.c. 
  276. A sample configuration is:
  277. .CS
  278.     DHCPS_RELAY_DESC dhcpsRelayTbl [] =
  279. {
  280. {"90.11.46.75", "90.11.46.0"}
  281. };
  282. .CE
  283. Each entry in the table specifies the address of a relay agent that will 
  284. transmit the request and the corresponding subnet number.  To issue leases
  285. successfully, the address pool must also contain IP addresses for the 
  286. monitored subnets.
  287. The following table allows a DHCP server to act as a relay agent in 
  288. addition to its default function of processing messages.  It consists of 
  289. a list of IP addresses.
  290. .CS
  291.     DHCP_TARGET_DESC dhcpTargetTbl [] =
  292.  {
  293.  {"90.11.43.2"},
  294.  {"90.11.44.1"}
  295.  };
  296. .CE
  297. Each IP address in this list receives a copy of any client messages
  298. generated on the subnets monitored by the server.
  299. INTERNAL
  300. This library provides a wrapper for the WIDE project DHCP code found in the
  301. directory .../target/src/dhcp, which contains all the message
  302. processing functions.  This module uses the Berkeley Packet Filter services
  303. to intercept incoming DHCP messages and signals their arrival to the WIDE
  304. project code using a shared semaphore.
  305. INCLUDE FILES: dhcpsLib.h
  306. SEE ALSO: RFC 1541, RFC 1533
  307. */
  308. /* includes */
  309. #include "vxWorks.h"
  310. #include "dhcp/copyright_dhcp.h"
  311. #include "stdio.h"
  312. #include "stdlib.h"
  313. #include "netinet/if_ether.h"
  314. #include "netinet/in.h"
  315. #include "netinet/ip.h"
  316. #include "netinet/udp.h"
  317. #include "sys/ioctl.h"
  318. #include "inetLib.h"
  319. #include "end.h"
  320. #include "ipProto.h"
  321. #include "ioLib.h"             /* close() declaration. */
  322. #include "logLib.h"
  323. #include "rngLib.h"
  324. #include "semLib.h"
  325. #include "sockLib.h"
  326. #include "taskLib.h"
  327. #include "muxLib.h"
  328. #include "dhcp/dhcp.h"
  329. #include "dhcp/common.h"
  330. #include "dhcp/hash.h"
  331. #include "dhcp/common_subr.h"
  332. #include "dhcpsLib.h"
  333. #include "bpfDrv.h"
  334. /* defines */
  335. #define _DHCPS_MAX_DEVNAME 26  /* "/bpf/dhcps" + max unit number + vs num */
  336. /* globals for both the regular and virtual stacks */
  337. #ifndef VIRTUAL_STACK
  338. /* globals */
  339. DHCPS_RELAY_DESC *      pDhcpsRelaySourceTbl;
  340. DHCPS_LEASE_DESC * pDhcpsLeasePool;
  341. long    dhcps_dflt_lease; /* Default for default lease length */
  342. long  dhcps_max_lease;  /* Default maximum lease length */
  343. SEM_ID  dhcpsMutexSem;             /* Synchronization for lease entry adds. */
  344. FUNCPTR dhcpsLeaseHookRtn = NULL;  /* Accesses storage for lease bindings. */
  345. FUNCPTR dhcpsAddressHookRtn = NULL; /* Preserves additional address entries. */
  346. int dhcpsMaxSize;  /* Transmit buffer size & largest supported message. */
  347. int dhcpsBufSize;  /* Size of buffer for BPF devices */
  348. IMPORT struct iovec sbufvec[2];            /* send buffer */
  349. IMPORT struct msg dhcpsMsgOut;
  350. IMPORT struct hash_member *reslist;
  351. IMPORT struct hash_member *bindlist;
  352. IMPORT struct hash_tbl nmhashtable;
  353. IMPORT struct hash_tbl iphashtable;
  354. IMPORT struct hash_tbl cidhashtable;
  355. IMPORT struct hash_tbl relayhashtable;
  356. IMPORT struct hash_tbl paramhashtable;
  357. IMPORT char *dhcpsSendBuf;
  358. IMPORT char *dhcpsOverflowBuf;
  359. IMPORT u_short dhcps_port;
  360. IMPORT u_short dhcpc_port;
  361. /* locals */
  362. struct if_info *dhcpsIntfaceList = NULL;
  363. LOCAL BOOL dhcpsInitialized = FALSE;
  364. /* Berkeley Packet Filter instructions for catching DHCP messages. */
  365. LOCAL struct bpf_insn dhcpfilter[] = DHCPS_FILTER_DEFINE;
  366. LOCAL struct bpf_program dhcpread = {
  367.     sizeof (dhcpfilter) / sizeof (struct bpf_insn),
  368.     dhcpfilter
  369.     };
  370. #else
  371. #include "netinet/vsLib.h"
  372. #include "netinet/vsDhcps.h"
  373. #endif  /* VIRTUAL_STACK */
  374. /* forward declarations */
  375. LOCAL STATUS alloc_sbuf (int);
  376. void dhcpsCleanup (int);
  377. void dhcpsFreeResource (struct dhcp_resource *);
  378. IMPORT int resnmcmp();
  379. IMPORT int resipcmp();
  380. IMPORT int eval_symbol (void *, void *);
  381. IMPORT int open_if();
  382. IMPORT STATUS read_addrpool_file (void);
  383. IMPORT void read_server_db (int);
  384. IMPORT int process_entry (struct dhcp_resource *, DHCPS_ENTRY_DESC *);
  385. IMPORT void set_default (struct dhcp_resource *);
  386. /*******************************************************************************
  387. *
  388. * dhcpsInit - set up the DHCP server parameters and data structures
  389. *
  390. * This routine creates the necessary data structures, builds the
  391. * server address pool, retrieves any lease or address information from 
  392. * permanent storage through the user-provided hooks, and initializes the 
  393. * network interfaces for monitoring.  It is called at system startup if 
  394. * INCLUDE_DHCPS is defined at the time the VxWorks image is built.
  395. *
  396. * The <maxSize> parameter specifies the maximum length supported for any
  397. * DHCP message, including the UDP and IP headers and the largest link
  398. * level header for all supported devices. The smallest valid value is
  399. * 576 bytes, corresponding to the minimum IP datagram a host must accept.
  400. * Larger values will allow the server to handle longer DHCP messages.
  401. * RETURNS: OK, or ERROR if could not initialize.
  402. *
  403. */
  404. STATUS dhcpsInit
  405.     (
  406.     DHCPS_CFG_PARAMS  *pDhcpsCfg      /* configuration parameters */
  407.     )
  408.     {
  409.     struct if_info *pIf = NULL;            /* pointer to interface */
  410.     struct ifnet *pCIf = NULL;           /* pointer to current interface */
  411.     char bpfDevName [_DHCPS_MAX_DEVNAME];  /* "/bpf/dhcps" + max unit number */
  412. #ifdef VIRTUAL_STACK
  413.     char temp [_DHCPS_MAX_DEVNAME];
  414. #endif /* VIRTUAL_STACK */
  415.     int bpfDev;
  416.     struct ifreq ifreq;
  417.     struct sockaddr_in send_addr;
  418.     int loop;
  419.     int result;
  420.     STATUS status;
  421.     if (pDhcpsCfg == (DHCPS_CFG_PARAMS  *)NULL)
  422. return (ERROR);
  423. #ifdef VIRTUAL_STACK
  424.     if (dhcpsVsInit () == ERROR)
  425.         return (ERROR);
  426. #endif /* VIRTUAL_STACK */
  427.     /* It must return error, if it is already initialized */
  428.     if (dhcpsInitialized)
  429.         return (ERROR);
  430.     if (pDhcpsCfg->dhcpMaxMsgSize < DFLTDHCPLEN + UDPHL + IPHL)
  431.         return (ERROR);
  432.     if (bpfDrv () == ERROR)
  433.         return (ERROR);
  434.     dhcpsMaxSize = pDhcpsCfg->dhcpMaxMsgSize;
  435.     dhcpsBufSize = pDhcpsCfg->dhcpMaxMsgSize + sizeof (struct bpf_hdr);
  436.     dhcps_dflt_lease = pDhcpsCfg->dhcpsDfltLease;
  437.     dhcps_max_lease = pDhcpsCfg->dhcpsMaxLease;
  438.     dhcpsLeaseHookAdd (pDhcpsCfg->pDhcpsLeaseFunc);
  439.     dhcpsAddressHookAdd (pDhcpsCfg->pDhcpsAddrFunc);
  440. #ifdef VIRTUAL_STACK
  441.     sprintf(temp, "/bpf/vs%d_dhcps", myStackNum );
  442.     if (bpfDevCreate (temp, pDhcpsCfg->numDev, dhcpsBufSize) == ERROR)
  443. #else
  444.     if (bpfDevCreate ("/bpf/dhcps", pDhcpsCfg->numDev, dhcpsBufSize) == ERROR)
  445. #endif /* VIRTUAL_STACK */
  446.         return (ERROR);
  447.     dhcpsMutexSem = semBCreate (SEM_Q_FIFO, SEM_FULL);
  448.     if (dhcpsMutexSem == NULL)
  449.         return (ERROR);
  450.     bzero ( (char *)&ifreq, sizeof (ifreq));
  451.  
  452.     srand (taskIdSelf ());
  453.     /* Validate the MTU size. */
  454.     for (loop = 0; loop < pDhcpsCfg->numDev; loop++)
  455.         {
  456. pCIf = ifunit (pDhcpsCfg->pDhcpsIfTbl[loop].ifName);
  457. if (pCIf == NULL)
  458.     return (ERROR);
  459.         if (pCIf->if_mtu == 0)    /* No MTU size given: not attached? */
  460.             return (ERROR);
  461.         if (pCIf->if_mtu < DHCP_MSG_SIZE)
  462.             return (ERROR);
  463.         }
  464.     /*
  465.      * Alter the filter program to check for the correct length values and
  466.      * use the specified UDP destination port and maximum hop count.
  467.      */
  468.       /* IP length must at least equal a DHCP message with 4 option bytes. */
  469.     dhcpfilter [6].k = (DFLTDHCPLEN - DFLTOPTLEN + 4) + UDPHL + IPHL;
  470.     dhcpfilter [14].k = pDhcpsCfg->dhcpSPort;   /* Use actual destination port in test. */
  471.        /* UDP length must at least equal a DHCP message with 4 option bytes. */
  472.     dhcpfilter [16].k = (DFLTDHCPLEN - DFLTOPTLEN + 4) + UDPHL;
  473.     dhcpfilter [18].k = pDhcpsCfg->dhcpMaxHops;   /* Use real maximum hop count. */
  474.     /* Store the interface control information and get each BPF device. */
  475.     for (loop = 0; loop < pDhcpsCfg->numDev; loop++)
  476.         {
  477. pCIf = ifunit (pDhcpsCfg->pDhcpsIfTbl[loop].ifName);
  478.         pIf = (struct if_info *)calloc (1, sizeof (struct if_info));
  479.         if (pIf == NULL) 
  480.             {
  481.             logMsg ("Memory allocation error.n", 0, 0, 0, 0, 0, 0);
  482.             dhcpsCleanup (1); 
  483.             return (ERROR);
  484.             }
  485.         pIf->buf = (char *)memalign (4, dhcpsBufSize);
  486.         if (pIf->buf == NULL)
  487.             {
  488.             logMsg ("Memory allocation error.n", 0, 0, 0, 0, 0, 0);
  489.             dhcpsCleanup (1); 
  490.             return (ERROR);
  491.             }
  492.         bzero (pIf->buf, dhcpsBufSize);
  493. #ifdef VIRTUAL_STACK
  494.         sprintf (bpfDevName, "/bpf/vs%d_dhcps%d", myStackNum, loop);
  495. #else
  496.         sprintf (bpfDevName, "/bpf/dhcps%d", loop);
  497. #endif /* VIRTUAL_STACK */
  498.         bpfDev = open (bpfDevName, 0, 0);
  499.         if (bpfDev < 0)
  500.             {
  501.             logMsg ("BPF device creation error.n", 0, 0, 0, 0, 0, 0);
  502.             dhcpsCleanup (1);
  503.             return (ERROR);
  504.             }
  505.         /* Enable immediate mode for reading messages. */
  506.         result = 1;
  507.         result = ioctl (bpfDev, BIOCIMMEDIATE, (int)&result);
  508.         if (result != 0)
  509.             {
  510.             logMsg ("BPF device creation error.n", 0, 0, 0, 0, 0, 0);
  511.             dhcpsCleanup (1);
  512.             return (ERROR);
  513.             }
  514.         result = ioctl (bpfDev, BIOCSETF, (int)&dhcpread);
  515.         if (result != 0)
  516.             {
  517.             logMsg ("BPF filter assignment error.n", 0, 0, 0, 0, 0, 0);
  518.             dhcpsCleanup (1);
  519.             return (ERROR);
  520.             }
  521.         sprintf (ifreq.ifr_name, "%s", pDhcpsCfg->pDhcpsIfTbl[loop].ifName );
  522.         result = ioctl (bpfDev, BIOCSETIF, (int)&ifreq);
  523.         if (result != 0)
  524.             {
  525.             logMsg ("BPF interface attachment error.n", 0, 0, 0, 0, 0, 0);
  526.             dhcpsCleanup (1);
  527.             return (ERROR);
  528.             }
  529.         pIf->next = dhcpsIntfaceList;
  530.         dhcpsIntfaceList = pIf;
  531.         /*
  532.          * Fill in device name and hardware address using the information
  533.          * set when the driver attached to the IP network protocol.
  534.          */
  535.         sprintf (pIf->name, "%s", pCIf->if_name);
  536.         pIf->unit = pCIf->if_unit;
  537.         pIf->bpfDev = bpfDev;
  538.         if (muxDevExists (pCIf->if_name, pCIf->if_unit) == FALSE)
  539.             pIf->htype = ETHER;
  540.         else
  541.             pIf->htype = dhcpConvert (pCIf->if_type);
  542.         pIf->hlen = pCIf->if_addrlen;
  543.         bcopy ((char *) ((struct arpcom *)pCIf)->ac_enaddr,
  544.                (char *)&pIf->haddr, pIf->hlen); 
  545.         }
  546.     pDhcpsLeasePool = pDhcpsCfg->pDhcpsLeaseTbl;
  547.     pDhcpsRelaySourceTbl = pDhcpsCfg->pDhcpsRelayTbl;
  548.     pDhcpRelayTargetTbl = pDhcpsCfg->pDhcpsTargetTbl;
  549.     /* read address pool databasae */
  550.     status = read_addrpool_db (pDhcpsCfg->dhcpsLeaseTblSize);
  551.     if (status == ERROR) 
  552.         {
  553.         dhcpsCleanup (2); 
  554.         return (ERROR);
  555.         }
  556.     status = read_addrpool_file ();  /* retrieve additional address entries */
  557.     if (status == ERROR)
  558.         {
  559.         dhcpsCleanup (2); 
  560.         return (ERROR);
  561.         }
  562.     status = read_bind_db ();        /* read binding database */
  563.     if (status == ERROR)
  564.         {
  565.         dhcpsCleanup (3);
  566.         return (ERROR);
  567.         }
  568.     /* read database of relay agents */ 
  569.     if (pDhcpsCfg->dhcpsRelayTblSize != 0)
  570.         read_relay_db (pDhcpsCfg->dhcpsRelayTblSize);
  571.     /* read database of DHCP servers */
  572.     if (pDhcpsCfg->dhcpTargetTblSize != 0)
  573.         read_server_db (pDhcpsCfg->dhcpTargetTblSize);
  574.     /* Always use default ports for client and server. */
  575.     dhcps_port = htons (pDhcpsCfg->dhcpSPort);
  576.     dhcpc_port = htons (pDhcpsCfg->dhcpCPort);
  577.     /* Create a normal socket for sending messages across networks. */
  578.     dhcpsIntfaceList->fd = socket (AF_INET, SOCK_DGRAM, 0);
  579.     if (dhcpsIntfaceList->fd < 0)
  580.         {
  581.         dhcpsCleanup (4); 
  582.         return (ERROR);
  583.         }
  584.     /* Read-only socket: disable receives to prevent buffer exhaustion. */
  585.     result = 0;
  586.     if (setsockopt (dhcpsIntfaceList->fd, SOL_SOCKET, SO_RCVBUF,
  587.                     (char *)&result, sizeof (result)) != 0)
  588.         {
  589.         dhcpsCleanup (5); 
  590.         return (ERROR);
  591.         }
  592.     bzero ( (char *)&send_addr, sizeof (send_addr));
  593.     send_addr.sin_family = AF_INET;
  594.     send_addr.sin_addr.s_addr = htonl (INADDR_ANY);
  595.     send_addr.sin_port = dhcps_port;
  596.     status = bind (dhcpsIntfaceList->fd, (struct sockaddr *) &send_addr, 
  597.                    sizeof (send_addr));
  598.     if (status < 0)
  599.         {
  600.         dhcpsCleanup (5);
  601.         return (ERROR);
  602.         }
  603.     /* Fill in subnet mask and IP address for each monitored interface. */
  604.     pIf = dhcpsIntfaceList;
  605.     while (pIf != NULL)
  606.         { 
  607.         if (open_if (pIf) < 0) 
  608.             {
  609.             dhcpsCleanup (5);
  610.             return (ERROR);
  611.             }
  612.         pIf = pIf->next;
  613.         }
  614.     /* Create buffers for outgoing messages. */
  615.     if (alloc_sbuf (pDhcpsCfg->dhcpMaxMsgSize) != OK)
  616.         {
  617.         logMsg ("Error: Couldn't allocate memory.n", 0, 0, 0, 0, 0, 0);
  618.         dhcpsCleanup (5);  
  619.         return (ERROR);
  620.         }
  621.     dhcpsInitialized = TRUE;
  622.     return (OK);
  623.     }
  624. /*******************************************************************************
  625. *
  626. * dhcpsVsInit - Initializes the Virtual Stack Portion of the code
  627. *
  628. * dhcpsVsInit is used to configure the VS specific portion of the DHCP server.
  629. *
  630. * RETURNS: ERROR if it could not allocate the needed memory
  631. *    OK otherwise
  632. *
  633. * NOMANUAL
  634. */
  635. #ifdef VIRTUAL_STACK
  636. STATUS dhcpsVsInit ()
  637.     {
  638.     struct bpf_insn mydhcpfilter[] = DHCPS_FILTER_DEFINE;
  639.     unsigned char mydhcpsCookie[] = RFC1048_MAGIC;
  640.     if (vsTbl[myStackNum]->pDhcpsGlobals && (dhcpsInitialized == TRUE))
  641.  return (OK);
  642.     /* Allocate memory to the dhcps globals in this virtual stack */
  643.     vsTbl[myStackNum]->pDhcpsGlobals = (VS_DHCPS *) KHEAP_ALLOC (sizeof (VS_DHCPS));
  644.     if (vsTbl[myStackNum]->pDhcpsGlobals == (VS_DHCPS *) NULL)
  645.  return (ERROR);
  646.     bzero ((char *)vsTbl[myStackNum]->pDhcpsGlobals, sizeof (VS_DHCPS));
  647.     /* Copy over filter variables */
  648.     memcpy (dhcpfilter, mydhcpfilter, MAX_DHCPFILTERS * sizeof (struct bpf_insn));
  649.     dhcpread.bf_len = MAX_DHCPFILTERS;
  650.     dhcpread.bf_insns = dhcpfilter;
  651.     /* Copy over the magic cookie */
  652.     memcpy (dhcpCookie, mydhcpsCookie, MAGIC_LEN * sizeof (unsigned char));
  653.     return (OK);
  654.     }
  655. #endif /* VIRTUAL_STACK */
  656. /*******************************************************************************
  657. *
  658. * dhcpsCleanup - remove data structures
  659. * This routine frees all dynamically allocated memory obtained by the DHCP 
  660. * server.  It is called at multiple points before the program exits due to
  661. * an error occurring or manual shutdown.  The checkpoint parameter indicates 
  662. * which data structures have been created.
  663. *
  664. * RETURNS: N/A
  665. *
  666. * ERRNO: N/A
  667. *
  668. * NOMANUAL
  669. */
  670. void dhcpsCleanup 
  671.     (
  672.     int checkpoint  /* Progress identifier indicating created resources */
  673.     )
  674.     {
  675.     int current = 0;
  676.     struct if_info *pIf;
  677.     struct dhcp_resource *  pResData;
  678.     struct hash_member *  pListElem;
  679.     struct hash_member *  pHashElem;
  680.     struct hash_tbl *  pHashTbl;
  681.     struct dhcp_binding *  pBindData;
  682.     struct relay_acl *  pRelayData;
  683.     DHCP_SERVER_DESC *  pSrvData;
  684.     int loop;
  685.     semDelete (dhcpsMutexSem);               /* Checkpoint 0 */
  686.     current++;
  687.     if (current > checkpoint)
  688.         return;
  689.                                              /* Checkpoint 1 */
  690.     if (checkpoint >= 5)     /* Close socket descriptor if present.  */
  691.         close (dhcpsIntfaceList->fd);
  692.     while (dhcpsIntfaceList != NULL)
  693.         {
  694.         pIf = dhcpsIntfaceList;
  695.         if (pIf->buf != NULL)
  696.             {
  697.             if (pIf->bpfDev >= 0)
  698.                 close (pIf->bpfDev);
  699.             free (pIf->buf);
  700.             }
  701.         dhcpsIntfaceList = dhcpsIntfaceList->next;
  702.         free (pIf);
  703.         }
  704.     current++;
  705.     if (current > checkpoint)
  706.         return;
  707.    
  708.     while (reslist != NULL)                  /* Checkpoint 2 */
  709.         {
  710.         pListElem = reslist;
  711.         pResData = pListElem->data;
  712.         reslist = reslist->next;
  713.         dhcpsFreeResource (pResData);
  714.         free (pListElem);
  715.         }
  716.     pHashTbl = &nmhashtable;
  717.     for (loop = 0; loop < HASHTBL_SIZE; loop++)
  718.         {
  719.         pHashElem = (pHashTbl->head) [loop];
  720.         while (pHashElem != NULL)
  721.             {
  722.             pListElem = pHashElem;
  723.             pHashElem = pHashElem->next;
  724.             free (pListElem);
  725.             }
  726.         }
  727.     pHashTbl = &iphashtable;
  728.     for (loop = 0; loop < HASHTBL_SIZE; loop++)
  729.         {
  730.         pHashElem = (pHashTbl->head) [loop];
  731.         while (pHashElem != NULL)
  732.             {
  733.             pListElem = pHashElem;
  734.             pHashElem = pHashElem->next;
  735.             free (pListElem);
  736.             }
  737.         }
  738.     /*
  739.      * For the hash table holding additional parameters, also remove ID 
  740.      * records (i.e. bindings), since these are not added to the bindlist.
  741.      */
  742.     pHashTbl = &paramhashtable;
  743.     for (loop = 0; loop < HASHTBL_SIZE; loop++)
  744.         {
  745.         pHashElem = (pHashTbl->head) [loop];
  746.         while (pHashElem != NULL)
  747.             {
  748.             pListElem = pHashElem;
  749.             if (pHashElem->data != NULL)
  750.                 free (pHashElem->data);
  751.             pHashElem = pHashElem->next;
  752.             free (pListElem);
  753.             }
  754.         }
  755.     current++;                      
  756.     if (current > checkpoint)
  757.         return;
  758.     /* Checkpoint 3 */
  759.     if (dhcpsAddressHookRtn != NULL)
  760.         (* dhcpsAddressHookRtn) (DHCPS_STORAGE_STOP, NULL, NULL, NULL, NULL);
  761.     while (bindlist != NULL)
  762.         {
  763.         pListElem = bindlist;
  764.         pBindData = bindlist->data;
  765.         bindlist = bindlist->next;
  766.         free (pBindData);
  767.         free (pListElem);
  768.         }
  769.     pHashTbl = &cidhashtable;
  770.     for (loop = 0; loop < HASHTBL_SIZE; loop++)
  771.         {
  772.         pHashElem = (pHashTbl->head) [loop];
  773.         while (pHashElem != NULL)
  774.             {
  775.             pListElem = pHashElem;
  776.             pHashElem = pHashElem->next;
  777.             free (pListElem);
  778.             }
  779.         }
  780.     current++;
  781.     if (current > checkpoint)
  782.         return;
  783.     pHashTbl = &relayhashtable;             /* Checkpoint 4 */
  784.     for (loop = 0; loop < HASHTBL_SIZE; loop++)
  785.         {
  786.         pHashElem = (pHashTbl->head) [loop];
  787.         while (pHashElem != NULL)
  788.             {
  789.             pListElem = pHashElem;
  790.             pRelayData = pHashElem->data;
  791.             pHashElem = pHashElem->next;
  792.             free (pRelayData);
  793.             free (pListElem);
  794.             }
  795.         }
  796.     /* Remove elements of circular list created by read_server_db(). */
  797.     pSrvData = pDhcpTargetList;
  798.     for (loop = 0; loop < dhcpNumTargets; loop++)
  799.         {
  800.         pDhcpTargetList = pDhcpTargetList->next;
  801.         free (pSrvData);
  802.         }
  803.     current++;
  804.     if (current > checkpoint)
  805.         return;
  806.     /* Checkpoint 5 (close socket) contained in checkpoint 1. */
  807.     current++;
  808.     if (current > checkpoint)
  809.         return;
  810.     free (dhcpsSendBuf);                     /* Checkpoint 6 */
  811.     current++;
  812.     if (current > checkpoint)
  813.         return;
  814.     return;
  815.     }
  816. /*******************************************************************************
  817. *
  818. * void dhcpsFreeResource - remove allocated memory for resource entry
  819. *
  820. * This routine removes any dynamically allocated memory used by the given 
  821. * lease descriptor.  It is called during cleanup before the server shuts down.
  822. *
  823. * RETURNS: N/A
  824. *
  825. * ERRNO: N/A
  826. *
  827. * NOMANUAL
  828. */
  829. void dhcpsFreeResource 
  830.     (
  831.     struct dhcp_resource *pTarget    /* Pointer to resource to remove */
  832.     )
  833.     {
  834.     if (pTarget->mtu_plateau_table.shorts != NULL)
  835.         free (pTarget->mtu_plateau_table.shorts);
  836.     if (pTarget->router.addr != NULL)
  837.         free (pTarget->router.addr);
  838.     if (pTarget->time_server.addr != NULL)
  839.         free (pTarget->time_server.addr);
  840.     if (pTarget->name_server.addr != NULL)
  841.         free (pTarget->name_server.addr);
  842.     if (pTarget->dns_server.addr != NULL)
  843.         free (pTarget->dns_server.addr);
  844.     if (pTarget->log_server.addr != NULL)
  845.         free (pTarget->log_server.addr);
  846.     if (pTarget->cookie_server.addr != NULL)
  847.         free (pTarget->cookie_server.addr);
  848.     if (pTarget->lpr_server.addr != NULL)
  849.         free (pTarget->lpr_server.addr);
  850.     if (pTarget->impress_server.addr != NULL)
  851.         free (pTarget->impress_server.addr);
  852.     if (pTarget->rls_server.addr != NULL)
  853.         free (pTarget->rls_server.addr);
  854.     if (pTarget->nis_server.addr != NULL)
  855.         free (pTarget->nis_server.addr);
  856.     if (pTarget->ntp_server.addr != NULL)
  857.         free (pTarget->ntp_server.addr);
  858.     if (pTarget->nbn_server.addr != NULL)
  859.         free (pTarget->nbn_server.addr);
  860.     if (pTarget->nbdd_server.addr != NULL)
  861.         free (pTarget->nbdd_server.addr);
  862.     if (pTarget->xfont_server.addr != NULL)
  863.         free (pTarget->xfont_server.addr);
  864.     if (pTarget->xdisplay_manager.addr != NULL)
  865.         free (pTarget->xdisplay_manager.addr);
  866.     if (pTarget->nisp_server.addr != NULL)
  867.         free (pTarget->nisp_server.addr);
  868.     if (pTarget->mobileip_ha.addr != NULL)
  869.         free (pTarget->mobileip_ha.addr);
  870.     if (pTarget->smtp_server.addr != NULL)
  871.         free (pTarget->smtp_server.addr);
  872.     if (pTarget->pop3_server.addr != NULL)
  873.         free (pTarget->pop3_server.addr);
  874.     if (pTarget->nntp_server.addr != NULL)
  875.         free (pTarget->nntp_server.addr);
  876.     if (pTarget->dflt_www_server.addr != NULL)
  877.         free (pTarget->dflt_www_server.addr);
  878.     if (pTarget->dflt_finger_server.addr != NULL)
  879.         free (pTarget->dflt_finger_server.addr);
  880.     if (pTarget->dflt_irc_server.addr != NULL)
  881.         free (pTarget->dflt_irc_server.addr);
  882.     if (pTarget->streettalk_server.addr != NULL)
  883.         free (pTarget->streettalk_server.addr);
  884.     if (pTarget->stda_server.addr != NULL)
  885.         free (pTarget->stda_server.addr);
  886.     if (pTarget->policy_filter.addr1 != NULL)
  887.         free (pTarget->policy_filter.addr1);
  888.     if (pTarget->policy_filter.addr2 != NULL)
  889.         free (pTarget->policy_filter.addr2);
  890.     if (pTarget->static_route.addr1 != NULL)
  891.         free (pTarget->static_route.addr1);
  892.     if (pTarget->static_route.addr2 != NULL)
  893.         free (pTarget->static_route.addr2);
  894.     free (pTarget);
  895.     return;
  896.     }
  897. /*******************************************************************************
  898. *
  899. * dhcpsLeaseEntryAdd - add another entry to the address pool
  900. *
  901. * This routine allows the user to add new entries to the address pool without
  902. * rebuilding the VxWorks image.  The routine requires a unique entry name of up
  903. * to eight characters, starting and ending IP addresses, and a colon-separated 
  904. * list of parameters.  Possible values for the parameters are listed in the 
  905. * reference entry for dhcpsLib.  The parameters also determine the type of 
  906. * lease, which the server uses to determine priority when assigning lease 
  907. * addresses.  For examples of the possible lease types, see the reference 
  908. * entry for dhcpsLib.
  909. *
  910. * RETURNS: OK if entry read successfully, or ERROR otherwise.
  911. *
  912. * ERRNO: N/A
  913. */
  914. STATUS dhcpsLeaseEntryAdd
  915.     (
  916.     char * pName,  /* name of lease entry */
  917.     char * pStartIp,  /* first IP address to assign */
  918.     char *  pEndIp,  /* last IP address in assignment range */
  919.     char * pParams  /* formatted string of lease parameters */
  920.     )
  921.     {
  922.     struct dhcp_resource *pResData = NULL;
  923.     DHCPS_ENTRY_DESC entryData;
  924.     struct hash_member *pListElem = NULL;
  925.     int result;
  926.     char tmp [10];  /* sizeof ("tblc=dlft") for host requirements defaults. */
  927.     char entryName [BASE_NAME + 1];   /* User-given name for address range. */
  928.     char newName [MAX_NAME + 1];    /* Unique name for each entry in range. */
  929.     char newAddress [INET_ADDR_LEN];
  930.     struct in_addr nextAddr;
  931.     int len;
  932.     char *pTmp;
  933.     u_long start = 0;
  934.     u_long end = 0;
  935.     u_long loop;
  936.     u_long limit;
  937.     /* Ignore bad values for range. */
  938.     if (pStartIp != NULL && pEndIp == NULL)
  939.         return (ERROR);
  940.     if (pStartIp == NULL && pEndIp != NULL)
  941.         return (ERROR);
  942.     /* If no address specified, just process parameters once. */
  943.     if (pStartIp == NULL && pEndIp == NULL)
  944.         {
  945.         start = 0;
  946.         end = 0;
  947.         }
  948.     else
  949.         {
  950.         start = inet_addr (pStartIp);
  951.         end = inet_addr (pEndIp);
  952.         if (start == ERROR || end == ERROR)
  953.             return (ERROR);
  954.         }
  955.     entryData.pName = newName;
  956.     entryData.pAddress = newAddress;
  957.     entryData.pParams = pParams;
  958.     len = strlen (pName);
  959.     if (len > BASE_NAME)
  960.         {
  961.         bcopy (pName, entryName, BASE_NAME);
  962.         entryName [BASE_NAME] = '';
  963.         }
  964.     else
  965.         {
  966.         bcopy (pName, entryName, len);
  967.         entryName [len] = '';
  968.         }
  969.     limit = ntohl (end);
  970.     for (loop = ntohl (start); loop <= limit; loop++)
  971.         {
  972.         pResData = (struct dhcp_resource *)calloc (1, 
  973.                                                 sizeof (struct dhcp_resource));
  974.         if (pResData == NULL)
  975.             {
  976.             return (ERROR);
  977.             }
  978.         /* Generate a unique name by appending IP address value. */
  979.         sprintf (entryData.pName, "%s%lx", entryName, loop);
  980.         /* Assign current IP address in range. */
  981.         nextAddr.s_addr = htonl (loop);
  982.         inet_ntoa_b (nextAddr, entryData.pAddress);
  983.         /* Critical section with message processing routines. */ 
  984.         semTake (dhcpsMutexSem, WAIT_FOREVER);
  985.  
  986.         if (process_entry (pResData, &entryData) < 0)
  987.             {
  988.             semGive (dhcpsMutexSem);
  989.             dhcpsFreeResource (pResData);
  990.             return (ERROR);
  991.             }
  992.         /* 
  993.          * Add Host Requirements defaults to resource entry. Do not add
  994.          * to entries containing client-specific or class-specific 
  995.          * parameters. 
  996.          */
  997.         if (ISCLR (pResData->valid, S_PARAM_ID) &&
  998.             ISCLR (pResData->valid, S_CLASS_ID))
  999.             {
  1000.             sprintf (tmp, "%s", "tblc=dflt");
  1001.             pTmp = tmp;
  1002.             eval_symbol (&pTmp, pResData);
  1003.             }
  1004.         /* Set default values for entry, if not already assigned. */
  1005.         if (ISSET (pResData->valid, S_IP_ADDR))
  1006.             set_default (pResData);
  1007.         /*
  1008.          * Append entries to lease descriptor list. Exclude entries which
  1009.          * specify additional client- or class-specific parameters.
  1010.          */
  1011.         if (ISCLR (pResData->valid, S_PARAM_ID) && 
  1012.             ISCLR (pResData->valid, S_CLASS_ID))
  1013.             {
  1014.             pListElem = reslist;
  1015.             while (pListElem->next != NULL)
  1016.                 pListElem = pListElem->next; 
  1017.    
  1018.             pListElem->next =
  1019.                  (struct hash_member *)calloc (1, sizeof (struct hash_member));
  1020.             if (pListElem->next == NULL)
  1021.                 {
  1022.                 semGive (dhcpsMutexSem);
  1023.                 dhcpsFreeResource (pResData);
  1024.                 return (ERROR);
  1025.                 }
  1026.             pListElem = pListElem->next;
  1027.             pListElem->next = NULL;
  1028.             pListElem->data = (void *)pResData;
  1029.             /* Add entryname to appropriate hash table. */
  1030.             result = hash_ins (&nmhashtable, pResData->entryname, 
  1031.                                strlen (pResData->entryname), resnmcmp, 
  1032.                                pResData->entryname, pResData);
  1033.             if (result < 0)
  1034.                 {
  1035.                 semGive (dhcpsMutexSem);
  1036.                 return (ERROR);
  1037.                 }
  1038.             if (ISSET (pResData->valid, S_IP_ADDR))
  1039.                 if (hash_ins (&iphashtable, (char *)&pResData->ip_addr.s_addr,
  1040.                               sizeof (u_long), resipcmp, &pResData->ip_addr, 
  1041.                               pResData) < 0)
  1042.                     {
  1043.                     semGive (dhcpsMutexSem);
  1044.                     return (ERROR);
  1045.                     }
  1046.             }
  1047.         semGive (dhcpsMutexSem);
  1048.         }
  1049.     /* Save entry in permanent storage, if hook is provided. */
  1050.     if (dhcpsAddressHookRtn != NULL)
  1051.         (* dhcpsAddressHookRtn) (DHCPS_STORAGE_WRITE, pName,
  1052.                                  pStartIp, pEndIp, pParams);
  1053.     return (OK);
  1054.     }
  1055. /*******************************************************************************
  1056. * dhcpsLeaseHookAdd - assign a permanent lease storage hook for the server
  1057. * This routine allows the server to access some form of permanent storage
  1058. * that it can use to store current lease information across restarts.  The 
  1059. * only argument to dhcpsLeaseHookAdd() is a pointer to a storage routine 
  1060. * with the following interface: 
  1061. * .CS
  1062. *     STATUS dhcpsStorageHook (int op, char *buffer, int datalen);
  1063. * .CE
  1064. * The first parameter of the storage routine specifies one of the following 
  1065. * operations: 
  1066. *     DHCPS_STORAGE_START
  1067. *     DHCPS_STORAGE_READ
  1068. *     DHCPS_STORAGE_WRITE
  1069. *     DHCPS_STORAGE_STOP
  1070. *     DHCPS_STORAGE_CLEAR
  1071. * In response to START, the storage routine should prepare to return data or 
  1072. * overwrite data provided by earlier WRITEs.  For a WRITE the storage routine 
  1073. * must save the contents of the buffer to permanent storage.  For a READ, the 
  1074. * storage routine should copy data previously stored into the provided buffer 
  1075. * as a NULL-terminated string in FIFO order.  For a CLEAR, the storage routine 
  1076. * should discard currently stored data.  After a CLEAR, the READ operation
  1077. * must return ERROR until additional data is stored.  For a STOP, the storage 
  1078. * routine must handle cleanup.  After a STOP, READ and WRITE operations must
  1079. * return error until a START is received.  Each of these operations must 
  1080. * return OK if successful, or ERROR otherwise.
  1081. * Before the server is initialized, VxWorks automatically calls 
  1082. * dhcpsLeaseHookAdd(), passing in the routine name defined by DHCPS_LEASE_HOOK.
  1083. * RETURNS: OK, or ERROR if routine is NULL.
  1084. * ERRNO: N/A
  1085. */
  1086. STATUS dhcpsLeaseHookAdd
  1087.     (
  1088.     FUNCPTR pCacheHookRtn  /* routine to store/retrieve lease records */
  1089.     )
  1090.     {
  1091.     if (pCacheHookRtn != NULL)
  1092.         {
  1093.         dhcpsLeaseHookRtn = pCacheHookRtn;
  1094.         return (OK);
  1095.         }
  1096.     return (ERROR);
  1097.     }
  1098. /*******************************************************************************
  1099. *
  1100. * dhcpsAddressHookAdd - assign a permanent address storage hook for the server
  1101. *
  1102. * This routine allows the server to access some form of permanent storage
  1103. * to preserve additional address entries across restarts.  This routine is
  1104. * not required, but leases using unsaved addresses are not renewed.  The 
  1105. * only argument provided is the name of a function with the following interface:
  1106. * .CS
  1107. *     STATUS dhcpsAddressStorageHook (int op,
  1108. *                                     char *name, char *start, char *end, 
  1109. *                                     char *params);
  1110. * .CE
  1111. * The first parameter of this storage routine specifies one of the following 
  1112. * operations: 
  1113. *
  1114. *     DHCPS_STORAGE_START
  1115. *     DHCPS_STORAGE_READ
  1116. *     DHCPS_STORAGE_WRITE
  1117. *     DHCPS_STORAGE_STOP 
  1118. *
  1119. * In response to a START, the storage routine should prepare to return
  1120. * data or overwrite data provided by earlier WRITE operations.  For a 
  1121. * WRITE, the storage routine must save the contents of the four buffers 
  1122. * to permanent storage.  Those buffers contain the NULL-terminated 
  1123. * strings received by the dhcpsLeaseEntryAdd() routine.  For a READ, the
  1124. * storage routine should copy previously stored data (as NULL-terminated 
  1125. * strings) into the provided buffers in the order received by earlier WRITE
  1126. * operations.  For a STOP, the storage routine should do any necessary cleanup. 
  1127. * After a STOP, the storage routine should return an ERROR for all operations 
  1128. * except START.  However, the STOP operation does not normally occur since
  1129. * the server only deliberately exits following an unrecoverable error.  This
  1130. * storage routine must not rely on that operation to handle READ, WRITE, or
  1131. * new START attempts.
  1132. * The storage routine should return OK if successful, ERROR otherwise.
  1133. *
  1134. * Note that, unlike the lease storage routine, there is no CLEAR operation.
  1135. *
  1136. * Before the server is initialized, VxWorks calls this routine automatically 
  1137. * passing in the function named in DHCPS_ADDRESS_HOOK.
  1138. *
  1139. * RETURNS: OK, or ERROR if function pointer is NULL.
  1140. *
  1141. * ERRNO: N/A
  1142. */
  1143. STATUS dhcpsAddressHookAdd
  1144.     (
  1145.     FUNCPTR pCacheHookRtn  /* routine to store/retrieve lease entries */
  1146.     )
  1147.     {
  1148.     /* 
  1149.      * The hook routine is deliberately assigned before testing for NULL
  1150.      * so that this routine can be used to delete an existing address hook.
  1151.      * In that case, the user would just ignore the return value of ERROR.
  1152.      */
  1153.     dhcpsAddressHookRtn = pCacheHookRtn;
  1154.     if (pCacheHookRtn == NULL)
  1155.         return (ERROR);
  1156.     return (OK);
  1157.     }
  1158. /*******************************************************************************
  1159. *
  1160. * alloc_sbuf - create message transmission buffers
  1161. *
  1162. * This routine creates two transmission buffers for storing outgoing DHCP
  1163. * messages.  The first buffer has a fixed size equal to that of a standard 
  1164. * DHCP message as defined in the RFC.  The second buffer contains the
  1165. * remaining number of bytes needed to send the largest supported message.
  1166. * That buffer is only used if additional space for DHCP options is needed
  1167. * and if the requesting client accepts larger DHCP messages.  The two buffers
  1168. * are stored in a global "buffer vector" structure and are also accessible
  1169. * through individual global variables.
  1170. * RETURNS: N/A
  1171. * ERRNO: N/A
  1172. *
  1173. * NOMANUAL
  1174. */
  1175. LOCAL STATUS alloc_sbuf
  1176.     (
  1177.     int  maxSize  /* largest supported message size, in bytes */
  1178.     )
  1179.     {
  1180.     char *pSendBuf;
  1181.     int sbufsize;
  1182.     /*
  1183.      * Allocate transmission buffer using aligned memory to provide 
  1184.      * IP header alignment needed by Sun BSP's. 
  1185.      */
  1186.     sbufsize = IPHL + UDPHL + DFLTDHCPLEN;
  1187.     pSendBuf = (char *)memalign (4, maxSize);
  1188.     if (pSendBuf == NULL)
  1189.         return (-1);
  1190.     dhcpsSendBuf = pSendBuf;    /* Buffer for default DHCP message. */
  1191.     bzero (dhcpsSendBuf, sbufsize);
  1192.     sbufvec[0].iov_len = IPHL + UDPHL + DFLTDHCPLEN;
  1193.     sbufvec[0].iov_base = dhcpsSendBuf;
  1194.     dhcpsMsgOut.ip = (struct ip *)dhcpsSendBuf;
  1195.     dhcpsMsgOut.udp = (struct udphdr *)&dhcpsSendBuf [IPHL];
  1196.     dhcpsMsgOut.dhcp = (struct dhcp *)&dhcpsSendBuf [IPHL + UDPHL];
  1197.     dhcpsOverflowBuf = &pSendBuf [sbufsize];  /* Buffer for larger messages */
  1198.     sbufvec[1].iov_base = dhcpsOverflowBuf;
  1199.     sbufvec[1].iov_len = 0;   /* Contains length of bytes in use, not size. */
  1200.     return (OK);
  1201.     }