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

VxWorks

开发平台:

C/C++

  1. /* dhcpcBootLib.c - DHCP boot-time client library */
  2. /* Copyright 1984 - 2000 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01x,27mar02,wap  make dhcpcBootParamsGet() return error if dhcpcBootParam
  8.                  hasn't been initialized (SPR #73147)
  9. 01w,04dec01,wap  initialize dhcpcLeaseList correctly to avoid writing
  10.                  to page 0 (NULL pointer dereference) (SPR #69523)
  11. 01v,17nov00,spm  added support for BSD Ethernet devices
  12. 01u,15nov00,spm  fixed incorrect pointer assignment in lease list (SPR #62274)
  13. 01t,24oct00,spm  fixed modification history after merge from tor3_0_x branch
  14. 01s,23oct00,niq  merged from version 01t of tor3_0_x branch (base version 01r);
  15.                  upgrade to BPF replaces tagged frames support
  16. 01r,16mar99,spm  recovered orphaned code from tor2_0_x branch (SPR #25770)
  17. 01q,16mar99,spm  recovered orphaned code from tor1_0_1.sens1_1 (SPR #25770)
  18. 01p,01dec98,spm  added missing memory allocation (SPR #22881)
  19. 01p,06oct98,spm  fixed copying of parameters with IP address pairs (SPR #22416)
  20. 01o,14dec97,jdi  doc: cleanup.
  21. 01n,dec1097,kbw  fiddled manpage format
  22. 01m,04dec97,spm  added code review modifications
  23. 01l,06oct97,spm  removed reference to deleted endDriver global; replaced with
  24.                  support for dynamic driver type detection
  25. 01k,25sep97,spm  restored man page for dhcpcBootOptionSet() routine
  26. 01j,25sep97,gnn  SENS beta feedback fixes
  27. 01i,02sep97,spm  removed name conflicts with runtime DHCP client (SPR #9241)
  28. 01h,26aug97,spm  major overhaul: included version 01j of dhcpcCommonLib.c
  29.                  to retain single-lease library for boot time use
  30. 01g,12aug97,gnn  changes necessitated by MUX/END update.
  31. 01f,02jun97,spm  changed DHCP option tags to prevent name conflicts (SPR #8667)
  32.                  and updated man pages
  33. 01e,18apr97,spm  added call to dhcp_boot_client to reduce boot ROM size
  34. 01d,15apr97,kbw  fixed manpage format
  35. 01c,07apr97,spm  altered to use current value of configAll.h defines,
  36.                  rewrote documentation
  37. 01b,29jan97,spm  added END driver support and modified to fit coding standards
  38. 01a,14nov96,spm  created by removing unneeded functions from dhcpcLib.c
  39. */
  40. /*
  41. DESCRIPTION
  42. This library contains the interface for the client side of the Dynamic Host
  43. Configuration Protocol (DHCP) used during system boot. DHCP is an extension
  44. of BOOTP, the bootstrap protocol.  Like BOOTP, the protocol allows automatic
  45. system startup by providing an IP address, boot file name, and boot host's
  46. IP address over a network.  Additionally, DHCP provides the complete set of
  47. configuration parameters defined in the Host Requirements RFCs and allows
  48. automatic reuse of network addresses by specifying a lease duration for a
  49. set of configuration parameters.  This library is linked into the boot ROM 
  50. image automatically if INCLUDE_DHCPC is defined at the time that image is 
  51. constructed.
  52. HIGH-LEVEL INTERFACE
  53. The VxWorks boot program uses this library to obtain configuration parameters 
  54. with DHCP according to the client-server interaction detailed in RFC 2131 using
  55. the boot device specified in the boot parameters.  The DHCP client supports
  56. devices attached to the IP protocol with the MUX/END interface. It also
  57. supports BSD Ethernet devices attached to the IP protocol.
  58. To use DHCP, first build a boot ROM image with INCLUDE_DHCPC defined and set
  59.  the appropriate flag in the boot parameters before initiating booting with
  60. the "@" command.  The DHCP client will attempt to retrieve entries for the
  61. boot file name, and host IP address, as well as a subnet mask and broadcast
  62. address for the boot device.  If a target IP address is not available, the
  63. client will retrieve those parameters in the context of a lease. Otherwise,
  64. it will search for permanent assignments using a simpler message exchange.
  65. Any entries retrieved with either method will only be used if the corresponding
  66. fields in the boot parameters are blank.
  67. NOTE
  68. After DHCP retrieves the boot parameters, the specified boot file is loaded
  69. and the system restarts. As a result, the boot-time DHCP client cannot renew
  70. any lease which may be associated with the assigned IP address.  To avoid
  71. potential IP address conflicts while loading the boot file, the DHCPC_MIN_LEASE
  72. value should be set to exceed the file transfer time.  In addition, the boot
  73. file must also contain the DHCP client library so that the lease obtained
  74. before the restart can be renewed. Otherwise, the network initialization using
  75. the boot parameters will fail.  These restrictions do not apply if the target
  76. IP address is entered manually since the boot parameters do not involve a
  77. lease in that case.
  78. INTERNAL
  79. This module was created to reduce the size of the boot ROM image so that
  80. the DHCP client could be used with target architectures such as the MV147
  81. which have limited ROM capacity. The routines in this library are a modified
  82. version of similar routines available to the user in the dhcpcLib library. 
  83. These routines are only intended for use during boot time by the VxWorks 
  84. system. Among other differences, they do not support multiple leases and 
  85. they always apply configuration parameters to the underlying network device. 
  86. They should only be called by the boot program.
  87. INCLUDE FILES: dhcpcBootLib.h
  88. SEE ALSO: dhcpcLib, RFC 1541, RFC 1533
  89. */
  90. /* includes */
  91. #include "dhcp/copyright_dhcp.h"
  92. #include "vxWorks.h"
  93. #include "wdLib.h"
  94. #include "semLib.h"
  95. #include "ioLib.h"  /* ioctl() declaration */
  96. #include "taskLib.h"  /* taskSpawn() declaration */
  97. #include "muxLib.h"
  98. #include <stdio.h>
  99. #include <stdlib.h>
  100. #include <unistd.h>
  101. #include <string.h>
  102. #include <errno.h>
  103. #include <signal.h>
  104. #include <fcntl.h>
  105. #include <sys/types.h>
  106. #include <sys/socket.h>
  107. #include <sys/ioctl.h>
  108. #include <net/if.h>
  109. #include <netinet/in.h>
  110. #include <netinet/in_systm.h>
  111. #include <netinet/if_ether.h>
  112. #include <netinet/ip.h>
  113. #include <netinet/udp.h>
  114. #include <arpa/inet.h> 
  115. #include "dhcp/dhcpcCommonLib.h"
  116. #include "dhcpcBootLib.h"
  117. #include "bpfDrv.h"
  118. #include "end.h"
  119. #include "ipProto.h"
  120. /* defines */
  121. #define _BYTESPERWORD  4  /* Conversion factor for IP header */
  122. #define _DHCP_MAX_OPTLEN  255  /* Max. number of bytes in an option */
  123. #define _IPADDRLEN  4  /* Length of address in an ARP reply */
  124. #define _ETHER  1  /* Hardware type for Ethernet */
  125.                                         /* from assigned numbers RFC */
  126. #define _ETHERADDRLEN  6  /* Length of an Ethernet address */
  127.      /* Host requirements documents default values. */
  128. #define _HRD_MAX_DGRAM  576  /* Default maximum datagram size. */
  129. #define _HRD_IP_TTL  64  /* Default IP time-to-live (seconds) */
  130. #define _HRD_MTU  576  /* Default interface MTU */
  131. #define _HRD_ROUTER  0xffffffff /* Default router solication */
  132.                                    /* address - 255.255.255.255 */
  133. #define _HRD_ARP_TIME  60  /* Default ARP cache timeout (seconds) */
  134. #define _HRD_TCP_TTL  64  /* Default TCP time-to-live (seconds) */
  135. #define _HRD_TCP_TIME  7200  /* Default TCP keepalive interval (seconds) */
  136. #define _DHCPC_MAX_DEVNAME      21      /* "/bpf/dhcpc" + max unit number */
  137. IMPORT struct bpf_insn dhcpfilter[];    /* Needed to update client port. */
  138. IMPORT struct bpf_program dhcpread;     /* Installs filter for DHCP messages */
  139. IMPORT int dhcpcBufSize;
  140. IMPORT BOOL _dhcpcBootFlag;
  141. /* globals */
  142. LEASE_DATA      dhcpcBootLeaseData;
  143. LEASE_DATA *  pDhcpcBootLeaseData;
  144. int  dhcpcBindType;  /* Type of DHCP lease, if any. */
  145. /* locals */
  146. LOCAL int dhcpcOfferTimeout;  /* Set externally when building image */
  147. LOCAL int dhcpcDefaultLease;  /* Set externally when building image */
  148. LOCAL int dhcpcClientPort;  /* Set externally when building image */
  149. LOCAL int dhcpcServerPort;  /* Set externally when building image */
  150. /* forward declarations */
  151. IMPORT void dhcpcRead (void);  /* Retrieve incoming DHCP messages */
  152. LOCAL void dhcpcBootCleanup (void);
  153. /*******************************************************************************
  154. *
  155. * dhcpcBootInit - set up the DHCP client parameters and data structures
  156. *
  157. * This routine creates any necessary data structures and sets the client's 
  158. * option request list to retrieve a subnet mask and broadcast address for the 
  159. * network interface indicated by <pIf>.  The routine is executed automatically 
  160. * by the boot program when INCLUDE_DHCPC is defined and the automatic 
  161. * configuration option is set in the boot flags.  The network interface 
  162. * specified by <pIf> is used to transmit and receive all DHCP messages during 
  163. * the lease negotiation.  The DHCP client supports interfaces attached to the
  164. * IP protocol using the MUX/END interface and BSD Ethernet devices attached
  165. * to that protocol. The interface must be capable of sending broadcast
  166. * messages. The <maxSize> parameter specifies the maximum length supported for
  167. * any DHCP message, including the UDP and IP headers and the link level header.
  168. * The maximum length of the DHCP options field is based on this value or the
  169. * MTU size for the given interface, whichever is less. The smallest valid value
  170. * for the <maxSize> parameter is 576 bytes, corresponding to the minimum IP
  171. * datagram a host must accept. The MTU size of the network interface must be
  172. * large enough to handle those datagrams.
  173. *
  174. * ERRNO: N/A
  175. * RETURNS: Lease handle for later use, or NULL if lease startup fails.
  176. */
  177. void * dhcpcBootInit
  178.     (
  179.     struct ifnet * pIf,  /* network device used by client */
  180.     int  serverPort,     /* port used by DHCP servers (default 67) */
  181.     int  clientPort,     /* port used by DHCP clients (default 68) */
  182.     int  maxSize,  /* largest DHCP message supported, in bytes */
  183.     int  offerTimeout,   /* interval to get additional DHCP offers */
  184.     int  defaultLease,   /* default value for requested lease length */
  185.     int  minLease        /* minimum accepted lease length */
  186.     )
  187.     {
  188.     struct dhcp_reqspec *  pReqSpec;
  189.     LEASE_DATA *  pBootLeaseData;
  190.     BOOL bsdFlag = FALSE;
  191.     int loop;
  192.     int offset = 0;
  193.     int bufSize;  /* Receive buffer size (maxSize or MTU + BPF header) */
  194.     char bpfDevName [_DHCPC_MAX_DEVNAME];  /* "/bpf/dhcpc" + max unit number */
  195.     int bpfDev;
  196.     int result;
  197.     dhcpcServerPort = serverPort;
  198.     dhcpcClientPort = clientPort;
  199.     if (pIf == NULL)
  200.         {
  201.         printf ("Error: network device not specified.n");
  202.         return (NULL);
  203.         }
  204.     if (muxDevExists (pIf->if_name, pIf->if_unit) == FALSE)
  205.         {
  206.         bsdFlag = TRUE; 
  207.         }
  208.     /* Verify interface data sizes are appropriate for message. */
  209.     bufSize = pIf->if_mtu;
  210.     if (bufSize == 0)
  211.         {
  212.         printf ("Error: unusable network device.n");
  213.         return (NULL);
  214.         }
  215.     if (bufSize < DHCP_MSG_SIZE)
  216.         {
  217.         /*
  218.          * Devices must accept messages equal to the minimum IP datagram
  219.          * of 576 bytes, which corresponds to a DHCP message with up to
  220.          * 312 bytes of options.
  221.          */
  222.         printf ("Error: unusable network device.n");
  223.         return (NULL);
  224.         }
  225.     if (maxSize < DFLTDHCPLEN + UDPHL + IPHL)
  226.         {
  227.         /* The buffer size must also allow the minimum IP datagram. */
  228.         return (NULL);
  229.         }
  230.     if (bpfDrv () == ERROR)
  231.         {
  232.         return (NULL);
  233.         }
  234.     /* Select buffer size for BPF device less than or equal to the MTU size. */
  235.     bufSize += pIf->if_hdrlen;
  236.     if (bufSize > maxSize)
  237.         bufSize = maxSize;
  238.     bufSize += sizeof (struct bpf_hdr);
  239.     if (bpfDevCreate ("/bpf/dhcpc", 1, bufSize) == ERROR)
  240.         {
  241.         bpfDrvRemove ();
  242.         return (NULL);
  243.         }
  244.     /* Create and initialize storage for boot lease. */
  245.     pBootLeaseData = &dhcpcBootLeaseData;
  246.     pDhcpcBootLeaseData = pBootLeaseData;
  247.     dhcpcLeaseList = &pDhcpcBootLeaseData;
  248.     dhcpcMaxLeases = 1;      /* Only one DHCP session, for boot device. */
  249.     dhcpcDefaultLease = defaultLease;
  250.     dhcpcOfferTimeout = offerTimeout;
  251.     dhcpcMinLease = minLease;
  252.     /* Create signalling semaphore for event notification ring. */
  253.     dhcpcEventSem = semCCreate (SEM_Q_FIFO, 0);
  254.     if (dhcpcEventSem == NULL)
  255.         {
  256.         bpfDevDelete ("/bpf/dhcpc");
  257.         bpfDrvRemove ();
  258.         return (NULL);
  259.         }
  260.     /* Create event storage. */
  261.     dhcpcEventRing = rngCreate (EVENT_RING_SIZE);
  262.     if (dhcpcEventRing == NULL)
  263.         {
  264.         bpfDevDelete ("/bpf/dhcpc");
  265.         bpfDrvRemove ();
  266.         semDelete (dhcpcEventSem);
  267.         return (NULL);
  268.         }
  269.     /* Create message storage (matches number of elements in event ring). */
  270.     dhcpcMessageList = malloc (10 * sizeof (MESSAGE_DATA));
  271.     if (dhcpcMessageList == NULL)
  272.         {
  273.         bpfDevDelete ("/bpf/dhcpc");
  274.         bpfDrvRemove ();
  275.         semDelete (dhcpcEventSem);
  276.         rngDelete (dhcpcEventRing);
  277.         return (NULL);
  278.         }
  279.     /* Allocate (aligned) receive buffers based on maximum message size. */
  280.     for (loop = 0; loop < 10; loop++)
  281.         {
  282.         dhcpcMessageList [loop].msgBuffer = memalign (4, bufSize);
  283.         if (dhcpcMessageList [loop].msgBuffer == NULL)
  284.             break;
  285.         dhcpcMessageList [loop].writeFlag = TRUE;
  286.         }
  287.     if (loop < 10)
  288.         {
  289.         for (offset = 0; offset < loop; offset++)
  290.             free (dhcpcMessageList [offset].msgBuffer);
  291.         bpfDevDelete ("/bpf/dhcpc");
  292.         bpfDrvRemove ();
  293.         semDelete (dhcpcEventSem);
  294.         rngDelete (dhcpcEventRing);
  295.         free (dhcpcMessageList);
  296.         return (NULL);
  297.         }
  298.     /* Reset the message filter to use the specified client port. */
  299.     dhcpfilter [12].k = clientPort;
  300.     /* Get a BPF file descriptor to read/write DHCP messages. */
  301.     sprintf (bpfDevName, "/bpf/dhcpc%d", offset);
  302.     bpfDev = open (bpfDevName, 0, 0);
  303.     if (bpfDev < 0)
  304.         {
  305.         bpfDevDelete ("/bpf/dhcpc");
  306.         bpfDrvRemove ();
  307.         semDelete (dhcpcEventSem);
  308.         rngDelete (dhcpcEventRing);
  309.         for (offset = 0; offset < 10; offset++)
  310.             free (dhcpcMessageList [offset].msgBuffer);
  311.         free (dhcpcMessageList);
  312.         return (NULL);
  313.         }
  314.     /* Enable immediate mode for reading messages. */
  315.     result = 1;
  316.     result = ioctl (bpfDev, BIOCIMMEDIATE, (int)&result);
  317.     if (result != 0)
  318.         {
  319.         semDelete (dhcpcEventSem);
  320.         rngDelete (dhcpcEventRing);
  321.         for (offset = 0; offset < 10; offset++)
  322.             free (dhcpcMessageList [offset].msgBuffer);
  323.         free (dhcpcMessageList);
  324.         close (bpfDev);
  325.         bpfDevDelete ("/bpf/dhcpc");
  326.         bpfDrvRemove ();
  327.         return (NULL);
  328.         }
  329.     /* Initialize the lease-specific variables. */
  330.     bzero ( (char *)pBootLeaseData, sizeof (LEASE_DATA));
  331.     pBootLeaseData->initFlag = FALSE;
  332.     pBootLeaseData->autoConfig = TRUE;
  333.     pBootLeaseData->cacheHookRtn = NULL;   /* Results are saved in bootline. */
  334.     pReqSpec = &pBootLeaseData->leaseReqSpec;
  335.     bzero ( (char *)pReqSpec, sizeof (struct dhcp_reqspec));
  336.     bzero ( (char *)&pBootLeaseData->ifData, sizeof (struct if_info));
  337.     /* Initialize WIDE project global containing network device data.  */
  338.     sprintf (pBootLeaseData->ifData.name, "%s", pIf->if_name);
  339.     pBootLeaseData->ifData.unit = pIf->if_unit;
  340.     pBootLeaseData->ifData.iface = pIf;
  341.     pBootLeaseData->ifData.bpfDev = bpfDev;
  342.     pBootLeaseData->ifData.bufSize = bufSize;
  343.     /*
  344.      * For END devices, use hardware address information set when
  345.      * driver attached to IP. Assume BSD devices use Ethernet frames.
  346.      */
  347.     if (bsdFlag)
  348.         pBootLeaseData->ifData.haddr.htype = ETHER;
  349.     else
  350.         pBootLeaseData->ifData.haddr.htype = dhcpConvert (pIf->if_type);
  351.     pBootLeaseData->ifData.haddr.hlen = pIf->if_addrlen;
  352.     if (pBootLeaseData->ifData.haddr.hlen > MAX_HLEN)
  353.         pBootLeaseData->ifData.haddr.hlen = MAX_HLEN;
  354.     bcopy ( (char *) ( (struct arpcom *)pIf)->ac_enaddr,
  355.            (char *)&pBootLeaseData->ifData.haddr.haddr,
  356.            pBootLeaseData->ifData.haddr.hlen);
  357.     /*
  358.      * Set the maximum message length based on the MTU size and the
  359.      * specified maximum message/buffer size.
  360.      */
  361.     bufSize = pIf->if_mtu;
  362.     if (bufSize > maxSize)
  363.         pReqSpec->maxlen = maxSize;
  364.     else
  365.         pReqSpec->maxlen = bufSize;
  366.     dhcpcBufSize = maxSize;
  367.     /* set duration of client's wait for multiple offers */
  368.     pReqSpec->waitsecs = dhcpcOfferTimeout;
  369.     /* 
  370.      * Initialize request list with tags for options provided by server,
  371.      * according to RFC 2132.
  372.      */
  373.     pReqSpec->reqlist.len = 0;
  374.     pReqSpec->reqlist.list [pReqSpec->reqlist.len++] = _DHCP_SUBNET_MASK_TAG;
  375.     pReqSpec->reqlist.list [pReqSpec->reqlist.len++] = _DHCP_BRDCAST_ADDR_TAG;
  376.     /* Create event timer for state machine.  */
  377.     pBootLeaseData->timer = wdCreate ();
  378.     if (pBootLeaseData->timer == NULL)
  379.         {
  380.         semDelete (dhcpcEventSem);
  381.         rngDelete (dhcpcEventRing);
  382.         for (offset = 0; offset < 10; offset++)
  383.             free (dhcpcMessageList [offset].msgBuffer);
  384.         free (dhcpcMessageList);
  385.         close (bpfDev);
  386.         bpfDevDelete ("/bpf/dhcpc");
  387.         bpfDrvRemove ();
  388.         return (NULL);
  389.         }
  390.     pBootLeaseData->initFlag = TRUE;
  391.     _dhcpcBootFlag = TRUE;    /* Let read task ignore (unavailable) socket. */
  392.     /*
  393.      * Spawn the data retrieval task.  The entry routine will read all
  394.      * incoming DHCP messages and signal the client state machine when a
  395.      * valid one arrives.
  396.      */
  397.     result = taskSpawn ("tDhcpcReadTask", _dhcpcReadTaskPriority,
  398.                         _dhcpcReadTaskOptions, _dhcpcReadTaskStackSize,
  399.                         (FUNCPTR) dhcpcRead, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  400.     if (result == ERROR)
  401.         {
  402.         semDelete (dhcpcEventSem);
  403.         rngDelete (dhcpcEventRing);
  404.         for (offset = 0; offset < 10; offset++)
  405.             free (dhcpcMessageList [offset].msgBuffer);
  406.         free (dhcpcMessageList);
  407.         close (bpfDev);
  408.         bpfDevDelete ("/bpf/dhcpc");
  409.         bpfDrvRemove ();
  410.         wdDelete (pBootLeaseData->timer);
  411.         return (NULL);
  412.         }
  413.     dhcpcReadTaskId = result;
  414.     return (pBootLeaseData);
  415.     }
  416. /*******************************************************************************
  417. *
  418. * dhcpcBootBind - initialize the network with DHCP at boot time
  419. *
  420. * This routine performs the client side of a DHCP negotiation according to 
  421. * RFC 2131.  The negotiation uses the network device specified with the
  422. * initialization call.  The addressing information retrieved is applied to that 
  423. * network device.  Because the boot image is replaced by the downloaded target 
  424. * image, the resulting lease cannot be renewed.  Therefore, the minimum lease 
  425. * length specified by DHCPC_MIN_LEASE must be set so that the target image has 
  426. * sufficient time to download and begin monitoring the lease.  This routine is 
  427. * called automatically by the boot program when INCLUDE_DHCPC is defined and 
  428. * the automatic configuration option is set in the boot flags and no target
  429. * address is present.
  430. *
  431. * RETURNS: OK if negotiation is successful, or ERROR otherwise.
  432. *
  433. * ERRNO: N/A
  434. */
  435. STATUS dhcpcBootBind (void)
  436.     {
  437.     STATUS result = OK;
  438.     struct dhcpcOpts *  pOptList;
  439.     char *  pOptions;
  440.     struct ifreq  ifr;
  441.     /*
  442.      * Allocate space for any options in outgoing messages
  443.      * and fill in the options field.
  444.      */
  445.     pOptList = dhcpcBootLeaseData.leaseReqSpec.pOptList;
  446.     if (pOptList != NULL)
  447.         {
  448.         pOptions = malloc (pOptList->optlen);
  449.         if (pOptions == NULL)
  450.             {
  451.             return (ERROR);
  452.             }
  453.         dhcpcBootLeaseData.leaseReqSpec.optlen = pOptList->optlen;
  454.         dhcpcOptFieldCreate (pOptList, pOptions);
  455.         free (pOptList);
  456.         dhcpcBootLeaseData.leaseReqSpec.pOptList = NULL;
  457.         dhcpcBootLeaseData.leaseReqSpec.pOptions = pOptions;
  458.         }
  459.     /*
  460.      * Add a filter for incoming DHCP packets and assign the selected
  461.      * interface to the BPF device.
  462.      */
  463.     result = ioctl (dhcpcBootLeaseData.ifData.bpfDev, BIOCSETF, 
  464.                     (int)&dhcpread);
  465.     if (result != 0)
  466.         {
  467.         return (ERROR);
  468.         }
  469.     bzero ( (char *)&ifr, sizeof (struct ifreq));
  470.     sprintf (ifr.ifr_name, "%s%d", dhcpcBootLeaseData.ifData.name,
  471.                                    dhcpcBootLeaseData.ifData.unit);
  472.     result = ioctl (dhcpcBootLeaseData.ifData.bpfDev, BIOCSETIF, (int)&ifr);
  473.     if (result != 0)
  474.         {
  475.         return (ERROR);
  476.         }
  477.     dhcpcBindType = DHCP_MANUAL;
  478.     result = dhcp_boot_client (& (dhcpcBootLeaseData.ifData), 
  479.                                dhcpcServerPort, dhcpcClientPort, TRUE);
  480.     dhcpcBootCleanup ();
  481.     if (result != OK)
  482.       return (ERROR);
  483.     /* Bind was successful. */
  484.     return (OK);
  485.     }
  486. /*******************************************************************************
  487. *
  488. * dhcpcBootInformGet - obtain additional configuration parameters with DHCP
  489. *
  490. * This routine uses DHCP to retrieve additional configuration parameters for
  491. * a client with the externally configured network address given by the
  492. * <pAddrString> parameter. It sends an INFORM message and waits for a reply
  493. * following the process described in RFC 2131. The message exchange uses
  494. * the network device specified with the initialization call. Any interface
  495. * information retrieved is applied to that network device. Since this process
  496. * does not establish a lease, the target address will not contain any
  497. * timestamp information so that the runtime image will not attempt to verify 
  498. * the configuration parameters. This routine is called automatically by the
  499. * boot program when INCLUDE_DHCPC is defined and the automatic configuration
  500. * option is set in the boot flags if a target address is already present.
  501. *
  502. * RETURNS: OK if negotiation is successful, or ERROR otherwise.
  503. *
  504. * ERRNO: N/A
  505. */
  506. STATUS dhcpcBootInformGet
  507.     (
  508.     char *  pAddrString  /* known address assigned to client */
  509.     )
  510.     {
  511.     STATUS result = OK;
  512.     struct dhcpcOpts *  pOptList;
  513.     char *  pOptions;
  514.     /* Set the requested IP address field to the externally assigned value. */
  515.     dhcpcBootLeaseData.leaseReqSpec.ipaddr.s_addr = inet_addr (pAddrString);
  516.     if (dhcpcBootLeaseData.leaseReqSpec.ipaddr.s_addr == -1)
  517.         return (ERROR);
  518.     /*
  519.      * Allocate space for any options in outgoing messages
  520.      * and fill in the options field.
  521.      */
  522.     pOptList = dhcpcBootLeaseData.leaseReqSpec.pOptList;
  523.     if (pOptList != NULL)
  524.         {
  525.         pOptions = malloc (pOptList->optlen);
  526.         if (pOptions == NULL)
  527.             {
  528.             return (ERROR);
  529.             }
  530.         dhcpcBootLeaseData.leaseReqSpec.optlen = pOptList->optlen;
  531.         dhcpcOptFieldCreate (pOptList, pOptions);
  532.         free (pOptList);
  533.         dhcpcBootLeaseData.leaseReqSpec.pOptList = NULL;
  534.         dhcpcBootLeaseData.leaseReqSpec.pOptions = pOptions;
  535.         }
  536.     dhcpcBindType = DHCP_MANUAL;
  537.     result = dhcp_boot_client (& (dhcpcBootLeaseData.ifData),
  538.                                dhcpcServerPort, dhcpcClientPort, FALSE);
  539.     dhcpcBootCleanup ();
  540.     if (result != OK)
  541.       return (ERROR);
  542.     /* Additional configuration parameters retrieved. */
  543.     return (OK);
  544.     }
  545. /*******************************************************************************
  546. *
  547. * dhcpcBootParamsGet - retrieve current network parameters
  548. *
  549. * This routine copies the configuration parameters obtained at boot time to 
  550. * the caller-supplied structure.  That structure contains non-NULL pointers to 
  551. * indicate the parameters of interest.  All other values within the structure 
  552. * must be set to 0 before calling the routine.  This routine is called 
  553. * internally at boot time when the DHCP client is in the BOUND state.
  554. *
  555. * RETURNS: OK if dhcpcBootParam is non-NULL, or ERROR otherwise.
  556. *
  557. * ERRNO: N/A
  558. *
  559. * NOMANUAL
  560. */
  561. STATUS dhcpcBootParamsGet
  562.     (
  563.     struct dhcp_param* pParamList 
  564.     )
  565.     {
  566.     /*
  567.      * If we were doing a DHCPINFORM and got no info, dhcpcBootParam
  568.      * might still be NULL, in which case there are no parameters to
  569.      * copy. Test for this here, otherwise dhcpcParamsCopy() will
  570.      * blindly try to copy stuff from page 0.
  571.      */
  572.     if (dhcpcBootParam == NULL)
  573.         return (ERROR);
  574.     dhcpcBootLeaseData.dhcpcParam = dhcpcBootParam;
  575.     dhcpcParamsCopy (&dhcpcBootLeaseData, pParamList);
  576.     return (OK);
  577.     }
  578. /******************************************************************************
  579. *
  580. * dhcpcBootCleanup - remove data structures used by boot-time DHCP client
  581. *
  582. * This routine removes all data structures used by the dhcp client. It is 
  583. * called internally when the client exits.
  584. *
  585. * RETURNS: N/A
  586. *
  587. * ERRNO:   N/A
  588. *
  589. * NOMANUAL
  590. */
  591. LOCAL void dhcpcBootCleanup (void)
  592.     {
  593.     int loop;
  594.     wdCancel (dhcpcBootLeaseData.timer);
  595.     wdDelete (dhcpcBootLeaseData.timer);
  596.     close (dhcpcBootLeaseData.ifData.bpfDev);
  597.     taskDelete (dhcpcReadTaskId);
  598.     semDelete (dhcpcEventSem);
  599.     rngDelete (dhcpcEventRing);
  600.     for (loop = 0; loop < 10; loop++)
  601.          free (dhcpcMessageList [loop].msgBuffer);
  602.     free (dhcpcMessageList);
  603.     if (dhcpcBootLeaseData.leaseReqSpec.pOptions != NULL)
  604.         {
  605.         free (dhcpcBootLeaseData.leaseReqSpec.pOptions);
  606.         }
  607.     bpfDevDelete ("/bpf/dhcpc");
  608.     bpfDrvRemove ();
  609.     return;
  610.     }