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

VxWorks

开发平台:

C/C++

  1. /* dhcpcCommonLib.c - DHCP client interface shared code library */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02a,26apr02,wap  Update documentation for dhcpcOptionAdd() routine (SPR
  8.                  #73769)
  9. 01z,23apr02,wap  Use BPF_WORDALIGN() when retreiving multiple messages from a
  10.                  BPF buffer (SPR #74215)
  11. 01y,06dec01,wap  Add NPT support
  12. 01x,16nov01,spm  added mod history fix from main branch, ver 01w, base 01v
  13. 01w,15oct01,rae  merge from truestack ver 01z, base 01q (SPR #65264)
  14. 01v,24may01,mil  Bump up dhcp read task stack size to 5000.
  15. 01u,17nov00,spm  added support for BSD Ethernet devices
  16. 01t,16nov00,spm  added required mutual exclusion when sending message
  17. 01s,24oct00,spm  fixed merge from tor3_x branch and updated mod history
  18. 01r,23oct00,niq  merged from version 01w of tor3_x branch (base version 01q);
  19.                  upgrade to BPF replaces tagged frames support
  20. 01q,16mar99,spm  recovered orphaned code from tor1_0_1.sens1_1 (SPR #25770)
  21. 01p,06oct98,spm  fixed copying of parameters with IP address pairs (SPR #22416)
  22. 01o,04dec97,spm  added code review modifications
  23. 01n,06oct97,spm  removed reference to deleted endDriver global; replaced with
  24.                  support for dynamic driver type detection
  25. 01m,30sep97,kbw  fixed minor spelling error in library man page
  26. 01l,02sep97,spm  modified handling of fatal errors - corrected conditions for 
  27.                  disabling network interface and added event hook execution
  28. 01k,26aug97,spm  major overhaul: reorganized code and changed user interface
  29.                  to support multiple leases at runtime
  30. 01j,06aug97,spm  removed parameters linked list to reduce memory required;
  31.                  renamed class field of dhcp_reqspec structure to prevent C++
  32.                  compilation errors (SPR #9079); corrected minor errors in
  33.                  man pages introduced by 01i revision
  34. 01i,30jul97,kbw  fixed man page problems found in beta review
  35. 01h,15jul97,spm  cleaned up man pages
  36. 01g,10jun97,spm  moved length test to prevent buffer overflow and isolated 
  37.                  incoming messages in state machine from input hooks
  38. 01f,02jun97,spm  changed DHCP option tags to prevent name conflicts (SPR #8667)
  39.                  and updated man pages
  40. 01e,06may97,spm  changed memory access to align IP header on four byte boundary
  41. 01d,15apr97,kbw  fixing man page format and wording
  42. 01c,07apr97,spm  added code to use Host Requirements defaults and cleanup 
  43.                  memory on exit, fixed bugs caused by Ethernet trailers, 
  44.                  eliminated potential buffer overruns, rewrote documentation
  45. 01b,29jan97,spm  added END driver support and modified to fit coding standards
  46. 01a,14nov96,spm  created from shared functions of dhcpcLib.c and dhcpcBootLib.c
  47. */
  48. /*
  49. DESCRIPTION
  50. This library contains the shared functions used by the both the run-time
  51. and boot-time portions of the DHCP client.
  52. INCLUDE FILES: dhcpcLib.h
  53. SEE ALSO: dhcpcLib
  54. */
  55. /* includes */
  56. #include "dhcp/copyright_dhcp.h"
  57. #include "vxWorks.h"
  58. #include "wdLib.h"
  59. #include "semLib.h"
  60. #include "intLib.h"
  61. #include "vxLib.h"  /* checksum() declaration */
  62. #include "tickLib.h"  /* tickGet() declaration */
  63. #include "muxLib.h"
  64. #include <stdio.h>
  65. #include <stdlib.h>
  66. #include <unistd.h>
  67. #include <string.h>
  68. #include <errno.h>
  69. #include <signal.h>
  70. #include <fcntl.h>
  71. #include <sys/types.h>
  72. #include <sys/socket.h>
  73. #include <sys/ioctl.h>
  74. #include <net/if.h>
  75. #include <netinet/in.h>
  76. #include <netinet/in_systm.h>
  77. #include <netinet/if_ether.h>
  78. #include <netinet/ip.h>
  79. #include <netinet/udp.h>
  80. #include <arpa/inet.h> 
  81. #include "dhcp/dhcpcCommonLib.h"
  82. #include "dhcp/dhcpcStateLib.h"
  83. #include "dhcp/dhcpc.h"
  84. #include "net/bpf.h"
  85. #include "ipProto.h"
  86. /* defines */
  87. #define _BYTESPERWORD  4  /* Conversion factor for IP header */
  88.      /* Host requirements documents default values. */
  89. #define _HRD_MAX_DGRAM  576     /* Default maximum datagram size. */
  90. #define _HRD_IP_TTL     64      /* Default IP time-to-live (seconds) */
  91. #define _HRD_MTU        576     /* Default interface MTU */
  92. #define _HRD_ROUTER     0xffffffff /* Default router solication */
  93.                                    /* address - 255.255.255.255 */
  94. #define _HRD_ARP_TIME   60      /* Default ARP cache timeout (seconds) */
  95. #define _HRD_TCP_TTL    64      /* Default TCP time-to-live (seconds) */
  96. #define _HRD_TCP_TIME   7200    /* Default TCP keepalive interval (seconds) */
  97. /* globals */
  98. int dhcpcDataSock;  /* Accesses runtime DHCP messages */
  99. BOOL _dhcpcBootFlag = FALSE;  /* Data socket available? (only at runtime) */
  100. int dhcpcReadTaskId;                    /* DHCP message retrieval task */
  101. LEASE_DATA **   dhcpcLeaseList;         /* List of available cookies. */
  102. MESSAGE_DATA *  dhcpcMessageList;       /* Available DHCP messages. */
  103. int dhcpcBufSize;  /* Maximum supported message size */
  104. int dhcpcMaxLeases;  /*
  105.                                  * Set externally when building runtime image
  106.                                  * or to 1 when running boot image.
  107.                                  */
  108. int dhcpcMinLease;  /* Set externally when building image. */
  109. int _dhcpcReadTaskPriority  = 56;      /* Priority level of data retriever */
  110. int _dhcpcReadTaskOptions   = 0;       /* Option settings of data retriever */
  111. int _dhcpcReadTaskStackSize = 5000;    /* Stack size of data retriever */
  112.     /* Berkeley Packet Filter instructions for catching DHCP messages. */
  113. struct bpf_insn dhcpfilter[] = {
  114.   BPF_STMT(BPF_LD+BPF_TYPE,0),                /* Save lltype in accumulator */
  115.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 22),  /* IP packet? */
  116.   /*
  117.    * The remaining statements use the (new) BPF_HLEN alias to avoid any
  118.    * link-layer dependencies. The expected destination port and transaction
  119.    * ID values are altered when necessary by the DHCP routines to match the
  120.    * actual settings.
  121.    */
  122.   BPF_STMT(BPF_LD+BPF_H+BPF_ABS+BPF_HLEN, 6),    /* A <- IP FRAGMENT field */
  123.   BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 20, 0),         /* OFFSET == 0 ? */
  124.   BPF_STMT(BPF_LDX+BPF_HLEN, 0),          /* X <- frame data offset */
  125.   BPF_STMT(BPF_LD+BPF_B+BPF_IND, 9),      /* A <- IP_PROTO field */
  126.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_UDP, 0, 17),     /* UDP ? */
  127.   BPF_STMT(BPF_LD+BPF_HLEN, 0),           /* A <- frame data offset */
  128.   BPF_STMT(BPF_LDX+BPF_B+BPF_MSH+BPF_HLEN, 0), /* X <- IPHDR LEN field */
  129.   BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),     /* A <- start of UDP datagram */
  130.   BPF_STMT(BPF_MISC+BPF_TAX, 0),          /* X <- start of UDP datagram */
  131.   BPF_STMT(BPF_LD+BPF_H+BPF_IND, 2),      /* A <- UDP DSTPORT */
  132.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 68, 0, 11), /* check DSTPORT */
  133.   BPF_STMT(BPF_LD+BPF_H+BPF_ABS+BPF_HLEN, 2),  /* A <- IP LEN field */
  134.   BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 0, 9),    /* Correct IP length? */
  135.   BPF_STMT(BPF_LD+BPF_H+BPF_IND, 4),      /* A <- UDP LEN field */
  136.   BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 0, 7),    /* Correct UDP length? */
  137.   BPF_STMT(BPF_LD+BPF_B+BPF_IND, 8),      /* A <- DHCP op field */
  138.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, BOOTREPLY, 0, 5),
  139.   BPF_STMT(BPF_LD+BPF_W+BPF_IND, 12),      /* A <- DHCP xid field */
  140.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, -1, 0, 3),   /* -1 replaced with real xid */
  141.   BPF_STMT(BPF_LD+BPF_W+BPF_IND, 244),    /* A <- DHCP options */
  142.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x63825363, 0, 1),
  143.                                                  /* Matches magic cookie? */
  144.   BPF_STMT(BPF_RET+BPF_K+BPF_HLEN, DFLTDHCPLEN + UDPHL + IPHL),
  145.                                            /*
  146.                                             * ignore data beyond expected
  147.                                             * size (some drivers add padding).
  148.                                             */
  149.   BPF_STMT(BPF_RET+BPF_K, 0)          /* unrecognized message: ignore frame */
  150.   };
  151. struct bpf_program dhcpread = {
  152.     sizeof (dhcpfilter) / sizeof (struct bpf_insn),
  153.     dhcpfilter
  154.     };
  155. RING_ID dhcpcEventRing;  /* Ring buffer of DHCP events */
  156. SEM_ID dhcpcEventSem;  /* DHCP event notification */
  157. /* forward declarations */
  158. UCHAR * dhcpcOptionMerge (UCHAR, UCHAR *, UCHAR *, int);
  159. UCHAR * dhcpcOptCreate (UCHAR, UCHAR *, UCHAR *, int);
  160. void dhcpcRead (void);                   /* Retrieve incoming DHCP messages */
  161. /*******************************************************************************
  162. *
  163. * dhcpcArpSend - transmit an outgoing ARP message
  164. *
  165. * This routine uses the MUX or netif interface to send a frame containing an
  166. * ARP packet independently of the link level type. 
  167. *
  168. * RETURNS: OK, or ERROR if send fails.
  169. *
  170. * ERRNO: N/A
  171. *
  172. * NOMANUAL
  173. *
  174. * INTERNAL
  175. * Ideally, the dhcpSend() routine would handle any link-level frame
  176. * using the registered output routine (ipOutput in the ipProto.c module).
  177. * However, constructing frames with the link-level broadcast address
  178. * requires significant changes to the MUX/END interface and the ipOutput
  179. * routine which are not backward compatible. This routine extracts
  180. * relevant portions of the ipOutput routine so that only the driver
  181. * layer interface is affected.
  182. */
  183. STATUS dhcpcArpSend
  184.     (
  185.     struct ifnet *      pIf,    /* interface for sending message */
  186.     char *              pData,  /* frame containing ARP packet */
  187.     int                 size  /* length of frame, in bytes */
  188.     )
  189.     {
  190.     u_short etype;
  191.     int s;
  192.     struct mbuf * pMbuf;
  193.     IP_DRV_CTRL* pDrvCtrl;
  194.     struct arpcom *ac = (struct arpcom *)pIf;
  195.     struct ether_header *eh;
  196.     BOOL bsdFlag = FALSE;    /* BSD or END network device? */
  197.     pDrvCtrl = (IP_DRV_CTRL *)pIf->pCookie;
  198.     if (pDrvCtrl == NULL)
  199.         bsdFlag = TRUE;         
  200.     else if (pDrvCtrl->pIpCookie == NULL)
  201.         return (ERROR);
  202.     if ((pIf->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  203.         return (ERROR);
  204.     pMbuf = bcopy_to_mbufs (pData, size, 0, pIf, NONE);
  205.     if (pMbuf == NULL)
  206.         return (ERROR);
  207.     pIf->if_lastchange = tickGet();
  208.     etype = htons (ETHERTYPE_ARP);
  209.     if (bsdFlag)
  210.         {
  211.         /* Build an Ethernet header to the broadcast address. */
  212.         M_PREPEND (pMbuf, sizeof (struct ether_header), M_DONTWAIT);
  213.         if (pMbuf == 0)
  214.             return (ERROR);
  215.         eh = mtod (pMbuf, struct ether_header *);
  216.         pMbuf->mBlkHdr.mFlags |= M_BCAST; /* Always broadcast ARP messages. */
  217.         bcopy((caddr_t)&etype,(caddr_t)&eh->ether_type,
  218.                 sizeof(eh->ether_type));
  219.         bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
  220.               sizeof (etherbroadcastaddr));
  221.         bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
  222.             sizeof(eh->ether_shost));
  223.         } 
  224.     else
  225.         {
  226.         /*
  227.          * Use the MUX interface to build a frame header. We
  228.          * need to handle both END and NPT devices here.
  229.          */
  230.         if (pDrvCtrl->nptFlag)
  231.             {
  232.             if (pIf->if_addrlen)
  233.                 {
  234.                 M_PREPEND(pMbuf, pIf->if_addrlen, M_DONTWAIT);
  235.                 if (pMbuf == NULL)
  236.                     return(ERROR);
  237.                 ((M_BLK_ID)pMbuf)->mBlkPktHdr.rcvif = 0;
  238.                 /* Store the destination address. */
  239.                 bcopy (pDrvCtrl->pDstAddr, pMbuf->m_data, pIf->if_addrlen);
  240.                 }
  241.             /* Save the network protocol type. */
  242.             ((M_BLK_ID)pMbuf)->mBlkHdr.reserved = etype;
  243.             }
  244.         else
  245.             {
  246.             pDrvCtrl->pSrc->m_data = (char *)&ac->ac_enaddr;
  247.             pDrvCtrl->pDst->mBlkHdr.reserved = etype;
  248.             pDrvCtrl->pSrc->mBlkHdr.reserved = etype;
  249.             pMbuf->mBlkHdr.mFlags |= M_BCAST; /* Always broadcast ARP messages. */
  250.             if ((pMbuf = muxLinkHeaderCreate (pDrvCtrl->pIpCookie, pMbuf,
  251.                                               pDrvCtrl->pSrc,
  252.                                               pDrvCtrl->pDst, TRUE)) == NULL)
  253.                 return (ERROR);
  254.             }
  255.         }
  256.     s = splimp();
  257.     /*
  258.      * Queue message on interface, and start output if interface
  259.      * not yet active.
  260.      */
  261.     if (IF_QFULL(&pIf->if_snd))
  262.         {
  263.         IF_DROP(&pIf->if_snd);
  264.         splx(s);
  265.         netMblkClChainFree (pMbuf);
  266.         return (ERROR);
  267.         }
  268.     IF_ENQUEUE(&pIf->if_snd, pMbuf);
  269.     if ((pIf->if_flags & IFF_OACTIVE) == 0)
  270.         (*pIf->if_start)(pIf);
  271.     splx(s);
  272.     pIf->if_obytes += pMbuf->mBlkHdr.mLen;
  273.     if (pMbuf->m_flags & M_MCAST || pMbuf->m_flags & M_BCAST)
  274.         pIf->if_omcasts++;
  275.     return (OK);
  276.     }
  277. /*******************************************************************************
  278. *
  279. * dhcpSend - transmit an outgoing DHCP message
  280. *
  281. * This routine uses the MUX interface to send an IP packet containing a
  282. * DHCP message independently of the link level type. It is derived from
  283. * the ipOutput() routine in the ipProto.c module. It also transmits messages
  284. * for a BSD Ethernet interface.
  285. *
  286. * RETURNS: OK, or ERROR if send fails.
  287. *
  288. * ERRNO: N/A
  289. *
  290. * INTERNAL
  291. * Since the underlying processing performs address resolution, this transmit
  292. * routine is only valid when sending messages to a DHCP participant (such
  293. * as a server or relay agent) with a known IP address. It cannot send
  294. * replies to clients since the hosts will not respond to resolution requests
  295. * for the target IP address if it is not yet assigned.
  296. *
  297. * NOMANUAL
  298. */
  299. STATUS dhcpSend
  300.     (
  301.     struct ifnet *  pIf,    /* interface for sending message */
  302.     struct sockaddr_in *  pDest,  /* destination IP address of message */
  303.     char *  pData,  /* IP packet containing DHCP message */
  304.     int  size,   /* amount of data to send */
  305.     BOOL  broadcastFlag   /* broadcast packet? */
  306.     )
  307.     {
  308.     struct mbuf * pMbuf;
  309.     int result;
  310.     int level;
  311.     pMbuf = bcopy_to_mbufs (pData, size, 0, pIf, NONE);
  312.     if (pMbuf == NULL)
  313.         return (ERROR);
  314.     if (broadcastFlag)
  315.         pMbuf->mBlkHdr.mFlags |= M_BCAST;
  316.     level = splnet ();
  317.     result = pIf->if_output (pIf, pMbuf, (struct sockaddr *)pDest, NULL);
  318.     splx (level);
  319.     if (result)
  320.         return (ERROR);
  321.     return (OK);
  322.     }
  323. /*******************************************************************************
  324. *
  325. * dhcpcRead - handle all incoming DHCP messages
  326. *
  327. * This routine monitors all active BPF devices for new DHCP messages and
  328. * signals the lease monitor task when a valid message arrives. It is the
  329. * entry point for the data retrieval task created during the library
  330. * initialization and should only be called internally.
  331. *
  332. * RETURNS: N/A
  333. *
  334. * ERRNO: N/A
  335. *
  336. * NOMANUAL
  337. */
  338. void dhcpcRead (void)
  339.     {
  340.     STATUS  result;
  341.     EVENT_DATA  newEvent;
  342.     int key;
  343.     char *  pMsgData = NULL;
  344.     BOOL  dataFlag;
  345.     fd_set  readFds;
  346.     int  fileNum = 0;
  347.     int  maxFileNum;
  348.     int  slot = 0;  /* Current buffer for holding messages. */
  349.     int  maxSlot = 10;  /* Matches size of event ring. */
  350.     int  loop;
  351.     int  bufSize = 0;
  352.     struct bpf_hdr *  pMsgHdr;
  353.     int  msglen;
  354.     int  curlen;
  355.     int  totlen;  /* Amount of data in BPF buffer. */
  356.     struct timeval timeout;
  357.     timeout.tv_sec = timeout.tv_usec = 0;
  358.  
  359.     FOREVER
  360.         {
  361.         /*
  362.          * Wait until a message arrives or a new DHCP session is available.
  363.          * The dhcpcInit() routine forces the read task to rebuild the list
  364.          * of active devices by sending an empty message to the selected DHCP
  365.          * client port so that the select routine exits.
  366.          */
  367.         FD_ZERO (&readFds);
  368.         maxFileNum = 0;
  369.         if (!_dhcpcBootFlag)
  370.             {
  371.             /*
  372.              * Runtime DHCP sessions monitor a UDP socket bound to the
  373.              * DHCP port to read and discard messages which were already
  374.              * processed through the Berkeley Packet Filters. This socket
  375.              * also allows the read loop to restart when a new DHCP session
  376.              * begins. The boot time DHCP session is unable to use any
  377.              * sockets since no fully configured devices exist.
  378.              */
  379.             
  380.             FD_SET (dhcpcDataSock, &readFds);
  381.             maxFileNum = dhcpcDataSock;
  382.             }
  383.         /* Create list of active BPF devices for monitoring. */
  384.         for (loop = 0; loop < dhcpcMaxLeases; loop++)
  385.             {
  386.             if (dhcpcLeaseList [loop] != NULL &&
  387.                     dhcpcLeaseList [loop]->initFlag)
  388.                 {
  389.                 fileNum = dhcpcLeaseList [loop]->ifData.bpfDev;
  390.                 FD_SET (fileNum, &readFds);
  391.                 if (fileNum > maxFileNum)
  392.                     maxFileNum = fileNum;
  393.                 }
  394.             }
  395.         /*
  396.          * No BPF devices will be active until a lease session starts
  397.          * which uses an interface without an assigned IP address.
  398.          */
  399.         maxFileNum++;     /* Adjust maximum for select() routine. */
  400.         /*
  401.          * Check for an incoming DHCP message. None may be available
  402.          * if a new session started.
  403.          */
  404.         result = select (maxFileNum, &readFds, NULL, NULL, NULL);
  405.         if (result <= 0)
  406.             continue;
  407.         /*
  408.          * Ignore the message if the current buffer is full. That
  409.          * condition indicates an overflow of the message "ring".
  410.          */
  411.         if (dhcpcMessageList [slot].writeFlag == FALSE)
  412.             continue;
  413.         dhcpcMessageList [slot].writeFlag = FALSE;
  414.         pMsgData = dhcpcMessageList [slot].msgBuffer;
  415.         if (!_dhcpcBootFlag)
  416.             {
  417.             /*
  418.              * For runtime DHCP sessions, read and discard any DHCP
  419.              * messages which reach the socket layer. An (empty)
  420.              * DHCP message is sent to the loopback address when a
  421.              * new session begins. This operation also removes
  422.              * messages which were already handled by the Berkeley
  423.              * Packet Filter, but also reach the socket layer if
  424.              * any device is configured with an IP address. Creating
  425.              * a socket to receive them prevents the transmission of
  426.              * ICMP errors.
  427.              */
  428.             dataFlag = FD_ISSET (dhcpcDataSock, &readFds);
  429.             if (dataFlag)
  430.                 {
  431.                 read (dhcpcDataSock, pMsgData, dhcpcBufSize);
  432.                 dhcpcMessageList [slot].writeFlag = TRUE;
  433.                 continue;
  434.                 }
  435.             }
  436.         /* Read the first available DHCP message. */
  437.         for (loop = 0; loop < dhcpcMaxLeases; loop++)
  438.             {
  439.             if (dhcpcLeaseList [loop]->initFlag)
  440.                 {
  441.                 fileNum = dhcpcLeaseList [loop]->ifData.bpfDev;
  442.                 dataFlag = FD_ISSET (fileNum, &readFds);
  443.                 if (dataFlag)
  444.                     {
  445.                     /*
  446.                      * Any users must read an entire BPF buffer. The size
  447.                      * is set during the initialization for each lease.
  448.                      */
  449.                     bufSize = dhcpcLeaseList [loop]->ifData.bufSize;
  450.                     break;
  451.                     }
  452.                 }
  453.             }
  454.         if (loop == dhcpcMaxLeases)
  455.             {
  456.             /* No DHCP sessions are using the BPF devices. */
  457.             continue;
  458.             }
  459.  
  460.         /*
  461.          * Ignore any read errors. The DHCP protocol is designed to handle
  462.          * any problems with false arrival notifications or invalid messages.
  463.          */
  464.         totlen = read (fileNum, pMsgData, bufSize);
  465.         /* Signal lease monitor for each DHCP message in the BPF buffer. */
  466.         newEvent.source = DHCP_AUTO_EVENT;
  467.         newEvent.type = DHCP_MSG_ARRIVED;
  468.         newEvent.leaseId = dhcpcLeaseList [loop];
  469.         newEvent.slot = slot;
  470.         msglen = curlen = 0;
  471.         pMsgHdr = (struct bpf_hdr *)pMsgData;
  472.         while (curlen < totlen)
  473.             {
  474.             msglen = BPF_WORDALIGN(pMsgHdr->bh_hdrlen + pMsgHdr->bh_caplen);
  475.             curlen += msglen;
  476.             /* Set the pointer to skip the BPF and link level headers. */
  477.             newEvent.pMsg = pMsgData + pMsgHdr->bh_hdrlen +
  478.                                 pMsgHdr->bh_linklen;
  479.             if (curlen < totlen)
  480.                 newEvent.lastFlag = FALSE;
  481.             else
  482.                 newEvent.lastFlag = TRUE;
  483.             /* Lock interrupts to prevent conflicts with timeout thread. */
  484.             key = intLock ();
  485.             rngBufPut (dhcpcEventRing, (char *) &newEvent, sizeof(newEvent));
  486.             intUnlock (key);
  487.             semGive (dhcpcEventSem);
  488.             pMsgData = pMsgData + msglen;
  489.             pMsgHdr = (struct bpf_hdr *)pMsgData;
  490.             }
  491.         /* Advance to next element in message ring. */
  492.         slot = (slot + 1) % maxSlot;
  493.         }
  494.     }
  495. /*******************************************************************************
  496. *
  497. * dhcpcOptionSet - add an option to the option request list
  498. *
  499. * This routine specifies which options the lease indicated by the <pCookie>
  500. * parameter will request from a server.  The <option> parameter specifies an 
  501. * option tag as defined in RFC 2132.  See the dhcp/dhcp.h include file for a
  502. * listing of defined aliases for the available option tags. This routine will
  503. * not accept the following <option> values, which are either used by the
  504. * server for control purposes or only supplied by the client:
  505. *
  506. *     _DHCP_PAD_TAG
  507. *     _DHCP_REQUEST_IPADDR_TAG 
  508. *     _DHCP_LEASE_TIME_TAG  
  509. *     _DHCP_OPT_OVERLOAD_TAG
  510. *     _DHCP_MSGTYPE_TAG
  511. *     _DHCP_SERVER_ID_TAG
  512. *     _DHCP_REQ_LIST_TAG 
  513. *     _DHCP_ERRMSG_TAG 
  514. *     _DHCP_MAXMSGSIZE_TAG
  515. *     _DHCP_CLASS_ID_TAG 
  516. *     _DHCP_CLIENT_ID_TAG 
  517. *     _DHCP_END_TAG
  518. *
  519. * This routine also will not accept <option> values 62 or 63, which are not
  520. * currently defined.
  521. *
  522. * The maximum length of the option field in a DHCP message depends on the
  523. * MTU size of the associated interface and the maximum DHCP message size set
  524. * during the DHCP library initialization. Both the option request list and
  525. * the options sent by the client through the dhcpcOptionAdd() routine share
  526. * that field. Options which exceed the limit will not be stored.
  527. *
  528. * NOTE: The boot program automatically requests all options necessary for
  529. * default target configuration. This routine is only necessary to support
  530. * special circumstances in which additional options are required. Any
  531. * options requested in that case may be retrieved after the runtime image
  532. * has started.
  533. * NOTE: The DHCP specification forbids changing the option request list after
  534. * a lease has been established.  Therefore, this routine must not be used
  535. * after the dhcpcBind() call (in a runtime image) or the dhcpcBootBind() call
  536. * (for a boot image).  Changing the request list at that point could have
  537. * unpredictable results.
  538. *
  539. * NOTE: Options are added directly to outgoing DHCP messages, and numeric
  540. * options (e.g. lease duration time) are expected to be provided in network
  541. * byte order. Care must be taken on little-endian hosts to insure that
  542. * numeric arguments are properly byte-swapped before being passed to this
  543. * routine.
  544. *
  545. * RETURNS: OK if the option was set successfully, or ERROR if the option
  546. * is invalid or storage failed.
  547. *
  548. * ERRNO: S_dhcpcLib_BAD_OPTION, S_dhcpcLib_OPTION_NOT_STORED
  549. *
  550. */
  551. STATUS dhcpcOptionSet
  552.     (
  553.     void *  pCookie,  /* identifier returned by dhcpcInit() */
  554.     int  option /* RFC 2132 tag of desired option */
  555.     )
  556.     {
  557.     LEASE_DATA *   pLeaseData;
  558.     struct dhcp_reqspec *  pReqSpec;
  559.     struct dhcpcOpts *  pOptList;
  560.     int msglen = 0;  /* Length of DHCP message after inserting option */
  561.     /*
  562.      * Use the cookie to access the lease-specific data structures.  For now,
  563.      * just typecast the cookie.  This translation could be replaced with a more
  564.      * sophisticated lookup at some point.
  565.      */
  566.     pLeaseData = (LEASE_DATA *)pCookie;
  567.     pReqSpec = &pLeaseData->leaseReqSpec;
  568.     /* Check for restricted or undefined options. */
  569.     switch (option)
  570.         {
  571.         case _DHCP_PAD_TAG:  /* fall-through */
  572.         case _DHCP_REQUEST_IPADDR_TAG:  /* fall-through */
  573.         case _DHCP_LEASE_TIME_TAG:  /* fall-through */
  574.         case _DHCP_OPT_OVERLOAD_TAG:  /* fall-through */
  575.         case _DHCP_MSGTYPE_TAG:  /* fall-through */
  576.         case _DHCP_SERVER_ID_TAG:  /* fall-through */
  577.         case _DHCP_REQ_LIST_TAG:  /* fall-through */
  578.         case _DHCP_ERRMSG_TAG:  /* fall-through */
  579.         case _DHCP_MAXMSGSIZE_TAG:  /* fall-through */
  580.         case _DHCP_CLASS_ID_TAG:  /* fall-through */
  581.         case _DHCP_CLIENT_ID_TAG:  /* fall-through */
  582.         case _DHCP_END_TAG:
  583.             errno = S_dhcpcLib_BAD_OPTION;
  584.             return (ERROR);
  585.             break;
  586.         default:
  587.             break;
  588.         }
  589.     if (option == 62 || option == 63)
  590.         {
  591.         errno = S_dhcpcLib_BAD_OPTION;
  592.         return (ERROR);
  593.         }
  594.         
  595.     if (option < 0 || option > _DHCP_LAST_OPTION)
  596.         {
  597.         errno = S_dhcpcLib_BAD_OPTION;
  598.         return (ERROR);
  599.         }
  600.     /*
  601.      * Verify that the option won't exceed the MTU size for a message.
  602.      * Start with an initial length equal to the UDP and IP headers and
  603.      * the fixed-length portion of a DHCP message.
  604.      */
  605.     msglen = UDPHL + IPHL + (DFLTDHCPLEN - DFLTOPTLEN);
  606.     /* Include size of existing options and option request list. */
  607.     pOptList = pReqSpec->pOptList;
  608.     if (pOptList)
  609.         msglen += pReqSpec->pOptList->optlen;
  610.     msglen += (pReqSpec->reqlist.len + 1);
  611.     /*
  612.      * Include space for required magic cookie (4 bytes), message
  613.      * type option (3 bytes), maximum message size (4 bytes), and
  614.      * server identifier option (6 bytes).
  615.      */
  616.     msglen += 17;
  617.     /* Include space for required requested IP address option (6 bytes). */
  618.     msglen += 6;
  619.     if (msglen > pReqSpec->maxlen)
  620.         {
  621.         /*
  622.          * Option field is full.  New option would either exceed MTU size
  623.          * or overflow the transmit buffer.
  624.          */
  625.         errno = S_dhcpcLib_OPTION_NOT_STORED;
  626.         return (ERROR);
  627.         }
  628.     pReqSpec->reqlist.list [pReqSpec->reqlist.len++] = option;
  629.     return (OK);
  630.     }
  631. /*******************************************************************************
  632. *
  633. * dhcpcOptionAdd - add an option to the client messages
  634. *
  635. * This routine inserts option tags and associated values into the body of
  636. * all outgoing messages for the lease indicated by the <pCookie> parameter.
  637. * Each lease can accept option data up to the MTU size of the underlying
  638. * interface, minus the link-level header size and the additional 283 bytes
  639. * required for a minimum DHCP message (including mandatory options).
  640. *
  641. * The <option> parameter specifies an option tag defined in RFC 2132. See
  642. * the dhcp/dhcp.h include file for a listing of defined aliases for the
  643. * available option tags. This routine will not accept the following <option>
  644. * values, which are used for control purposes and cannot be included
  645. * arbitrarily:
  646. *
  647. *     _DHCP_PAD_TAG
  648. *     _DHCP_OPT_OVERLOAD_TAG
  649. *     _DHCP_MSGTYPE_TAG
  650. *     _DHCP_SERVER_ID_TAG
  651. *     _DHCP_MAXMSGSIZE_TAG
  652. *     _DHCP_END_TAG
  653. *
  654. * This routine also will not accept <option> values 62 or 63, which are not
  655. * currently defined.
  656. *
  657. * The <length> parameter indicates the number of bytes in the option body
  658. * provided by the <pData> parameter. 
  659. *
  660. * The maximum length of the option field in a DHCP message depends on the
  661. * MTU size of the associated interface and the maximum DHCP message size set
  662. * during the DHCP library initialization. These option settings share that
  663. * field with any option request list created through the dhcpcOptionSet()
  664. * routine. Options which exceed the limit will not be stored.
  665. *
  666. * Each call to this routine with the same <option> value usually replaces
  667. * the value of the existing option, if any. However, the routine will append
  668. * the new data for the <option> values which contain variable length lists,
  669. * corresponding to tags 3-11, 21, 25, 33, 41-45, 48-49, 55, 65, and 68-76.
  670. *
  671. * WARNING: The _DHCP_REQ_LIST_TAG <option> value (55) will replace
  672. * any existing list created with the dhcpcOptionSet() routine.
  673. *
  674. * RETURNS: OK if the option was inserted successfully, or ERROR if the option
  675. * is invalid or storage failed.
  676. *
  677. * ERRNO: S_dhcpcLib_BAD_OPTION, S_dhcpcLib_OPTION_NOT_STORED
  678. *
  679. */
  680. STATUS dhcpcOptionAdd
  681.     (
  682.     void *  pCookie,  /* identifier returned by dhcpcInit() */
  683.     UCHAR  option,  /* RFC 2132 tag of desired option */
  684.     int  length,  /* length of option data */
  685.     UCHAR *  pData  /* option data */
  686.     )
  687.     {
  688.     LEASE_DATA *                pLeaseData;
  689.     struct dhcp_reqspec *       pReqSpec;
  690.     char *  pDest;
  691.     struct dhcpcOpts *  pOptList;
  692.     int msglen = 0;  /* Length of DHCP message after inserting option */
  693.     /*
  694.      * Use the cookie to access the lease-specific data structures.  For now,
  695.      * just typecast the cookie.  This translation could be replaced with a more
  696.      * sophisticated lookup at some point.
  697.      */
  698.     pLeaseData = (LEASE_DATA *)pCookie;
  699.     pReqSpec = &pLeaseData->leaseReqSpec;
  700.     /* Check for restricted or invalid options. */
  701.     switch (option)
  702.         {
  703.         case _DHCP_PAD_TAG:             /* fall-through */
  704.         case _DHCP_OPT_OVERLOAD_TAG:    /* fall-through */
  705.         case _DHCP_MSGTYPE_TAG:         /* fall-through */
  706.         case _DHCP_SERVER_ID_TAG:       /* fall-through */
  707.         case _DHCP_MAXMSGSIZE_TAG:      /* fall-through */
  708.         case _DHCP_END_TAG:
  709.             errno = S_dhcpcLib_BAD_OPTION;
  710.             return (ERROR);
  711.             break;
  712.         default:
  713.             break;
  714.         }
  715.     if (option == 62 || option == 63)
  716.         {
  717.         errno = S_dhcpcLib_BAD_OPTION;
  718.         return (ERROR);
  719.         }
  720.         
  721.     /*
  722.      * Verify that the option won't exceed the MTU size for a message.
  723.      * Start with an initial length equal to the UDP and IP headers and
  724.      * the fixed-length portion of a DHCP message.
  725.      */
  726.     msglen = UDPHL + IPHL + (DFLTDHCPLEN - DFLTOPTLEN);
  727.     /* Include size of existing options and option request list. */
  728.     pOptList = pReqSpec->pOptList;
  729.     if (pOptList)
  730.         msglen += pReqSpec->pOptList->optlen;
  731.     if (option == _DHCP_REQ_LIST_TAG)    /* Replacing request list? */
  732.         msglen -= pReqSpec->reqlist.len;
  733.     else
  734.         msglen += pReqSpec->reqlist.len;
  735.     /*
  736.      * Include space for required magic cookie (4 bytes), message
  737.      * type option (3 bytes), maximum message size (4 bytes), and
  738.      * server identifier option (6 bytes).
  739.      */
  740.     msglen += 17;
  741.     /* Include space for required requested IP address option (6 bytes). */
  742.     msglen += 6;
  743.     /* Add size of any other option (don't double-count IP address). */
  744.     if (option != _DHCP_REQUEST_IPADDR_TAG)
  745.         msglen += length + 2;    /* +2 includes tag and length values */
  746.     if (msglen > dhcpcBufSize)
  747.         {
  748.         /* Option field is full.  New option would overflow transmit buffer. */
  749.         errno = S_dhcpcLib_OPTION_NOT_STORED;
  750.         return (ERROR);
  751.         }
  752.     if (msglen > pReqSpec->maxlen)
  753.         {
  754.         /*
  755.          * Option field is full.  New option would either exceed MTU size
  756.          * or overflow the transmit buffer.
  757.          */
  758.         errno = S_dhcpcLib_OPTION_NOT_STORED;
  759.         return (ERROR);
  760.         }
  761.     if (pData == NULL)
  762.         {
  763.         errno = S_dhcpcLib_BAD_OPTION;
  764.         return (ERROR);
  765.         }
  766.     /* Validate the length of each option. */
  767.     switch (option)
  768.         {
  769.         /* 1 byte values */
  770.         case _DHCP_IP_FORWARD_TAG:  /* Option Tag 19 */
  771.         case _DHCP_NONLOCAL_SRCROUTE_TAG:  /* Option Tag 20 */
  772.         case _DHCP_DEFAULT_IP_TTL_TAG:  /* Option Tag 23 */
  773.         case _DHCP_ALL_SUBNET_LOCAL_TAG:  /* Option Tag 27 */
  774.         case _DHCP_MASK_DISCOVER_TAG:  /* Option Tag 29 */
  775.         case _DHCP_MASK_SUPPLIER_TAG:  /* Option Tag 30 */
  776.         case _DHCP_ROUTER_DISCOVER_TAG:  /* Option Tag 31 */
  777.         case _DHCP_TRAILER_TAG:  /* Option Tag 34 */
  778.         case _DHCP_ETHER_ENCAP_TAG:  /* Option Tag 36 */
  779.         case _DHCP_DEFAULT_TCP_TTL_TAG:  /* Option Tag 37 */
  780.         case _DHCP_KEEPALIVE_GARBAGE_TAG:  /* Option Tag 39 */
  781.         case _DHCP_NB_NODETYPE_TAG:  /* Option Tag 46 */
  782.             if (length != 1)
  783.                 {
  784.                 errno = S_dhcpcLib_BAD_OPTION;
  785.                 return (ERROR);
  786.                 }
  787.             break;
  788.         /* 2 byte values */
  789.         case _DHCP_BOOTSIZE_TAG:  /* Option Tag 13 */
  790.         case _DHCP_MAX_DGRAM_SIZE_TAG:  /* Option Tag 22 */
  791.         case _DHCP_IF_MTU_TAG:  /* Option Tag 26 */
  792.             if (length != 2)
  793.                 {
  794.                 errno = S_dhcpcLib_BAD_OPTION;
  795.                 return (ERROR);
  796.                 }
  797.             break;
  798.         /* 4 byte values */
  799.         case _DHCP_SUBNET_MASK_TAG:  /* Option Tag 1 */
  800.         case _DHCP_TIME_OFFSET_TAG:  /* Option Tag 2 */
  801.         case _DHCP_SWAP_SERVER_TAG:  /* Option Tag 16 */
  802.         case _DHCP_MTU_AGING_TIMEOUT_TAG:  /* Option Tag 24 */
  803.         case _DHCP_BRDCAST_ADDR_TAG:  /* Option Tag 28 */
  804.         case _DHCP_ROUTER_SOLICIT_TAG:  /* Option Tag 32 */
  805.         case _DHCP_ARP_CACHE_TIMEOUT_TAG:  /* Option Tag 35 */
  806.         case _DHCP_KEEPALIVE_INTERVAL_TAG:  /* Option Tag 38 */
  807.         case _DHCP_REQUEST_IPADDR_TAG:  /* Option Tag 50 */
  808.         case _DHCP_LEASE_TIME_TAG:  /* Option Tag 51 */
  809.         case _DHCP_T1_TAG:  /* Option Tag 58 */
  810.         case _DHCP_T2_TAG:  /* Option Tag 59 */
  811.             if (length != 4)
  812.                 {
  813.                 errno = S_dhcpcLib_BAD_OPTION;
  814.                 return (ERROR);
  815.                 }
  816.             break;
  817.         /* Table entries (2 bytes each) */
  818.         case _DHCP_MTU_PLATEAU_TABLE_TAG:  /* Option Tag 25 */
  819.             if (length % 2)
  820.                 {
  821.                 errno = S_dhcpcLib_BAD_OPTION;
  822.                 return (ERROR);
  823.                 }
  824.             break;
  825.         /* Address values (4 bytes each) */
  826.         case _DHCP_ROUTER_TAG:  /* Option Tag 3 */
  827.         case _DHCP_TIME_SERVER_TAG:  /* Option Tag 4 */
  828.         case _DHCP_NAME_SERVER_TAG:  /* Option Tag 5 */
  829.         case _DHCP_DNS_SERVER_TAG:  /* Option Tag 6 */
  830.         case _DHCP_LOG_SERVER_TAG:  /* Option Tag 7 */
  831.         case _DHCP_COOKIE_SERVER_TAG:  /* Option Tag 8 */
  832.         case _DHCP_LPR_SERVER_TAG:  /* Option Tag 9 */
  833.         case _DHCP_IMPRESS_SERVER_TAG:  /* Option Tag 10 */
  834.         case _DHCP_RLS_SERVER_TAG:  /* Option Tag 11 */
  835.         case _DHCP_NIS_SERVER_TAG:  /* Option Tag 41 */
  836.         case _DHCP_NTP_SERVER_TAG:  /* Option Tag 42 */
  837.         case _DHCP_NBN_SERVER_TAG:  /* Option Tag 44 */
  838.         case _DHCP_NBDD_SERVER_TAG:  /* Option Tag 45 */
  839.         case _DHCP_XFONT_SERVER_TAG:  /* Option Tag 48 */
  840.         case _DHCP_XDISPLAY_MANAGER_TAG:  /* Option Tag 49 */
  841.         case _DHCP_NISP_SERVER_TAG:  /* Option Tag 65 */
  842.         case _DHCP_MOBILEIP_HA_TAG:  /* Option Tag 68 */
  843.         case _DHCP_SMTP_SERVER_TAG:  /* Option Tag 69 */
  844.         case _DHCP_POP3_SERVER_TAG:  /* Option Tag 70 */
  845.         case _DHCP_NNTP_SERVER_TAG:  /* Option Tag 71 */
  846.         case _DHCP_DFLT_WWW_SERVER_TAG:  /* Option Tag 72 */
  847.         case _DHCP_DFLT_FINGER_SERVER_TAG:  /* Option Tag 73 */
  848.         case _DHCP_DFLT_IRC_SERVER_TAG:   /* Option Tag 74 */
  849.         case _DHCP_STREETTALK_SERVER_TAG:   /* Option Tag 75 */
  850.         case _DHCP_STDA_SERVER_TAG:  /* Option Tag 76 */
  851.             if (length % 4)
  852.                 {
  853.                 errno = S_dhcpcLib_BAD_OPTION;
  854.                 return (ERROR);
  855.                 }
  856.             break;
  857.         /* Address pairs or address/mask values (8 bytes each). */
  858.         case _DHCP_POLICY_FILTER_TAG:  /* Option Tag 21 */
  859.         case _DHCP_STATIC_ROUTE_TAG:  /* Option Tag 33 */
  860.             if (length % 8)
  861.                 {
  862.                 errno = S_dhcpcLib_BAD_OPTION;
  863.                 return (ERROR);
  864.                 }
  865.             break;
  866.         /* Variable-length values */
  867.         case _DHCP_HOSTNAME_TAG:  /* Option Tag 12 */
  868.         case _DHCP_MERIT_DUMP_TAG:  /* Option Tag 14 */
  869.         case _DHCP_DNS_DOMAIN_TAG:  /* Option Tag 15 */
  870.         case _DHCP_ROOT_PATH_TAG:  /* Option Tag 17 */
  871.         case _DHCP_EXTENSIONS_PATH_TAG:  /* Option Tag 18 */
  872.         case _DHCP_NIS_DOMAIN_TAG:  /* Option Tag 40 */
  873.         case _DHCP_VENDOR_SPEC_TAG:  /* Option Tag 43 */
  874.         case _DHCP_NB_SCOPE_TAG:  /* Option Tag 47 */
  875.         case _DHCP_REQ_LIST_TAG:  /* Option Tag 55 */
  876.         case _DHCP_ERRMSG_TAG:  /* Option Tag 56 */
  877.         case _DHCP_CLASS_ID_TAG:  /* Option Tag 60 */
  878.         case _DHCP_CLIENT_ID_TAG:  /* Option Tag 61 */
  879.         case _DHCP_NISP_DOMAIN_TAG:  /* Option Tag 64 */
  880.         case _DHCP_TFTP_SERVERNAME_TAG:  /* Option Tag 66 */
  881.         case _DHCP_BOOTFILE_TAG:  /* Option Tag 67 */
  882.             if (length < 1 || length > _DHCP_MAX_OPTLEN)
  883.                 {
  884.                 errno = S_dhcpcLib_BAD_OPTION;
  885.                 return (ERROR);
  886.                 }
  887.             break;
  888.         }
  889.     /* Store the option body in the space provided. */
  890.     if (pOptList == NULL)
  891.         {
  892.         pOptList = malloc (sizeof (struct dhcpcOpts));
  893.         if (pOptList == NULL)
  894.             {
  895.             errno = S_dhcpcLib_OPTION_NOT_STORED;
  896.             return (ERROR);
  897.             }
  898.         bzero ( (char *)pOptList, sizeof (struct dhcpcOpts));
  899.         pReqSpec->pOptList = pOptList;
  900.         }
  901.     switch (option)
  902.         {
  903.         /* 1 byte values */
  904.         case _DHCP_IP_FORWARD_TAG:  /* Option Tag 19 */
  905.             pOptList->tag19 = *pData;
  906.             break;    
  907.         case _DHCP_NONLOCAL_SRCROUTE_TAG:  /* Option Tag 20 */
  908.             pOptList->tag20 = *pData;
  909.             break;
  910.         case _DHCP_DEFAULT_IP_TTL_TAG:  /* Option Tag 23 */
  911.             pOptList->tag23 = *pData;
  912.             break;
  913.         case _DHCP_ALL_SUBNET_LOCAL_TAG:  /* Option Tag 27 */
  914.             pOptList->tag27 = *pData;
  915.             break;
  916.         case _DHCP_MASK_DISCOVER_TAG:  /* Option Tag 29 */
  917.             pOptList->tag29 = *pData;
  918.             break;
  919.         case _DHCP_MASK_SUPPLIER_TAG:  /* Option Tag 30 */
  920.             pOptList->tag30 = *pData;
  921.             break;
  922.         case _DHCP_ROUTER_DISCOVER_TAG:  /* Option Tag 31 */
  923.             pOptList->tag31 = *pData;
  924.             break;
  925.         case _DHCP_TRAILER_TAG:  /* Option Tag 34 */
  926.             pOptList->tag34 = *pData;
  927.             break;
  928.         case _DHCP_ETHER_ENCAP_TAG:  /* Option Tag 36 */
  929.             pOptList->tag36 = *pData;
  930.             break;
  931.         case _DHCP_DEFAULT_TCP_TTL_TAG:  /* Option Tag 37 */
  932.             pOptList->tag37 = *pData;
  933.             break;
  934.         case _DHCP_KEEPALIVE_GARBAGE_TAG:  /* Option Tag 39 */
  935.             pOptList->tag39 = *pData;
  936.             break;
  937.         case _DHCP_NB_NODETYPE_TAG:  /* Option Tag 46 */
  938.             pOptList->tag46 = *pData;
  939.             break;
  940.         /* 2 byte values */
  941.         case _DHCP_BOOTSIZE_TAG:  /* Option Tag 13 */
  942.             bcopy (pData, (char *)&pOptList->tag13, sizeof (USHORT));
  943.             break;
  944.         case _DHCP_MAX_DGRAM_SIZE_TAG:  /* Option Tag 22 */
  945.             bcopy (pData, (char *)&pOptList->tag22, sizeof (USHORT));
  946.             break;
  947.         case _DHCP_IF_MTU_TAG:  /* Option Tag 26 */
  948.             bcopy (pData, (char *)&pOptList->tag26, sizeof (USHORT));
  949.             break;
  950.         /* 4 byte values */
  951.         case _DHCP_SUBNET_MASK_TAG:  /* Option Tag 1 */
  952.             bcopy (pData, (char *)&pOptList->tag1, sizeof (ULONG));
  953.             break;
  954.         case _DHCP_TIME_OFFSET_TAG:  /* Option Tag 2 */
  955.             bcopy (pData, (char *)&pOptList->tag2, sizeof (long));
  956.             break;
  957.         case _DHCP_SWAP_SERVER_TAG:  /* Option Tag 16 */
  958.             bcopy (pData, (char *)&pOptList->tag16, sizeof (ULONG));
  959.             break;
  960.         case _DHCP_MTU_AGING_TIMEOUT_TAG:  /* Option Tag 24 */
  961.             bcopy (pData, (char *)&pOptList->tag24, sizeof (ULONG));
  962.             break;
  963.         case _DHCP_BRDCAST_ADDR_TAG:  /* Option Tag 28 */
  964.             bcopy (pData, (char *)&pOptList->tag28, sizeof (ULONG));
  965.             break;
  966.         case _DHCP_ROUTER_SOLICIT_TAG:  /* Option Tag 32 */
  967.             bcopy (pData, (char *)&pOptList->tag32, sizeof (ULONG));
  968.             break;
  969.         case _DHCP_ARP_CACHE_TIMEOUT_TAG:  /* Option Tag 35 */
  970.             bcopy (pData, (char *)&pOptList->tag35, sizeof (ULONG));
  971.             break;
  972.         case _DHCP_KEEPALIVE_INTERVAL_TAG:  /* Option Tag 38 */
  973.             bcopy (pData, (char *)&pOptList->tag38, sizeof (ULONG));
  974.             break;
  975.         case _DHCP_REQUEST_IPADDR_TAG:  /* Option Tag 50 */
  976.             /*
  977.              * This option is stored separately since it is not
  978.              * always included in the client's initial message.
  979.              */
  980.             bcopy (pData, (char *)&pReqSpec->ipaddr.s_addr, sizeof (ULONG));
  981.             break;
  982.         case _DHCP_LEASE_TIME_TAG:  /* Option Tag 51 */
  983.             bcopy (pData, (char *)&pOptList->tag51, sizeof (ULONG));
  984.             break;
  985.         case _DHCP_T1_TAG:  /* Option Tag 58 */
  986.             bcopy (pData, (char *)&pOptList->tag58, sizeof (ULONG));
  987.             break;
  988.         case _DHCP_T2_TAG:  /* Option Tag 59 */
  989.             bcopy (pData, (char *)&pOptList->tag59, sizeof (ULONG));
  990.             break;
  991.         /*
  992.          * Variable-length lists. Add new entry or merge.
  993.          * Store tag value and length before option body.
  994.          */
  995.         case _DHCP_MTU_PLATEAU_TABLE_TAG:  /* Option Tag 25 */
  996.             pDest = dhcpcOptionMerge (option, pOptList->pTag25, pData, length);
  997.             if (pDest == NULL)
  998.                 {
  999.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1000.                 return (ERROR);
  1001.                 }
  1002.             else
  1003.                 pOptList->pTag25 = pDest;
  1004.             break;
  1005.         case _DHCP_ROUTER_TAG:  /* Option Tag 3 */
  1006.             pDest = dhcpcOptionMerge (option, pOptList->pTag3, pData, length);
  1007.             if (pDest == NULL)
  1008.                 {
  1009.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1010.                 return (ERROR);
  1011.                 }
  1012.             else
  1013.                 pOptList->pTag3 = pDest;
  1014.             break;
  1015.         case _DHCP_TIME_SERVER_TAG:  /* Option Tag 4 */
  1016.             pDest = dhcpcOptionMerge (option, pOptList->pTag4, pData, length);
  1017.             if (pDest == NULL)
  1018.                 {
  1019.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1020.                 return (ERROR);
  1021.                 }
  1022.             else
  1023.                 pOptList->pTag4 = pDest;
  1024.             break;
  1025.         case _DHCP_NAME_SERVER_TAG:  /* Option Tag 5 */
  1026.             pDest = dhcpcOptionMerge (option, pOptList->pTag5, pData, length);
  1027.             if (pDest == NULL)
  1028.                 {
  1029.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1030.                 return (ERROR);
  1031.                 }
  1032.             else
  1033.                 pOptList->pTag5 = pDest;
  1034.             break;
  1035.         case _DHCP_DNS_SERVER_TAG:  /* Option Tag 6 */
  1036.             pDest = dhcpcOptionMerge (option, pOptList->pTag6, pData, length);
  1037.             if (pDest == NULL)
  1038.                 {
  1039.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1040.                 return (ERROR);
  1041.                 }
  1042.             else
  1043.                 pOptList->pTag6 = pDest;
  1044.             break;
  1045.         case _DHCP_LOG_SERVER_TAG:  /* Option Tag 7 */
  1046.             pDest = dhcpcOptionMerge (option, pOptList->pTag7, pData, length);
  1047.             if (pDest == NULL)
  1048.                 {
  1049.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1050.                 return (ERROR);
  1051.                 }
  1052.             else
  1053.                 pOptList->pTag7 = pDest;
  1054.             break;
  1055.         case _DHCP_COOKIE_SERVER_TAG:  /* Option Tag 8 */
  1056.             pDest = dhcpcOptionMerge (option, pOptList->pTag8, pData, length);
  1057.             if (pDest == NULL)
  1058.                 {
  1059.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1060.                 return (ERROR);
  1061.                 }
  1062.             else
  1063.                 pOptList->pTag8 = pDest;
  1064.             break;
  1065.         case _DHCP_LPR_SERVER_TAG:  /* Option Tag 9 */
  1066.             pDest = dhcpcOptionMerge (option, pOptList->pTag9, pData, length);
  1067.             if (pDest == NULL)
  1068.                 {
  1069.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1070.                 return (ERROR);
  1071.                 }
  1072.             else
  1073.                 pOptList->pTag9 = pDest;
  1074.             break;
  1075.         case _DHCP_IMPRESS_SERVER_TAG:  /* Option Tag 10 */
  1076.             pDest = dhcpcOptionMerge (option, pOptList->pTag10, pData, length);
  1077.             if (pDest == NULL)
  1078.                 {
  1079.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1080.                 return (ERROR);
  1081.                 }
  1082.             else
  1083.                 pOptList->pTag10 = pDest;
  1084.             break;
  1085.         case _DHCP_RLS_SERVER_TAG:  /* Option Tag 11 */
  1086.             pDest = dhcpcOptionMerge (option, pOptList->pTag11, pData, length);
  1087.             if (pDest == NULL)
  1088.                 {
  1089.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1090.                 return (ERROR);
  1091.                 }
  1092.             else
  1093.                 pOptList->pTag11 = pDest;
  1094.             break;
  1095.         case _DHCP_NIS_SERVER_TAG:  /* Option Tag 41 */
  1096.             pDest = dhcpcOptionMerge (option, pOptList->pTag41, pData, length);
  1097.             if (pDest == NULL)
  1098.                 {
  1099.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1100.                 return (ERROR);
  1101.                 }
  1102.             else
  1103.                 pOptList->pTag41 = pDest;
  1104.             break;
  1105.         case _DHCP_NTP_SERVER_TAG:  /* Option Tag 42 */
  1106.             pDest = dhcpcOptionMerge (option, pOptList->pTag42, pData, length);
  1107.             if (pDest == NULL)
  1108.                 {
  1109.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1110.                 return (ERROR);
  1111.                 }
  1112.             else
  1113.                 pOptList->pTag42 = pDest;
  1114.             break;
  1115.         case _DHCP_NBN_SERVER_TAG:  /* Option Tag 44 */
  1116.             pDest = dhcpcOptionMerge (option, pOptList->pTag44, pData, length);
  1117.             if (pDest == NULL)
  1118.                 {
  1119.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1120.                 return (ERROR);
  1121.                 }
  1122.             else
  1123.                 pOptList->pTag44 = pDest;
  1124.             break;
  1125.         case _DHCP_NBDD_SERVER_TAG:  /* Option Tag 45 */
  1126.             pDest = dhcpcOptionMerge (option, pOptList->pTag45, pData, length);
  1127.             if (pDest == NULL)
  1128.                 {
  1129.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1130.                 return (ERROR);
  1131.                 }
  1132.             else
  1133.                 pOptList->pTag45 = pDest;
  1134.             break;
  1135.         case _DHCP_XFONT_SERVER_TAG:  /* Option Tag 48 */
  1136.             pDest = dhcpcOptionMerge (option, pOptList->pTag48, pData, length);
  1137.             if (pDest == NULL)
  1138.                 {
  1139.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1140.                 return (ERROR);
  1141.                 }
  1142.             else
  1143.                 pOptList->pTag48 = pDest;
  1144.             break;
  1145.         case _DHCP_XDISPLAY_MANAGER_TAG:  /* Option Tag 49 */
  1146.             pDest = dhcpcOptionMerge (option, pOptList->pTag49, pData, length);
  1147.             if (pDest == NULL)
  1148.                 {
  1149.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1150.                 return (ERROR);
  1151.                 }
  1152.             else
  1153.                 pOptList->pTag49 = pDest;
  1154.             break;
  1155.         case _DHCP_NISP_SERVER_TAG:  /* Option Tag 65 */
  1156.             pDest = dhcpcOptionMerge (option, pOptList->pTag65, pData, length);
  1157.             if (pDest == NULL)
  1158.                 {
  1159.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1160.                 return (ERROR);
  1161.                 }
  1162.             else
  1163.                 pOptList->pTag65 = pDest;
  1164.             break;
  1165.         case _DHCP_MOBILEIP_HA_TAG:  /* Option Tag 68 */
  1166.             pDest = dhcpcOptionMerge (option, pOptList->pTag68, pData, length);
  1167.             if (pDest == NULL)
  1168.                 {
  1169.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1170.                 return (ERROR);
  1171.                 }
  1172.             else
  1173.                 pOptList->pTag68 = pDest;
  1174.             break;
  1175.         case _DHCP_SMTP_SERVER_TAG:  /* Option Tag 69 */
  1176.             pDest = dhcpcOptionMerge (option, pOptList->pTag69, pData, length);
  1177.             if (pDest == NULL)
  1178.                 {
  1179.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1180.                 return (ERROR);
  1181.                 }
  1182.             else
  1183.                 pOptList->pTag69 = pDest;
  1184.             break;
  1185.         case _DHCP_POP3_SERVER_TAG:  /* Option Tag 70 */
  1186.             pDest = dhcpcOptionMerge (option, pOptList->pTag70, pData, length);
  1187.             if (pDest == NULL)
  1188.                 {
  1189.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1190.                 return (ERROR);
  1191.                 }
  1192.             else
  1193.                 pOptList->pTag70 = pDest;
  1194.             break;
  1195.         case _DHCP_NNTP_SERVER_TAG:  /* Option Tag 71 */
  1196.             pDest = dhcpcOptionMerge (option, pOptList->pTag71, pData, length);
  1197.             if (pDest == NULL)
  1198.                 {
  1199.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1200.                 return (ERROR);
  1201.                 }
  1202.             else
  1203.                 pOptList->pTag71 = pDest;
  1204.             break;
  1205.         case _DHCP_DFLT_WWW_SERVER_TAG:  /* Option Tag 72 */
  1206.             pDest = dhcpcOptionMerge (option, pOptList->pTag72, pData, length);
  1207.             if (pDest == NULL)
  1208.                 {
  1209.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1210.                 return (ERROR);
  1211.                 }
  1212.             else
  1213.                 pOptList->pTag72 = pDest;
  1214.             break;
  1215.         case _DHCP_DFLT_FINGER_SERVER_TAG:  /* Option Tag 73 */
  1216.             pDest = dhcpcOptionMerge (option, pOptList->pTag73, pData, length);
  1217.             if (pDest == NULL)
  1218.                 {
  1219.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1220.                 return (ERROR);
  1221.                 }
  1222.             else
  1223.                 pOptList->pTag73 = pDest;
  1224.             break;
  1225.         case _DHCP_DFLT_IRC_SERVER_TAG:   /* Option Tag 74 */
  1226.             pDest = dhcpcOptionMerge (option, pOptList->pTag74, pData, length);
  1227.             if (pDest == NULL)
  1228.                 {
  1229.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1230.                 return (ERROR);
  1231.                 }
  1232.             else
  1233.                 pOptList->pTag74 = pDest;
  1234.             break;
  1235.         case _DHCP_STREETTALK_SERVER_TAG:   /* Option Tag 75 */
  1236.             pDest = dhcpcOptionMerge (option, pOptList->pTag75, pData, length);
  1237.             if (pDest == NULL)
  1238.                 {
  1239.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1240.                 return (ERROR);
  1241.                 }
  1242.             else
  1243.                 pOptList->pTag75 = pDest;
  1244.             break;
  1245.         case _DHCP_STDA_SERVER_TAG:  /* Option Tag 76 */
  1246.             pDest = dhcpcOptionMerge (option, pOptList->pTag76, pData, length);
  1247.             if (pDest == NULL)
  1248.                 {
  1249.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1250.                 return (ERROR);
  1251.                 }
  1252.             else
  1253.                 pOptList->pTag76 = pDest;
  1254.             break;
  1255.         case _DHCP_POLICY_FILTER_TAG:  /* Option Tag 21 */
  1256.             pDest = dhcpcOptionMerge (option, pOptList->pTag21, pData, length);
  1257.             if (pDest == NULL)
  1258.                 {
  1259.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1260.                 return (ERROR);
  1261.                 }
  1262.             else
  1263.                 pOptList->pTag21 = pDest;
  1264.             break;
  1265.         case _DHCP_STATIC_ROUTE_TAG:  /* Option Tag 33 */
  1266.             pDest = dhcpcOptionMerge (option, pOptList->pTag33, pData, length);
  1267.             if (pDest == NULL)
  1268.                 {
  1269.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1270.                 return (ERROR);
  1271.                 }
  1272.             else
  1273.                 pOptList->pTag33 = pDest;
  1274.             break;
  1275.         case _DHCP_VENDOR_SPEC_TAG:  /* Option Tag 43 */
  1276.             pDest = dhcpcOptionMerge (option, pOptList->pTag43, pData, length);
  1277.             if (pDest == NULL)
  1278.                 {
  1279.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1280.                 return (ERROR);
  1281.                 }
  1282.             else
  1283.                 pOptList->pTag43 = pDest;
  1284.             break;
  1285.         case _DHCP_REQ_LIST_TAG:  /* Option Tag 55 */
  1286.             pDest = dhcpcOptionMerge (option, pOptList->pTag55, pData, length);
  1287.             if (pDest == NULL)
  1288.                 {
  1289.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1290.                 return (ERROR);
  1291.                 }
  1292.             else
  1293.                 {
  1294.                 /* Add new list. Ignore dhcpcOptionSet() routine results. */
  1295.                 pReqSpec->reqlist.len = 0;
  1296.                 pOptList->pTag55 = pDest;
  1297.                 }
  1298.             break;
  1299.         /*
  1300.          * Variable-length values. Add new entry or replace existing one.
  1301.          * Store tag value and length before option body.
  1302.          */
  1303.         case _DHCP_HOSTNAME_TAG:  /* Option Tag 12 */
  1304.             pDest = dhcpcOptCreate (option, pOptList->pTag12, pData, length);
  1305.             if (pDest == NULL)
  1306.                 {
  1307.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1308.                 return (ERROR);
  1309.                 }
  1310.             else
  1311.                 pOptList->pTag12 = pDest;
  1312.             break;
  1313.         case _DHCP_MERIT_DUMP_TAG:  /* Option Tag 14 */
  1314.             pDest = dhcpcOptCreate (option, pOptList->pTag14, pData, length);
  1315.             if (pDest == NULL)
  1316.                 {
  1317.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1318.                 return (ERROR);
  1319.                 }
  1320.             else
  1321.                 pOptList->pTag14 = pDest;
  1322.             break;
  1323.         case _DHCP_DNS_DOMAIN_TAG:  /* Option Tag 15 */
  1324.             pDest = dhcpcOptCreate (option, pOptList->pTag15, pData, length);
  1325.             if (pDest == NULL)
  1326.                 {
  1327.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1328.                 return (ERROR);
  1329.                 }
  1330.             else
  1331.                 pOptList->pTag15 = pDest;
  1332.             break;
  1333.         case _DHCP_ROOT_PATH_TAG:  /* Option Tag 17 */
  1334.             pDest = dhcpcOptCreate (option, pOptList->pTag17, pData, length);
  1335.             if (pDest == NULL)
  1336.                 {
  1337.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1338.                 return (ERROR);
  1339.                 }
  1340.             else
  1341.                 pOptList->pTag17 = pDest;
  1342.             break;
  1343.         case _DHCP_EXTENSIONS_PATH_TAG:  /* Option Tag 18 */
  1344.             pDest = dhcpcOptCreate (option, pOptList->pTag18, pData, length);
  1345.             if (pDest == NULL)
  1346.                 {
  1347.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1348.                 return (ERROR);
  1349.                 }
  1350.             else
  1351.                 pOptList->pTag18 = pDest;
  1352.             break;
  1353.         case _DHCP_NIS_DOMAIN_TAG:  /* Option Tag 40 */
  1354.             pDest = dhcpcOptCreate (option, pOptList->pTag40, pData, length);
  1355.             if (pDest == NULL)
  1356.                 {
  1357.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1358.                 return (ERROR);
  1359.                 }
  1360.             else
  1361.                 pOptList->pTag40 = pDest;
  1362.             break;
  1363.         case _DHCP_NB_SCOPE_TAG:  /* Option Tag 47 */
  1364.             pDest = dhcpcOptCreate (option, pOptList->pTag47, pData, length);
  1365.             if (pDest == NULL)
  1366.                 {
  1367.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1368.                 return (ERROR);
  1369.                 }
  1370.             else
  1371.                 pOptList->pTag47 = pDest;
  1372.             break;
  1373.         case _DHCP_ERRMSG_TAG:  /* Option Tag 56 */
  1374.             pDest = dhcpcOptCreate (option, pOptList->pTag56, pData, length);
  1375.             if (pDest == NULL)
  1376.                 {
  1377.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1378.                 return (ERROR);
  1379.                 }
  1380.             else
  1381.                 pOptList->pTag56 = pDest;
  1382.             break;
  1383.         case _DHCP_CLASS_ID_TAG:  /* Option Tag 60 */
  1384.             pDest = dhcpcOptCreate (option, pOptList->pTag60, pData, length);
  1385.             if (pDest == NULL)
  1386.                 {
  1387.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1388.                 return (ERROR);
  1389.                 }
  1390.             else
  1391.                 pOptList->pTag60 = pDest;
  1392.             break;
  1393.         case _DHCP_CLIENT_ID_TAG:  /* Option Tag 61 */
  1394.             /*
  1395.              * This option is also stored separately since it is included
  1396.              * independently in DECLINE and RELEASE messages.
  1397.              */
  1398.             if (pReqSpec->clid == NULL)
  1399.                 {
  1400.                 pReqSpec->clid = malloc (sizeof (struct client_id));
  1401.                 if (pReqSpec->clid == NULL)
  1402.                     {
  1403.                     errno = S_dhcpcLib_OPTION_NOT_STORED;
  1404.                     return (ERROR);
  1405.                     }
  1406.                 bzero ( (char *)pReqSpec->clid, sizeof (struct client_id));
  1407.                 }
  1408.             if (pReqSpec->clid->id != NULL)
  1409.                 free (pReqSpec->clid->id);
  1410.             pReqSpec->clid->id = malloc (length * sizeof (char));
  1411.             if (pReqSpec->clid->id == NULL)
  1412.                 {
  1413.                 free (pReqSpec->clid);
  1414.                 pReqSpec->clid = NULL;
  1415.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1416.                 return (ERROR);
  1417.                 }
  1418.             bcopy (pData, pReqSpec->clid->id, length);
  1419.             pReqSpec->clid->len = length;
  1420.             pDest = dhcpcOptCreate (option, pOptList->pTag61, pData, length);
  1421.             if (pDest == NULL)
  1422.                 {
  1423.                 free (pReqSpec->clid->id);
  1424.                 free (pReqSpec->clid);
  1425.                 pReqSpec->clid = NULL;
  1426.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1427.                 return (ERROR);
  1428.                 }
  1429.             else
  1430.                 pOptList->pTag61 = pDest;
  1431.             break;
  1432.         case _DHCP_NISP_DOMAIN_TAG:  /* Option Tag 64 */
  1433.             pDest = dhcpcOptCreate (option, pOptList->pTag64, pData, length);
  1434.             if (pDest == NULL)
  1435.                 {
  1436.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1437.                 return (ERROR);
  1438.                 }
  1439.             else
  1440.                 pOptList->pTag64 = pDest;
  1441.             break;
  1442.         case _DHCP_TFTP_SERVERNAME_TAG:  /* Option Tag 66 */
  1443.             pDest = dhcpcOptCreate (option, pOptList->pTag66, pData, length);
  1444.             if (pDest == NULL)
  1445.                 {
  1446.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1447.                 return (ERROR);
  1448.                 }
  1449.             else
  1450.                 pOptList->pTag66 = pDest;
  1451.             break;
  1452.         case _DHCP_BOOTFILE_TAG:  /* Option Tag 67 */
  1453.             pDest = dhcpcOptCreate (option, pOptList->pTag67, pData, length);
  1454.             if (pDest == NULL)
  1455.                 {
  1456.                 errno = S_dhcpcLib_OPTION_NOT_STORED;
  1457.                 return (ERROR);
  1458.                 }
  1459.             else
  1460.                 pOptList->pTag67 = pDest;
  1461.             break;
  1462.         }
  1463.     pReqSpec->pOptList->optlen += length + 2;
  1464.     SETBIT (pOptList->optmask, option);
  1465.     return (OK);
  1466.     }
  1467. /*******************************************************************************
  1468. *
  1469. * dhcpcOptionMerge - combine options into a single body
  1470. *
  1471. * The dhcpcOptionAdd() routine uses this routine to extend an existing option
  1472. * body, if any, with new data. This merge operation is required when the same
  1473. * option is inserted more than once for a given tag. If no option currently
  1474. * exists, this routine just creates the new option subfield. The <pOrig>
  1475. * parameter contains the current option subfield, or NULL if none exists yet.
  1476. * The <pData> parameter contains <length> bytes of additional option data.
  1477. *
  1478. * RETURNS: Pointer to new option subfield, or NULL if error occurs.
  1479. *
  1480. * NOMANUAL
  1481. */
  1482. UCHAR * dhcpcOptionMerge
  1483.     (
  1484.     UCHAR option,  /* RFC 2132 tag of desired option */
  1485.     UCHAR *  pOrig,  /* current option subfield, or NULL if none */
  1486.     UCHAR *  pData,  /* additional/first option body */
  1487.     int  length  /* amount of new data */
  1488.     )
  1489.     {
  1490.     int optlen;  /* Size of current subfield */
  1491.     int newlen;  /* Size of new subfield */
  1492.     UCHAR * pDest;
  1493.     if (pOrig != NULL)
  1494.         optlen = * (pOrig + 1);
  1495.     else
  1496.         optlen = 0;
  1497.     optlen += 2;  /* Adjust for tag and length values. */
  1498.     newlen = optlen + length;
  1499.     if (newlen > 255)  /* Merged option exceeds maximum length. */
  1500.         return (NULL);
  1501.     pDest = malloc (newlen);
  1502.     if (pDest != NULL)
  1503.         {
  1504.         if (pOrig != NULL)
  1505.             {
  1506.             bcopy (pOrig, pDest, optlen);
  1507.             free (pOrig);
  1508.             }
  1509.         else
  1510.             *pDest = option;
  1511.         * (pDest + 1) = newlen;    /* Update length field to new value. */
  1512.         bcopy (pData, pDest + optlen, length);
  1513.         }
  1514.     return (pDest);
  1515.     }
  1516. /*******************************************************************************
  1517. *
  1518. * dhcpcOptCreate - generate a new subfield for variable-length options
  1519. *
  1520. * The dhcpcOptionAdd() routine uses this routine to create or replace an
  1521. * option subfield. The <pOrig> parameter contains the current option subfield,
  1522. * or NULL if none exists yet. The <pData> parameter contains <length> bytes of
  1523. * option data for the new (or initial) subfield.
  1524. *
  1525. * RETURNS: Pointer to new option subfield, or NULL if error occurs.
  1526. *
  1527. * NOMANUAL
  1528. */
  1529. UCHAR * dhcpcOptCreate
  1530.     (
  1531.     UCHAR option,  /* RFC 2132 tag of desired option */
  1532.     UCHAR *  pOrig,  /* current option subfield, or NULL if none */
  1533.     UCHAR *  pData,  /* additional/first option body */
  1534.     int  length  /* amount of new data */
  1535.     )
  1536.     {
  1537.     UCHAR * pDest;
  1538.     pDest = malloc (length + 2);    /* Adjusts for tag and length */
  1539.     if (pDest != NULL)
  1540.         {
  1541.         *pDest = option;
  1542.         * (pDest + 1) = length;
  1543.         bcopy (pData, pDest + 2, length);
  1544.         if (pOrig != NULL)
  1545.             free (pOrig);
  1546.         }
  1547.     return (pDest);
  1548.     }
  1549. /*******************************************************************************
  1550. *
  1551. * dhcpcOptFieldCreate - fill in the options field for outgoing messages
  1552. *
  1553. * The boot-time and run-time DHCP clients use this routine to fill the
  1554. * options field for all outgoing messages from the available entries in
  1555. * the <pOptList> structure. Any memory used for variable-length subfields
  1556. * within that structure is released. The <pOptions> parameter indicates the
  1557. * destination for the options to be included in all outgoing messages. This
  1558. * routine ignores the contents for the "requested IP address" option, if
  1559. * present, since that option cannot always be included in the initial message.
  1560. *
  1561. * RETURNS: N/A
  1562. *
  1563. * NOMANUAL
  1564. */
  1565. void dhcpcOptFieldCreate
  1566.     (
  1567.     struct dhcpcOpts *  pOptList,  /* Available options for message */
  1568.     UCHAR *   pOptions  /* Resulting message field */
  1569.     )
  1570.     {
  1571.     int  loop;
  1572.     int  optlen = 0;
  1573.     UCHAR *  pData = NULL;
  1574.     UCHAR *  pDest;
  1575.     BOOL  copyFlag;
  1576.     pDest = pOptions;
  1577.     for (loop = 0; loop < MAXTAGNUM; loop++)
  1578.         {
  1579.         if (ISSET (pOptList->optmask, loop))
  1580.             {
  1581.             copyFlag = FALSE;
  1582.             /* 
  1583.              * For fixed size options, copy option body after inserting
  1584.              * option tag and length.
  1585.              */
  1586.             switch (loop)
  1587.                 {
  1588.                 /* 1 byte values */
  1589.                 case _DHCP_IP_FORWARD_TAG:  /* Option Tag 19 */
  1590.                     optlen = 1;
  1591.                     pData = &pOptList->tag19;
  1592.                     copyFlag = TRUE; 
  1593.                     break;    
  1594.                 case _DHCP_NONLOCAL_SRCROUTE_TAG:  /* Option Tag 20 */
  1595.                     optlen = 1;
  1596.                     pData = &pOptList->tag20;
  1597.                     copyFlag = TRUE; 
  1598.                     break;
  1599.                 case _DHCP_DEFAULT_IP_TTL_TAG:  /* Option Tag 23 */
  1600.                     optlen = 1;
  1601.                     pData = &pOptList->tag23;
  1602.                     copyFlag = TRUE; 
  1603.                     break;
  1604.                 case _DHCP_ALL_SUBNET_LOCAL_TAG:  /* Option Tag 27 */
  1605.                     optlen = 1;
  1606.                     pData = &pOptList->tag27;
  1607.                     copyFlag = TRUE; 
  1608.                     break;
  1609.                 case _DHCP_MASK_DISCOVER_TAG:  /* Option Tag 29 */
  1610.                     optlen = 1;
  1611.                     pData = &pOptList->tag29;
  1612.                     copyFlag = TRUE; 
  1613.                     break;
  1614.                 case _DHCP_MASK_SUPPLIER_TAG:  /* Option Tag 30 */
  1615.                     optlen = 1;
  1616.                     pData = &pOptList->tag30;
  1617.                     copyFlag = TRUE; 
  1618.                     break;
  1619.                 case _DHCP_ROUTER_DISCOVER_TAG:  /* Option Tag 31 */
  1620.                     optlen = 1;
  1621.                     pData = &pOptList->tag31;
  1622.                     copyFlag = TRUE; 
  1623.                     break;
  1624.                 case _DHCP_TRAILER_TAG:  /* Option Tag 34 */
  1625.                     optlen = 1;
  1626.                     pData = &pOptList->tag34;
  1627.                     copyFlag = TRUE; 
  1628.                     break;
  1629.                 case _DHCP_ETHER_ENCAP_TAG:  /* Option Tag 36 */
  1630.                     optlen = 1;
  1631.                     pData = &pOptList->tag36;
  1632.                     copyFlag = TRUE; 
  1633.                     break;
  1634.                 case _DHCP_DEFAULT_TCP_TTL_TAG:  /* Option Tag 37 */
  1635.                     optlen = 1;
  1636.                     pData = &pOptList->tag37;
  1637.                     copyFlag = TRUE; 
  1638.                     break;
  1639.                 case _DHCP_KEEPALIVE_GARBAGE_TAG:  /* Option Tag 39 */
  1640.                     optlen = 1;
  1641.                     pData = &pOptList->tag39;
  1642.                     copyFlag = TRUE; 
  1643.                     break;
  1644.                 case _DHCP_NB_NODETYPE_TAG:  /* Option Tag 46 */
  1645.                     optlen = 1;
  1646.                     pData = &pOptList->tag46;
  1647.                     copyFlag = TRUE; 
  1648.                     break;
  1649.                 /* 2 byte values */
  1650.                 case _DHCP_BOOTSIZE_TAG:  /* Option Tag 13 */
  1651.                     optlen = 2;
  1652.                     pData = (UCHAR *)&pOptList->tag13;
  1653.                     copyFlag = TRUE; 
  1654.                     break;
  1655.                 case _DHCP_MAX_DGRAM_SIZE_TAG:  /* Option Tag 22 */
  1656.                     optlen = 2;
  1657.                     pData = (UCHAR *)&pOptList->tag22;
  1658.                     copyFlag = TRUE; 
  1659.                     break;
  1660.                 case _DHCP_IF_MTU_TAG:  /* Option Tag 26 */
  1661.                     optlen = 2;
  1662.                     pData = (UCHAR *)&pOptList->tag26;
  1663.                     copyFlag = TRUE; 
  1664.                     break;
  1665.                 /* 4 byte values */
  1666.                 case _DHCP_SUBNET_MASK_TAG:  /* Option Tag 1 */
  1667.                     optlen = 4;
  1668.                     pData = (UCHAR *)&pOptList->tag1;
  1669.                     copyFlag = TRUE; 
  1670.                     break;
  1671.                 case _DHCP_TIME_OFFSET_TAG:  /* Option Tag 2 */
  1672.                     optlen = 4;
  1673.                     pData = (UCHAR *)&pOptList->tag2;
  1674.                     copyFlag = TRUE; 
  1675.                     break;
  1676.                 case _DHCP_SWAP_SERVER_TAG:  /* Option Tag 16 */
  1677.                     optlen = 4;
  1678.                     pData = (UCHAR *)&pOptList->tag16;
  1679.                     copyFlag = TRUE; 
  1680.                     break;
  1681.                 case _DHCP_MTU_AGING_TIMEOUT_TAG:  /* Option Tag 24 */
  1682.                     optlen = 4;
  1683.                     pData = (UCHAR *)&pOptList->tag24;
  1684.                     copyFlag = TRUE; 
  1685.                     break;
  1686.                 case _DHCP_BRDCAST_ADDR_TAG:  /* Option Tag 28 */
  1687.                     optlen = 4;
  1688.                     pData = (UCHAR *)&pOptList->tag28;
  1689.                     copyFlag = TRUE; 
  1690.                     break;
  1691.                 case _DHCP_ROUTER_SOLICIT_TAG:  /* Option Tag 32 */
  1692.                     optlen = 4;
  1693.                     pData = (UCHAR *)&pOptList->tag32;
  1694.                     copyFlag = TRUE; 
  1695.                     break;
  1696.                 case _DHCP_ARP_CACHE_TIMEOUT_TAG:  /* Option Tag 35 */
  1697.                     optlen = 4;
  1698.                     pData = (UCHAR *)&pOptList->tag35;
  1699.                     copyFlag = TRUE; 
  1700.                     break;
  1701.                 case _DHCP_KEEPALIVE_INTERVAL_TAG:  /* Option Tag 38 */
  1702.                     optlen = 4;
  1703.                     pData = (UCHAR *)&pOptList->tag38;
  1704.                     copyFlag = TRUE; 
  1705.                     break;
  1706.                 case _DHCP_LEASE_TIME_TAG:  /* Option Tag 51 */
  1707.                     optlen = 4;
  1708.                     pData = (UCHAR *)&pOptList->tag51;
  1709.                     copyFlag = TRUE; 
  1710.                     break;
  1711.                 case _DHCP_T1_TAG:  /* Option Tag 58 */
  1712.                     optlen = 4;
  1713.                     pData = (UCHAR *)&pOptList->tag58;
  1714.                     copyFlag = TRUE; 
  1715.                     break;
  1716.                 case _DHCP_T2_TAG:  /* Option Tag 59 */
  1717.                     optlen = 4;
  1718.                     pData = (UCHAR *)&pOptList->tag59;
  1719.                     copyFlag = TRUE; 
  1720.                     break;
  1721.                 }
  1722.             if (copyFlag)
  1723.                 {
  1724.                 *pDest++ = (UCHAR)loop;
  1725.                 *pDest++ = (UCHAR)optlen;
  1726.                 bcopy (pData, pDest, optlen);
  1727.                 pDest += optlen;
  1728.                 continue;
  1729.                 }
  1730.             /* 
  1731.              * For variable length options, copy the entry (which already
  1732.              * includes the option tag and length) then release the memory.
  1733.              */
  1734.             switch (loop)
  1735.                 {
  1736.                 case _DHCP_MTU_PLATEAU_TABLE_TAG:  /* Option Tag 25 */
  1737.                     pData = pOptList->pTag25;
  1738.                     break;
  1739.                 case _DHCP_ROUTER_TAG:  /* Option Tag 3 */
  1740.                     pData = pOptList->pTag3;
  1741.                     break;
  1742.                 case _DHCP_TIME_SERVER_TAG:  /* Option Tag 4 */
  1743.                     pData = pOptList->pTag4;
  1744.                     break;
  1745.                 case _DHCP_NAME_SERVER_TAG:  /* Option Tag 5 */
  1746.                     pData = pOptList->pTag5;
  1747.                     break;
  1748.                 case _DHCP_DNS_SERVER_TAG:  /* Option Tag 6 */
  1749.                     pData = pOptList->pTag6;
  1750.                     break;
  1751.                 case _DHCP_LOG_SERVER_TAG:  /* Option Tag 7 */
  1752.                     pData = pOptList->pTag7;
  1753.                     break;
  1754.                 case _DHCP_COOKIE_SERVER_TAG:  /* Option Tag 8 */
  1755.                     pData = pOptList->pTag8;
  1756.                     break;
  1757.                 case _DHCP_LPR_SERVER_TAG:  /* Option Tag 9 */
  1758.                     pData = pOptList->pTag9;
  1759.                     break;
  1760.                 case _DHCP_IMPRESS_SERVER_TAG:  /* Option Tag 10 */
  1761.                     pData = pOptList->pTag10;
  1762.                     break;
  1763.                 case _DHCP_RLS_SERVER_TAG:  /* Option Tag 11 */
  1764.                     pData = pOptList->pTag11;
  1765.                     break;
  1766.                 case _DHCP_NIS_SERVER_TAG:  /* Option Tag 41 */
  1767.                     pData = pOptList->pTag41;
  1768.                     break;
  1769.                 case _DHCP_NTP_SERVER_TAG:  /* Option Tag 42 */
  1770.                     pData = pOptList->pTag42;
  1771.                     break;
  1772.                 case _DHCP_NBN_SERVER_TAG:  /* Option Tag 44 */
  1773.                     pData = pOptList->pTag44;
  1774.                     break;
  1775.                 case _DHCP_NBDD_SERVER_TAG:  /* Option Tag 45 */
  1776.                     pData = pOptList->pTag45;
  1777.                     break;
  1778.                 case _DHCP_XFONT_SERVER_TAG:  /* Option Tag 48 */
  1779.                     pData = pOptList->pTag48;
  1780.                     break;
  1781.                 case _DHCP_XDISPLAY_MANAGER_TAG:  /* Option Tag 49 */
  1782.                     pData = pOptList->pTag49;
  1783.                     break;
  1784.                 case _DHCP_NISP_SERVER_TAG:  /* Option Tag 65 */
  1785.                     pData = pOptList->pTag65;
  1786.                     break;
  1787.                 case _DHCP_MOBILEIP_HA_TAG:  /* Option Tag 68 */
  1788.                     pData = pOptList->pTag68;
  1789.                     break;
  1790.                 case _DHCP_SMTP_SERVER_TAG:  /* Option Tag 69 */
  1791.                     pData = pOptList->pTag69;
  1792.                     break;
  1793.                 case _DHCP_POP3_SERVER_TAG:  /* Option Tag 70 */
  1794.                     pData = pOptList->pTag70;
  1795.                     break;
  1796.                 case _DHCP_NNTP_SERVER_TAG:  /* Option Tag 71 */
  1797.                     pData = pOptList->pTag71;
  1798.                     break;
  1799.                 case _DHCP_DFLT_WWW_SERVER_TAG:  /* Option Tag 72 */
  1800.                     pData = pOptList->pTag72;
  1801.                     break;
  1802.                 case _DHCP_DFLT_FINGER_SERVER_TAG:  /* Option Tag 73 */
  1803.                     pData = pOptList->pTag73;
  1804.                     break;
  1805.                 case _DHCP_DFLT_IRC_SERVER_TAG:   /* Option Tag 74 */
  1806.                     pData = pOptList->pTag74;
  1807.                     break;
  1808.                 case _DHCP_STREETTALK_SERVER_TAG:   /* Option Tag 75 */
  1809.                     pData = pOptList->pTag75;
  1810.                     break;
  1811.                 case _DHCP_STDA_SERVER_TAG:  /* Option Tag 76 */
  1812.                     pData = pOptList->pTag76;
  1813.                     break;
  1814.                 case _DHCP_POLICY_FILTER_TAG:  /* Option Tag 21 */
  1815.                     pData = pOptList->pTag21;
  1816.                     break;
  1817.                 case _DHCP_STATIC_ROUTE_TAG:  /* Option Tag 33 */
  1818.                     pData = pOptList->pTag33;
  1819.                     break;
  1820.                 case _DHCP_VENDOR_SPEC_TAG:  /* Option Tag 43 */
  1821.                     pData = pOptList->pTag43;
  1822.                     break;
  1823.                 case _DHCP_REQ_LIST_TAG:  /* Option Tag 55 */
  1824.                     pData = pOptList->pTag55;
  1825.                     break;
  1826.                 case _DHCP_HOSTNAME_TAG:  /* Option Tag 12 */
  1827.                     pData = pOptList->pTag12;
  1828.                     break;
  1829.                 case _DHCP_MERIT_DUMP_TAG:  /* Option Tag 14 */
  1830.                     pData = pOptList->pTag14;
  1831.                     break;
  1832.                 case _DHCP_DNS_DOMAIN_TAG:  /* Option Tag 15 */
  1833.                     pData = pOptList->pTag15;
  1834.                     break;
  1835.                 case _DHCP_ROOT_PATH_TAG:  /* Option Tag 17 */
  1836.                     pData = pOptList->pTag17;
  1837.                     break;
  1838.                 case _DHCP_EXTENSIONS_PATH_TAG:  /* Option Tag 18 */
  1839.                     pData = pOptList->pTag18;
  1840.                     break;
  1841.                 case _DHCP_NIS_DOMAIN_TAG:  /* Option Tag 40 */
  1842.                     pData = pOptList->pTag40;
  1843.                     break;
  1844.                 case _DHCP_NB_SCOPE_TAG:  /* Option Tag 47 */
  1845.                     pData = pOptList->pTag47;
  1846.                     break;
  1847.                 case _DHCP_ERRMSG_TAG:  /* Option Tag 56 */
  1848.                     pData = pOptList->pTag56;
  1849.                     break;
  1850.                 case _DHCP_CLASS_ID_TAG:  /* Option Tag 60 */
  1851.                     pData = pOptList->pTag60;
  1852.                     break;
  1853.                 case _DHCP_CLIENT_ID_TAG:  /* Option Tag 61 */
  1854.                     pData = pOptList->pTag61;
  1855.                     break;
  1856.                 case _DHCP_NISP_DOMAIN_TAG:  /* Option Tag 64 */
  1857.                     pData = pOptList->pTag64;
  1858.                     break;
  1859.                 case _DHCP_TFTP_SERVERNAME_TAG:  /* Option Tag 66 */
  1860.                     pData = pOptList->pTag66;
  1861.                     break;
  1862.                 case _DHCP_BOOTFILE_TAG:  /* Option Tag 67 */
  1863.                     pData = pOptList->pTag67;
  1864.                     break;
  1865.                 }
  1866.             optlen = *(pData + 1);
  1867.             optlen += 2;  /* Adjust for tag and length value. */
  1868.             bcopy (pData, pDest, optlen);
  1869.             pDest += optlen;
  1870.             free (pData);
  1871.             }    /* END: if (ISSET (<option value>) */
  1872.         }    /* END: loop */
  1873.     return;
  1874.     }
  1875. /******************************************************************************
  1876. *
  1877. * dhcpcDefaultsSet - assign host requirements defaults for client
  1878. *
  1879. * This routine fills the client's parameters structure with the default
  1880. * values specified in the Host Requirements Documents (RFC's 1122 and 1123),
  1881. * the Path MTU Discovery description (RFC 1191), or the Router Discovery
  1882. * specification (RFC 1256). This data is assigned before processing a message 
  1883. * received from a DHCP server, so that it can override the defaults.
  1884. *
  1885. * RETURNS: N/A
  1886. *
  1887. * ERRNO: N/A
  1888. *
  1889. * NOMANUAL
  1890. */
  1891. void dhcpcDefaultsSet
  1892.     (
  1893.     struct dhcp_param *  pNewParam
  1894.     )
  1895.     {
  1896.     /* Default IP layer parameters, per host. */
  1897.     pNewParam->ip_forward = FALSE;
  1898.     pNewParam->nonlocal_srcroute = FALSE;
  1899.     pNewParam->max_dgram_size = _HRD_MAX_DGRAM;
  1900.     pNewParam->default_ip_ttl = _HRD_IP_TTL;
  1901.     /* Default IP layer parameters, per interface. */
  1902.     pNewParam->intf_mtu = _HRD_MTU;
  1903.     pNewParam->all_subnet_local = FALSE;
  1904.     pNewParam->mask_discover = FALSE;
  1905.     pNewParam->mask_supplier = FALSE;
  1906.     pNewParam->router_discover = TRUE;
  1907.     pNewParam->router_solicit.s_addr = _HRD_ROUTER;
  1908.     /* Default link layer parameters, per interface. */
  1909.     pNewParam->trailer = FALSE;
  1910.     pNewParam->arp_cache_timeout = _HRD_ARP_TIME;
  1911.     pNewParam->ether_encap = FALSE;
  1912.     /* Default link layer parameters, per host. */
  1913.     pNewParam->default_tcp_ttl = _HRD_TCP_TTL;
  1914.     pNewParam->keepalive_inter = _HRD_TCP_TIME;
  1915.     pNewParam->keepalive_garba = FALSE;
  1916.     }
  1917. /******************************************************************************
  1918. *
  1919. * dhcpcEventAdd - send event notification to monitor task
  1920. *
  1921. * This routine adds event descriptors to the event queue for later handling 
  1922. * by the DHCP client monitor task. 
  1923. *
  1924. * If the <source> parameter is set to DHCP_USER_EVENT, the routine was called 
  1925. * by one of the following API routines: dhcpcInformGet(), dhcpcBind(),
  1926. * dhcpcRelease(), dhcpcVerify(), or dhcpcShutdown(). The <type> parameter
  1927. * indicates the corresponding action: DHCP_USER_INFORM to get additional
  1928. * configuration parameters without establishing a lease, DHCP_USER_BIND to
  1929. * initiate the lease negotiation process, DHCP_USER_VERIFY to verify an
  1930. * active lease, DHCP_USER_RELEASE to relinquish an active lease or
  1931. * remove additional parameters, and DHCP_USER_SHUTDOWN to release all sets
  1932. * of configuration parameters and disable the DHCP client library. 
  1933. *
  1934. * If the <source> parameter is set to DHCP_AUTO_EVENT, the routine was called
  1935. * in response to a timeout in the DHCP client state machine and the
  1936. * <type> parameter is set to DHCP_TIMEOUT.
  1937. *
  1938. * The <pLeaseId> parameter identifies the configuration parameters (usually
  1939. * associated with a lease) for timeout events and the first four user events.
  1940. *
  1941. * The <intFlag> parameter indicates if this routine is executing at interrupt 
  1942. * level. If it is FALSE, then interrupts must be locked out to prevent
  1943. * write conflicts to the event ring buffer between user requests and watchdog 
  1944. * timers.
  1945. *
  1946. * RETURNS: OK if event added successfully, or ERROR otherwise.
  1947. *
  1948. * ERRNO: N/A
  1949. *
  1950. * NOMANUAL
  1951. */ 
  1952. STATUS dhcpcEventAdd
  1953.     (
  1954.     int  source,  /* automatic event or user request */
  1955.     int  type,  /* event identifier */
  1956.     void *  pLeaseId, /* internal lease identifier */
  1957.     BOOL  intFlag  /* executing at interrupt level? */
  1958.     )
  1959.     {
  1960.     EVENT_DATA  newEvent;
  1961.     int  status;
  1962.     int  key = 0;
  1963.     newEvent.source = source;
  1964.     newEvent.type = type;
  1965.     newEvent.leaseId = pLeaseId;
  1966.     /*
  1967.      * Add the event to the monitor task's event list. 
  1968.      * Disable interrupts if necessary. 
  1969.      */
  1970.     if (!intFlag)
  1971.         key = intLock ();
  1972.     status = rngBufPut (dhcpcEventRing, (char *)&newEvent, sizeof (newEvent));
  1973.     if (!intFlag)
  1974.         intUnlock (key);
  1975.     if (status != sizeof (newEvent))
  1976.         return (ERROR);
  1977.     /* Signal the monitor task of the event arrival. */
  1978.     status = semGive (dhcpcEventSem);
  1979.     if (status == ERROR)
  1980.         return (ERROR);
  1981.     return (OK);
  1982.     }
  1983. /******************************************************************************
  1984. *
  1985. * dhcpcParamsCopy - copy current network parameters.
  1986. *
  1987. * This routine copies the network parameters to the caller-supplied structure.
  1988. * A run-time session calls this routine internally with the dhcpcParamsGet()
  1989. * routine and the <pLeaseData> parameter identifies the target lease. The DHCP
  1990. * boot-time session also uses this routine within the dhcpcBootParamsGet()
  1991. * routine. In that case, the parameters accessed through the lease structure
  1992. * for compatibility with the interface are actually available directly.
  1993. *
  1994. * RETURNS: N/A
  1995. *
  1996. * ERRNO: N/A
  1997. *
  1998. * NOMANUAL
  1999. *
  2000. * INTERNAL
  2001. * The data structure accessed by this routine was defined by the original
  2002. * public domain code used as a basis for the DHCP implementation. The 
  2003. * structure tag and field names are not required to follow the coding 
  2004. * standards (and they don't).
  2005. */
  2006. void dhcpcParamsCopy
  2007.     (
  2008.     LEASE_DATA *  pLeaseData,
  2009.     struct dhcp_param * pParamList 
  2010.     )
  2011.     {
  2012.     int loop;
  2013.     int limit = 0;
  2014.     struct dhcp_param * pDhcpcParam;
  2015.     /*
  2016.      * The DHCP client parameters received from the server are stored in a 
  2017.      * large structure which either contains the actual parameter value 
  2018.      * or a pointer to the data. Because the parameters received are 
  2019.      * determined by the server configuration and many parameters are
  2020.      * optional, any of the fields could use the default value determined
  2021.      * earlier. In most cases, the default value is an empty field (or
  2022.      * zero in the case of numeric values). However, some parameters contain 
  2023.      * default settings specified by the host requirements documents which are 
  2024.      * used if the server does not provide a value. The following code copies 
  2025.      * any available parameters into the provided target structure. If 
  2026.      * necessary, it checks for empty fields. The code is divided into logical 
  2027.      * blocks according to the various data types used by the DHCP parameters.
  2028.      */
  2029.     pDhcpcParam = pLeaseData->dhcpcParam;
  2030.     /* Process all string parameters. */
  2031.     bcopy (pDhcpcParam->got_option, pParamList->got_option, OPTMASKSIZE);
  2032.     if (pParamList->sname != NULL && pDhcpcParam->sname != NULL)
  2033.         strcpy (pParamList->sname, pDhcpcParam->sname);
  2034.     if (pParamList->file  != NULL && pDhcpcParam->file != NULL)
  2035.         strcpy (pParamList->file, pDhcpcParam->file);
  2036.     if (pParamList->hostname != NULL && pDhcpcParam->hostname != NULL)
  2037.         strcpy (pParamList->hostname, pDhcpcParam->hostname);
  2038.     if (pParamList->merit_dump != NULL && pDhcpcParam->merit_dump != NULL)
  2039.         strcpy (pParamList->merit_dump, pDhcpcParam->merit_dump);
  2040.     if (pParamList->dns_domain != NULL && pDhcpcParam->dns_domain != NULL)
  2041.         strcpy (pParamList->dns_domain, pDhcpcParam->dns_domain);
  2042.     if (pParamList->root_path != NULL && pDhcpcParam->root_path != NULL)
  2043.         strcpy (pParamList->root_path, pDhcpcParam->root_path);
  2044.     if (pParamList->extensions_path != NULL && 
  2045.         pDhcpcParam->extensions_path != NULL)
  2046.         strcpy (pParamList->extensions_path, pDhcpcParam->extensions_path);
  2047.     if (pParamList->nis_domain != NULL && pDhcpcParam->nis_domain != NULL)
  2048.         strcpy (pParamList->nis_domain, pDhcpcParam->nis_domain);
  2049.     if (pParamList->nb_scope != NULL && pDhcpcParam->nb_scope != NULL)
  2050.         strcpy (pParamList->nb_scope, pDhcpcParam->nb_scope);
  2051.     if (pParamList->errmsg != NULL && pDhcpcParam->errmsg != NULL)
  2052.         strcpy (pParamList->errmsg, pDhcpcParam->errmsg);
  2053.     if (pParamList->nisp_domain != NULL && pDhcpcParam->nisp_domain != NULL)
  2054.         strcpy (pParamList->nisp_domain, pDhcpcParam->nisp_domain);
  2055.     /* Process all boolean parameters. */
  2056.     pParamList->ip_forward = pDhcpcParam->ip_forward;
  2057.     pParamList->nonlocal_srcroute = pDhcpcParam->nonlocal_srcroute;
  2058.     pParamList->all_subnet_local = pDhcpcParam->all_subnet_local;
  2059.     pParamList->mask_discover = pDhcpcParam->mask_discover;
  2060.     pParamList->mask_supplier = pDhcpcParam->mask_supplier;
  2061.     pParamList->router_discover = pDhcpcParam->router_discover;
  2062.     pParamList->trailer = pDhcpcParam->trailer;
  2063.     pParamList->ether_encap = pDhcpcParam->ether_encap;
  2064.     pParamList->keepalive_garba = pDhcpcParam->keepalive_garba;
  2065.     /* Process all single numeric parameters. */
  2066.     pParamList->time_offset = pDhcpcParam->time_offset;
  2067.     pParamList->bootsize = pDhcpcParam->bootsize;
  2068.     pParamList->max_dgram_size = pDhcpcParam->max_dgram_size;
  2069.     pParamList->default_ip_ttl = pDhcpcParam->default_ip_ttl;
  2070.     pParamList->mtu_aging_timeout = pDhcpcParam->mtu_aging_timeout;
  2071.     pParamList->intf_mtu = pDhcpcParam->intf_mtu;
  2072.     pParamList->arp_cache_timeout = pDhcpcParam->arp_cache_timeout;
  2073.     pParamList->default_tcp_ttl = pDhcpcParam->default_tcp_ttl;
  2074.     pParamList->keepalive_inter = pDhcpcParam->keepalive_inter;
  2075.     pParamList->nb_nodetype = pDhcpcParam->nb_nodetype;
  2076.     pParamList->lease_origin = pDhcpcParam->lease_origin;
  2077.     pParamList->lease_duration = pDhcpcParam->lease_duration;
  2078.     pParamList->dhcp_t1 = pDhcpcParam->dhcp_t1;
  2079.     pParamList->dhcp_t2 = pDhcpcParam->dhcp_t2;
  2080.     /* Process multiple numeric parameters. */
  2081.     if (pParamList->mtu_plateau_table != NULL &&
  2082.         pDhcpcParam->mtu_plateau_table != NULL)
  2083.         {
  2084.         limit = 0;
  2085.         if (pParamList->mtu_plateau_table->shortnum != NULL)
  2086.             {
  2087.             limit = (pParamList->mtu_plateau_table->num <
  2088.                      pDhcpcParam->mtu_plateau_table->num) ?
  2089.                      pParamList->mtu_plateau_table->num :
  2090.                      pDhcpcParam->mtu_plateau_table->num;
  2091.             for (loop = 0; loop < limit; loop++)
  2092.                 {
  2093.                 pParamList->mtu_plateau_table->shortnum [loop] =
  2094.                 pDhcpcParam->mtu_plateau_table->shortnum [loop];
  2095.                 }
  2096.             }
  2097.         pParamList->mtu_plateau_table->num = limit;
  2098.         }
  2099.     /* Process single IP addresses. */
  2100.     pParamList->server_id = pDhcpcParam->server_id;
  2101.     pParamList->ciaddr = pDhcpcParam->ciaddr;
  2102.     pParamList->yiaddr = pDhcpcParam->yiaddr;
  2103.     pParamList->siaddr = pDhcpcParam->siaddr;
  2104.     pParamList->giaddr = pDhcpcParam->giaddr;
  2105.     if (pParamList->subnet_mask != NULL && pDhcpcParam->subnet_mask != NULL)
  2106.         bcopy ( (char *)pDhcpcParam->subnet_mask,
  2107.                (char *)pParamList->subnet_mask, sizeof (struct in_addr));
  2108.     if (pParamList->swap_server != NULL && pDhcpcParam->swap_server != NULL)
  2109.         bcopy ( (char *)pDhcpcParam->swap_server,
  2110.                (char *)pParamList->swap_server, sizeof (struct in_addr));
  2111.     if (pParamList->brdcast_addr != NULL &&
  2112.         pDhcpcParam->brdcast_addr != NULL)
  2113.         bcopy ( (char *)pDhcpcParam->brdcast_addr,
  2114.                (char *)pParamList->brdcast_addr, sizeof (struct in_addr));
  2115.     pParamList->router_solicit = pDhcpcParam->router_solicit;
  2116.     /* Process multiple IP addresses. */
  2117.     if (pParamList->router != NULL && pDhcpcParam->router != NULL)
  2118.         {
  2119.         limit = 0;
  2120.         if (pParamList->router->addr != NULL)
  2121.             {
  2122.             limit = (pParamList->router->num < pDhcpcParam->router->num) ?
  2123.                      pParamList->router->num : pDhcpcParam->router->num;
  2124.             for (loop = 0; loop < limit; loop++)
  2125.                 {
  2126.                 bcopy ( (char *)&pDhcpcParam->router->addr [loop],
  2127.                        (char *)&pParamList->router->addr [loop],
  2128.                        sizeof (struct in_addr));
  2129.                 }
  2130.             }
  2131.         pParamList->router->num = limit;
  2132.         }
  2133.     if (pParamList->time_server != NULL && pDhcpcParam->time_server != NULL)
  2134.         {
  2135.         limit = 0;
  2136.         if (pParamList->time_server->addr != NULL)
  2137.             {
  2138.             limit = (pParamList->time_server->num <
  2139.                      pDhcpcParam->time_server->num) ?
  2140.                      pParamList->time_server->num :
  2141.                      pDhcpcParam->time_server->num;
  2142.             for (loop = 0; loop < limit; loop++)
  2143.                 {
  2144.                 bcopy ( (char *)&pDhcpcParam->time_server->addr [loop],
  2145.                        (char *)&pParamList->time_server->addr [loop],
  2146.                        sizeof (struct in_addr));
  2147.                 }
  2148.             }
  2149.         pParamList->time_server->num = limit;
  2150.         }
  2151.     if (pParamList->name_server != NULL && pDhcpcParam->name_server != NULL)
  2152.         {
  2153.         limit = 0;
  2154.         if (pParamList->name_server->addr != NULL)
  2155.             {
  2156.             limit = (pParamList->name_server->num <
  2157.                      pDhcpcParam->name_server->num) ?
  2158.                      pParamList->name_server->num :
  2159.                      pDhcpcParam->name_server->num;
  2160.             for (loop = 0; loop < limit; loop++)
  2161.                 {
  2162.                 bcopy ( (char *)&pDhcpcParam->name_server->addr [loop],
  2163.                        (char *)&pParamList->name_server->addr [loop],
  2164.                        sizeof (struct in_addr));
  2165.                 }
  2166.             }
  2167.         pParamList->name_server->num = limit;
  2168.         }
  2169.     if (pParamList->dns_server != NULL && pDhcpcParam->dns_server != NULL)
  2170.         {
  2171.         limit = 0;
  2172.         if (pParamList->dns_server->addr != NULL)
  2173.             {
  2174.             limit = (pParamList->dns_server->num <
  2175.                      pDhcpcParam->dns_server->num) ?
  2176.                      pParamList->dns_server->num :
  2177.                      pDhcpcParam->dns_server->num;
  2178.             for (loop = 0; loop < limit; loop++)
  2179.                 {
  2180.                 bcopy ( (char *)&pDhcpcParam->dns_server->addr [loop],
  2181.                        (char *)&pParamList->dns_server->addr [loop],
  2182.                        sizeof (struct in_addr));
  2183.                 }
  2184.             }
  2185.         pParamList->dns_server->num = limit;
  2186.         }
  2187.     if (pParamList->log_server != NULL && pDhcpcParam->log_server != NULL)
  2188.         {
  2189.         limit = 0;
  2190.         if (pParamList->log_server->addr != NULL)
  2191.             {
  2192.             limit = (pParamList->log_server->num <
  2193.                      pDhcpcParam->log_server->num) ?
  2194.                      pParamList->log_server->num :
  2195.                      pDhcpcParam->log_server->num;
  2196.             for (loop = 0; loop < limit; loop++)
  2197.                 {
  2198.                 bcopy ( (char *)&pDhcpcParam->log_server->addr [loop],
  2199.                        (char *)&pParamList->log_server->addr [loop],
  2200.                        sizeof (struct in_addr));
  2201.                 }
  2202.             }
  2203.         pParamList->log_server->num = limit;
  2204.         }
  2205.     if (pParamList->cookie_server != NULL && 
  2206.         pDhcpcParam->cookie_server != NULL)
  2207.         {
  2208.         limit = 0;
  2209.         if (pParamList->cookie_server->addr != NULL)
  2210.             {
  2211.             limit = (pParamList->log_server->num <
  2212.                      pDhcpcParam->log_server->num) ?
  2213.                      pParamList->log_server->num :
  2214.                      pDhcpcParam->log_server->num;
  2215.             for (loop = 0; loop < limit; loop++)
  2216.                 {
  2217.                 bcopy ( (char *)&pDhcpcParam->cookie_server->addr [loop],
  2218.                        (char *)&pParamList->cookie_server->addr [loop],
  2219.                        sizeof (struct in_addr));
  2220.                 }
  2221.             }
  2222.         pParamList->cookie_server->num = limit;
  2223.         }
  2224.     if (pParamList->lpr_server != NULL && pDhcpcParam->lpr_server != NULL)
  2225.         {
  2226.         limit = 0;
  2227.         if (pParamList->lpr_server->addr != NULL)
  2228.             {
  2229.             limit = (pParamList->lpr_server->num <
  2230.                      pDhcpcParam->lpr_server->num) ?
  2231.                      pParamList->lpr_server->num :
  2232.                      pDhcpcParam->lpr_server->num;
  2233.             for (loop = 0; loop < limit; loop++)
  2234.                 {
  2235.                 bcopy( (char *)&pDhcpcParam->lpr_server->addr [loop],
  2236.                       (char *)&pParamList->lpr_server->addr [loop],
  2237.                       sizeof (struct in_addr));
  2238.                 }
  2239.             }
  2240.         pParamList->lpr_server->num = limit;
  2241.         }
  2242.     if (pParamList->impress_server != NULL &&
  2243.         pDhcpcParam->impress_server != NULL)
  2244.         {
  2245.         limit = 0;
  2246.         if (pParamList->impress_server->addr != NULL)
  2247.             {
  2248.             limit = (pParamList->impress_server->num <
  2249.                      pDhcpcParam->impress_server->num) ?
  2250.                      pParamList->impress_server->num :
  2251.                      pDhcpcParam->impress_server->num;
  2252.             for (loop = 0; loop < limit; loop++)
  2253.                 {
  2254.                 bcopy ( (char *)&pDhcpcParam->impress_server->addr [loop],
  2255.                        (char *)&pParamList->impress_server->addr [loop],
  2256.                        sizeof (struct in_addr));
  2257.                 }
  2258.             }
  2259.         pParamList->impress_server->num = limit;
  2260.         }
  2261.     if (pParamList->rls_server != NULL && pDhcpcParam->rls_server != NULL)
  2262.         {
  2263.         limit = 0;
  2264.         if (pParamList->rls_server->addr != NULL)
  2265.             {
  2266.             limit = (pParamList->rls_server->num <
  2267.                      pDhcpcParam->rls_server->num) ?
  2268.                      pParamList->rls_server->num :
  2269.                      pDhcpcParam->rls_server->num;
  2270.             for (loop = 0; loop < limit; loop++)
  2271.                 {
  2272.                 bcopy ( (char *)&pDhcpcParam->rls_server->addr [loop],
  2273.                        (char *)&pParamList->rls_server->addr [loop],
  2274.                        sizeof (struct in_addr));
  2275.                 }
  2276.             }
  2277.         pParamList->rls_server->num = limit;
  2278.         }
  2279.     if (pParamList->nis_server != NULL && pDhcpcParam->nis_server != NULL)
  2280.         {
  2281.         limit = 0;
  2282.         if (pParamList->nis_server->addr != NULL)
  2283.             {
  2284.             limit = (pParamList->nis_server->num <
  2285.                      pDhcpcParam->nis_server->num) ?
  2286.                      pParamList->nis_server->num :
  2287.                      pDhcpcParam->nis_server->num;
  2288.             for (loop = 0; loop < limit; loop++)
  2289.                 {
  2290.                 bcopy ( (char *)&pDhcpcParam->nis_server->addr [loop],
  2291.                        (char *)&pParamList->nis_server->addr [loop],
  2292.                        sizeof (struct in_addr));
  2293.                 }
  2294.             }
  2295.         pParamList->nis_server->num = limit;
  2296.         }
  2297.     if (pParamList->ntp_server != NULL && pDhcpcParam->ntp_server != NULL)
  2298.         {
  2299.         limit = 0;
  2300.         if (pParamList->ntp_server->addr != NULL)
  2301.             {
  2302.             limit = (pParamList->ntp_server->num <
  2303.                      pDhcpcParam->ntp_server->num) ?
  2304.                      pParamList->ntp_server->num :
  2305.                      pDhcpcParam->ntp_server->num;
  2306.             for (loop = 0; loop < limit; loop++)
  2307.                 {
  2308.                 bcopy ( (char *)&pDhcpcParam->ntp_server->addr [loop],
  2309.                        (char *)&pParamList->ntp_server->addr [loop],
  2310.                        sizeof (struct in_addr));
  2311.                 }
  2312.             }
  2313.         pParamList->ntp_server->num = limit;
  2314.         }
  2315.     if (pParamList->nbn_server != NULL && pDhcpcParam->nbn_server != NULL)
  2316.         {
  2317.         limit = 0;
  2318.         if (pParamList->nbn_server->addr != NULL)
  2319.             {
  2320.             limit = (pParamList->nbn_server->num <
  2321.                      pDhcpcParam->nbn_server->num) ?
  2322.                      pParamList->nbn_server->num :
  2323.                      pDhcpcParam->nbn_server->num;
  2324.             for (loop = 0; loop < limit; loop++)
  2325.                 {
  2326.                 bcopy ( (char *)&pDhcpcParam->nbn_server->addr [loop],
  2327.                        (char *)&pParamList->nbn_server->addr [loop],
  2328.                        sizeof (struct in_addr));
  2329.                 }
  2330.             }
  2331.         pParamList->nbn_server->num = limit;
  2332.         }
  2333.     if (pParamList->nbdd_server != NULL && pDhcpcParam->nbdd_server != NULL)
  2334.         {
  2335.         limit = 0;
  2336.         if (pParamList->nbdd_server->addr != NULL)
  2337.             {
  2338.             limit = (pParamList->nbdd_server->num <
  2339.                      pDhcpcParam->nbdd_server->num) ?
  2340.                      pParamList->nbdd_server->num :
  2341.                      pDhcpcParam->nbdd_server->num;
  2342.             for (loop = 0; loop < limit; loop++)
  2343.                 {
  2344.                 bcopy ( (char *)&pDhcpcParam->nbdd_server->addr [loop],
  2345.                        (char *)&pParamList->nbdd_server->addr [loop],
  2346.                        sizeof (struct in_addr));
  2347.                 }
  2348.             }
  2349.         pParamList->nbdd_server->num = limit;
  2350.         }
  2351.     if (pParamList->xfont_server != NULL &&
  2352.         pDhcpcParam->xfont_server != NULL)
  2353.         {
  2354.         limit = 0;
  2355.         if (pParamList->xfont_server->addr != NULL)
  2356.             {
  2357.             limit = (pParamList->xfont_server->num <
  2358.                      pDhcpcParam->xfont_server->num) ?
  2359.                      pParamList->xfont_server->num :
  2360.                      pDhcpcParam->xfont_server->num;
  2361.             for (loop = 0; loop < limit; loop++)
  2362.                 {
  2363.                 bcopy ( (char *)&pDhcpcParam->xfont_server->addr [loop],
  2364.                        (char *)&pParamList->xfont_server->addr [loop],
  2365.                        sizeof (struct in_addr));
  2366.                 }
  2367.             }
  2368.         pParamList->xfont_server->num = limit;
  2369.         }
  2370.     if (pParamList->xdisplay_manager != NULL &&
  2371.         pDhcpcParam->xdisplay_manager != NULL)
  2372.         {
  2373.         limit = 0;
  2374.         if (pParamList->xdisplay_manager->addr != NULL)
  2375.             {
  2376.             limit = (pParamList->xdisplay_manager->num <
  2377.                      pDhcpcParam->xdisplay_manager->num) ?
  2378.                      pParamList->xdisplay_manager->num :
  2379.                      pDhcpcParam->xdisplay_manager->num;
  2380.             for (loop = 0; loop < limit; loop++)
  2381.                 {
  2382.                 bcopy ( (char *)&pDhcpcParam->xdisplay_manager->addr [loop],
  2383.                        (char *)&pParamList->xdisplay_manager->addr [loop],
  2384.                        sizeof (struct in_addr));
  2385.                 }
  2386.             }
  2387.         pParamList->xdisplay_manager->num = limit;
  2388.         }
  2389.     if (pParamList->nisp_server != NULL && pDhcpcParam->nisp_server != NULL)
  2390.         {
  2391.         limit = 0;
  2392.         if (pParamList->nisp_server->addr != NULL)
  2393.             {
  2394.             limit = (pParamList->nisp_server->num <
  2395.                      pDhcpcParam->nisp_server->num) ?
  2396.                      pParamList->nisp_server->num :
  2397.                      pDhcpcParam->nisp_server->num;
  2398.             for (loop = 0; loop < limit; loop++)
  2399.                 {
  2400.                 bcopy ( (char *)&pDhcpcParam->nisp_server->addr [loop],
  2401.                        (char *)&pParamList->nisp_server->addr [loop],
  2402.                        sizeof (struct in_addr));
  2403.                 }
  2404.             }
  2405.         pParamList->nisp_server->num = limit;
  2406.         }
  2407.     if (pParamList->mobileip_ha != NULL && pDhcpcParam->mobileip_ha != NULL)
  2408.         {
  2409.         limit = 0;
  2410.         if (pParamList->mobileip_ha->addr != NULL)
  2411.             {
  2412.             limit = (pParamList->mobileip_ha->num <
  2413.                      pDhcpcParam->mobileip_ha->num) ?
  2414.                      pParamList->mobileip_ha->num :
  2415.                      pDhcpcParam->mobileip_ha->num;
  2416.             for (loop = 0; loop < limit; loop++)
  2417.                 {
  2418.                 bcopy ( (char *)&pDhcpcParam->mobileip_ha->addr [loop],
  2419.                        (char *)&pParamList->mobileip_ha->addr [loop],
  2420.                        sizeof (struct in_addr));
  2421.                 }
  2422.             }
  2423.         pParamList->mobileip_ha->num = limit;
  2424.         }
  2425.     if (pParamList->smtp_server != NULL && pDhcpcParam->smtp_server != NULL)
  2426.         {
  2427.         limit = 0;
  2428.         if (pParamList->smtp_server->addr != NULL)
  2429.             {
  2430.             limit = (pParamList->smtp_server->num <
  2431.                      pDhcpcParam->smtp_server->num) ?
  2432.                      pParamList->smtp_server->num :
  2433.                      pDhcpcParam->smtp_server->num;
  2434.             for (loop = 0; loop < limit; loop++)
  2435.                 {
  2436.                 bcopy ( (char *)&pDhcpcParam->smtp_server->addr [loop],
  2437.                        (char *)&pParamList->smtp_server->addr [loop],
  2438.                        sizeof (struct in_addr));
  2439.                 }
  2440.             }
  2441.         pParamList->smtp_server->num = limit;
  2442.         }
  2443.     if (pParamList->pop3_server != NULL && pDhcpcParam->pop3_server != NULL)
  2444.         {
  2445.         limit = 0;
  2446.         if (pParamList->pop3_server->addr != NULL)
  2447.             {
  2448.             limit = (pParamList->pop3_server->num <
  2449.                      pDhcpcParam->pop3_server->num) ?
  2450.                      pParamList->pop3_server->num :
  2451.                      pDhcpcParam->pop3_server->num;
  2452.             for (loop = 0; loop < limit; loop++)
  2453.                 {
  2454.                 bcopy ( (char *)&pDhcpcParam->pop3_server->addr [loop],
  2455.                        (char *)&pParamList->pop3_server->addr [loop],
  2456.                        sizeof (struct in_addr));
  2457.                 }
  2458.             }
  2459.         pParamList->pop3_server->num = limit;
  2460.         }
  2461.     if (pParamList->nntp_server != NULL && pDhcpcParam->nntp_server != NULL)
  2462.         {
  2463.         limit = 0;
  2464.         if (pParamList->nntp_server->addr != NULL)
  2465.             {
  2466.             limit = (pParamList->nntp_server->num <
  2467.                      pDhcpcParam->nntp_server->num) ?
  2468.                      pParamList->nntp_server->num :
  2469.                      pDhcpcParam->nntp_server->num;
  2470.             for (loop = 0; loop < limit; loop++)
  2471.                 {
  2472.                 bcopy ( (char *)&pDhcpcParam->nntp_server->addr [loop],
  2473.                        (char *)&pParamList->nntp_server->addr [loop],
  2474.                        sizeof (struct in_addr));
  2475.                 }
  2476.             }
  2477.         pParamList->nntp_server->num = limit;
  2478.         }
  2479.     if (pParamList->dflt_www_server != NULL &&
  2480.         pDhcpcParam->dflt_www_server != NULL)
  2481.         {
  2482.         limit = 0;
  2483.         if (pParamList->dflt_www_server->addr != NULL)
  2484.             {
  2485.             limit = (pParamList->dflt_www_server->num <
  2486.                      pDhcpcParam->dflt_www_server->num) ?
  2487.                      pParamList->dflt_www_server->num :
  2488.                      pDhcpcParam->dflt_www_server->num;
  2489.             for (loop = 0; loop < limit; loop++)
  2490.                 {
  2491.                 bcopy ( (char *)&pDhcpcParam->dflt_www_server->addr [loop],
  2492.                        (char *)&pParamList->dflt_www_server->addr [loop],
  2493.                        sizeof (struct in_addr));
  2494.                 }
  2495.             }
  2496.         pParamList->dflt_www_server->num = limit;
  2497.         }
  2498.     if (pParamList->dflt_finger_server != NULL &&
  2499.         pDhcpcParam->dflt_finger_server != NULL)
  2500.         {
  2501.         limit = 0;
  2502.         if (pParamList->dflt_finger_server->addr != NULL)
  2503.             {
  2504.             limit = (pParamList->dflt_finger_server->num <
  2505.                      pDhcpcParam->dflt_finger_server->num) ?
  2506.                      pParamList->dflt_finger_server->num :
  2507.                      pDhcpcParam->dflt_finger_server->num;
  2508.             for (loop = 0; loop < limit; loop++)
  2509.                 {
  2510.                 bcopy ( (char *)&pDhcpcParam->dflt_finger_server->addr [loop],
  2511.                        (char *)&pParamList->dflt_finger_server->addr [loop],
  2512.                        sizeof (struct in_addr));
  2513.                 }
  2514.             }
  2515.         pParamList->dflt_finger_server->num = limit;
  2516.         }
  2517.     if (pParamList->dflt_irc_server != NULL &&
  2518.         pDhcpcParam->dflt_irc_server != NULL)
  2519.         {
  2520.         limit = 0;
  2521.         if (pParamList->dflt_irc_server->addr != NULL)
  2522.             {
  2523.             limit = (pParamList->dflt_irc_server->num <
  2524.                      pDhcpcParam->dflt_irc_server->num) ?
  2525.                      pParamList->dflt_irc_server->num :
  2526.                      pDhcpcParam->dflt_irc_server->num;
  2527.             for (loop = 0; loop < limit; loop++)
  2528.                 {
  2529.                 bcopy ( (char *)&pDhcpcParam->dflt_irc_server->addr [loop],
  2530.                        (char *)&pParamList->dflt_irc_server->addr [loop],
  2531.                        sizeof (struct in_addr));
  2532.                 }
  2533.             }
  2534.         pParamList->dflt_irc_server->num = limit;
  2535.         }
  2536.     if (pParamList->streettalk_server != NULL &&
  2537.         pDhcpcParam->streettalk_server != NULL)
  2538.         {
  2539.         limit = 0;
  2540.         if (pParamList->streettalk_server->addr != NULL)
  2541.             {
  2542.             limit = (pParamList->streettalk_server->num <
  2543.                      pDhcpcParam->streettalk_server->num) ?
  2544.                      pParamList->streettalk_server->num :
  2545.                      pDhcpcParam->streettalk_server->num;
  2546.             for (loop = 0; loop < limit; loop++)
  2547.                 {
  2548.                 bcopy ( (char *)&pDhcpcParam->streettalk_server->addr [loop],
  2549.                        (char *)&pParamList->streettalk_server->addr [loop],
  2550.                        sizeof (struct in_addr));
  2551.                 }
  2552.             }
  2553.         pParamList->streettalk_server->num = limit;
  2554.         }
  2555.     if (pParamList->stda_server != NULL &&
  2556.         pDhcpcParam->stda_server != NULL)
  2557.         {
  2558.         limit = 0;
  2559.         if (pParamList->stda_server->addr != NULL)
  2560.             {
  2561.             limit = (pParamList->stda_server->num <
  2562.                      pDhcpcParam->stda_server->num) ?
  2563.                      pParamList->stda_server->num :
  2564.                      pDhcpcParam->stda_server->num;
  2565.             for (loop = 0; loop < limit; loop++)
  2566.                 {
  2567.                 bcopy ( (char *)&pDhcpcParam->stda_server->addr [loop],
  2568.                        (char *)&pParamList->stda_server->addr [loop],
  2569.                        sizeof (struct in_addr));
  2570.                 }
  2571.             }
  2572.         pParamList->stda_server->num = limit;
  2573.         }
  2574.     /* Handle multiple IP address pairs. */
  2575.     if (pParamList->policy_filter != NULL &&
  2576.         pDhcpcParam->policy_filter != NULL)
  2577.         {
  2578.         limit = 0;
  2579.         if (pParamList->policy_filter->addr != NULL)
  2580.             {
  2581.             limit = (pParamList->policy_filter->num <
  2582.                      pDhcpcParam->policy_filter->num) ?
  2583.                      pParamList->policy_filter->num :
  2584.                      pDhcpcParam->policy_filter->num;
  2585.             for (loop = 0; loop < limit; loop++)
  2586.                 {
  2587.                 bcopy( (char *)&pDhcpcParam->policy_filter->addr [loop * 2],
  2588.                       (char *)&pParamList->policy_filter->addr [loop * 2],
  2589.                       2 * sizeof (struct in_addr));
  2590.                 }
  2591.             }
  2592.         pParamList->policy_filter->num = limit;
  2593.         }
  2594.     if (pParamList->static_route != NULL &&
  2595.         pDhcpcParam->static_route != NULL)
  2596.         {
  2597.         limit = 0;
  2598.         if (pParamList->static_route->addr != NULL)
  2599.             {
  2600.             limit = (pParamList->static_route->num <
  2601.                      pDhcpcParam->static_route->num) ?
  2602.                      pParamList->static_route->num :
  2603.                      pDhcpcParam->static_route->num;
  2604.             for (loop = 0; loop < limit; loop++)
  2605.                 {
  2606.                 bcopy ( (char *)&pDhcpcParam->static_route->addr [loop * 2],
  2607.                        (char *)&pParamList->static_route->addr [loop * 2],
  2608.                        2 * sizeof (struct in_addr));
  2609.                 }
  2610.             }
  2611.         pParamList->static_route->num = limit;
  2612.         }
  2613.     /* Handle lists. */
  2614.     if (pParamList->vendlist != NULL && pDhcpcParam->vendlist != NULL)
  2615.         {
  2616.         limit = (pParamList->vendlist->len < pDhcpcParam->vendlist->len) ?
  2617.                 pParamList->vendlist->len : pDhcpcParam->vendlist->len;
  2618.         bcopy (pDhcpcParam->vendlist->list, pParamList->vendlist->list,
  2619.                limit);
  2620.         pParamList->vendlist->len = limit;
  2621.         }
  2622.     return;
  2623.     }