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

VxWorks

开发平台:

C/C++

  1. /* dhcprLib.c - DHCP relay agent library */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc.  */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01p,22mar02,wap  don't start DHCP relay task if the relay table is empty
  8.                  (SPR #74456)
  9. 01o,16nov01,spm  fixed modification history following merge
  10. 01n,15oct01,rae  merge from truestack ver 01q, base 01lj (SPR #69981)
  11. 01m,17nov00,spm  added support for BSD Ethernet devices
  12. 01l,24oct00,spm  fixed modification history after merge from tor3_0_x branch
  13. 01k,23oct00,niq  merged from version 01l of tor3_0_x branch (base version 01j);
  14.                  upgrade to BPF replaces tagged frames support
  15. 01j,04dec97,spm  added code review modifications
  16. 01i,06oct97,spm  split interface name into device name and unit number; removed
  17.                  reference to deleted endDriver global; added stub routine to
  18.                  support delayed startup
  19. 01h,25sep97,gnn  SENS beta feedback fixes
  20. 01g,02sep97,spm  removed excess debug message (SPR #9149); corrected removal
  21.                  of target list in cleanup routine
  22. 01f,26aug97,spm  reorganized code and added support for UDP port selection
  23. 01e,12aug97,gnn  changes necessitated by MUX/END update.
  24. 01d,02jun97,spm  updated man pages and added ERRNO entries
  25. 01c,06may97,spm  changed memory access to align IP header on four byte boundary
  26. 01b,10apr97,kbw  changed title line to match actual file name 
  27. 01a,07apr97,spm  created by modifying WIDE project DHCP implementation
  28. */
  29. /*
  30. DESCRIPTION
  31. This library implements a relay agent for the Dynamic Host Configuration
  32. Protocol (DHCP).  DHCP is an extension of BOOTP.  Like BOOTP, it allows a 
  33. target to configure itself dynamically by using the network to get 
  34. its IP address, a boot file name, and the DHCP server's address.  The relay 
  35. agent forwards DHCP messages between clients and servers resident on 
  36. different subnets.  The standard DHCP server, if present on a subnet, can 
  37. also forward messages across subnet boundaries.  The relay agent is needed 
  38. only if there is no DHCP server running on the subnet.  The dhcprLibInit()
  39. routine links this library into the VxWorks system.  This happens automatically
  40. if INCLUDE_DHCPR is defined at the time the system is built, as long as 
  41. INCLUDE_DHCPS is <not> also defined.
  42. HIGH-LEVEL INTERFACE
  43. The dhcprInit() routine initializes the relay agent automatically.  The 
  44. relay agent forwards incoming DHCP messages to the IP addresses specified 
  45. at build time in the 'dhcpTargetTbl[]' array.
  46. INTERNAL
  47. The core relay agent code, derived from code developed by the WIDE project,
  48. is located in the dhcpr.c module in the directory /wind/river/target/src/dhcp.
  49. INCLUDE FILES: dhcprLib.h
  50. SEE ALSO: RFC 1541, RFC 1533
  51. */
  52. /* includes */
  53. #include "dhcp/copyright_dhcp.h"
  54. #include "vxWorks.h"
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <netinet/if_ether.h>
  58. #include <netinet/in.h>
  59. #include <netinet/ip.h>
  60. #include <netinet/udp.h>
  61. #include <sys/ioctl.h>
  62. #include "end.h"
  63. #include "ipProto.h"
  64. #include "logLib.h"
  65. #include "rngLib.h"
  66. #include "muxLib.h"
  67. #include "semLib.h"
  68. #include "sockLib.h"
  69. #include "ioLib.h"
  70. #include "dhcprLib.h"
  71. #include "dhcp/dhcp.h"
  72. #include "dhcp/common.h"
  73. #include "dhcp/common_subr.h"
  74. #include "bpfDrv.h"
  75. /* defines */
  76. #define _DHCPR_MAX_DEVNAME 21  /* "/bpf/dhcpr" + max unit number */
  77. /* globals */
  78. IMPORT int  dhcpSPort;  /* Port used by DHCP servers */
  79. IMPORT int  dhcpCPort;  /* Port used by DHCP clients */
  80. IMPORT int  dhcpMaxHops;    /* Hop limit before message is discarded. */
  81. IMPORT struct iovec sbufvec[2];            /* send buffer */
  82. IMPORT struct msg dhcprMsgOut;
  83. int dhcprBufSize;  /* Size of buffer for BPF devices */
  84. char * pDhcprSendBuf;  /* Buffer for transmitting messages */
  85. IMPORT u_short dhcps_port;     /* Server port */
  86. IMPORT u_short dhcpc_port;     /* Client port */
  87. void dhcprCleanup (int checkpoint);
  88. /* locals */
  89. LOCAL BOOL dhcprInitialized = FALSE;
  90. struct if_info *dhcprIntfaceList = NULL;
  91.     /* Berkeley Packet Filter instructions for catching DHCP messages. */
  92. LOCAL struct bpf_insn dhcpfilter[] = {
  93.   BPF_STMT(BPF_LD+BPF_TYPE,0),                /* Save lltype in accumulator */
  94.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 20),  /* IP packet? */
  95.   /*
  96.    * The remaining statements use the (new) BPF_HLEN alias to avoid any
  97.    * link-layer dependencies. The expected length values are assigned to the
  98.    * correct values during startup. The expected destination port is also
  99.    * altered to match the actual value chosen.
  100.    */
  101.   BPF_STMT(BPF_LD+BPF_H+BPF_ABS+BPF_HLEN, 6),    /* A <- IP FRAGMENT field */
  102.   BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 18, 0),         /* OFFSET == 0 ? */
  103.   BPF_STMT(BPF_LDX+BPF_HLEN, 0),          /* X <- frame data offset */
  104.   BPF_STMT(BPF_LD+BPF_H+BPF_IND, 2),      /* A <- IP_LEN field */
  105.   BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 0, 15),     /* IP/UDP headers + DHCP? */
  106.   BPF_STMT(BPF_LD+BPF_B+BPF_IND, 9),      /* A <- IP_PROTO field */
  107.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_UDP, 0, 13),     /* UDP ? */
  108.   BPF_STMT(BPF_LD+BPF_HLEN, 0),           /* A <- frame data offset */
  109.   BPF_STMT(BPF_LDX+BPF_B+BPF_MSH+BPF_HLEN, 0), /* X <- IPHDR LEN field */
  110.   BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),     /* A <- start of UDP datagram */
  111.   BPF_STMT(BPF_MISC+BPF_TAX, 0),          /* X <- start of UDP datagram */
  112.   BPF_STMT(BPF_LD+BPF_H+BPF_IND, 2),      /* A <- UDP DSTPORT */
  113.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 67, 0, 7), /* check DSTPORT */
  114.   BPF_STMT(BPF_LD+BPF_H+BPF_IND, 4),      /* A <- UDP LENGTH */
  115.   BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 0, 5), /* UDP header + DHCP? */
  116.   BPF_STMT(BPF_LD+BPF_B+BPF_IND, 11),      /* A <- DHCP hops field */
  117.   BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, -1, 3, 0),   /* -1 replaced with max hops */
  118.   BPF_STMT(BPF_LD+BPF_W+BPF_IND, 244),    /* A <- DHCP options */
  119.   BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x63825363, 0, 1),
  120.                                                  /* Matches magic cookie? */
  121.   BPF_STMT(BPF_RET+BPF_K+BPF_HLEN, DFLTDHCPLEN + UDPHL + IPHL),
  122.                                            /*
  123.                                             * ignore data beyond expected
  124.                                             * size (some drivers add padding).
  125.                                             */
  126.   BPF_STMT(BPF_RET+BPF_K, 0)          /* unrecognized message: ignore frame */
  127.   };
  128. LOCAL struct bpf_program dhcpread = {
  129.     sizeof (dhcpfilter) / sizeof (struct bpf_insn),
  130.     dhcpfilter
  131.     };
  132. /*******************************************************************************
  133. *
  134. * dhcprLibInit - initialize DHCP relay agent library
  135. *
  136. * This routine links the DHCP relay agent code into the runtime image and
  137. * allocates storage for incoming DHCP messages. The <maxSize> parameter
  138. * specifies the maximum length supported for any DHCP message, including
  139. * the UDP and IP headers and the largest link level header for all supported
  140. * devices. The smallest valid value for the <maxSize> parameter is 576 bytes,
  141. * corresponding to the minimum IP datagram a host must accept. Larger values
  142. * will allow the relay agent to handle longer DHCP messages.
  143. *
  144. * This routine must be called before calling any other library routines.
  145. * The routine is called automatically if INCLUDE_DHCPR is defined at the
  146. * time the system is built and assigns the maximum size to the value
  147. * specified by the DHCPR_MAX_MSGSIZE constant.
  148. * RETURNS: OK, or ERROR if initialization fails.
  149. *
  150. * ERRNO: N/A
  151. *
  152. * NOMANUAL
  153. */
  154. STATUS dhcprLibInit
  155.     (
  156.     int  maxSize  /* largest DHCP message supported, in bytes */
  157.     )
  158.     {
  159.     if (dhcprInitialized)
  160.         return (OK);
  161.     if (maxSize < DFLTDHCPLEN + UDPHL + IPHL)
  162.         return (ERROR);
  163.     if (bpfDrv () == ERROR)
  164.         return (ERROR);
  165.     pDhcprSendBuf = (char *)memalign (4, maxSize);
  166.     if (pDhcprSendBuf == NULL)
  167.         return (ERROR);
  168.     dhcprBufSize = maxSize + sizeof (struct bpf_hdr);
  169.     dhcprInitialized = TRUE;
  170.     return (OK);
  171.     }
  172. /*******************************************************************************
  173. *
  174. * dhcprInit - set up the DHCP relay agent parameters and data structures
  175. *
  176. * This routine creates the necessary data structures to monitor the specified
  177. * network interfaces for incoming DHCP messages and forward the messages to
  178. * the given Internet addresses. It may be called after the dhcprLibInit()
  179. * routine has initialized the global data structures.
  180. *
  181. * The <ppIf> argument provides a list of devices which the relay agent will
  182. * monitor to forward packets. The relay agent supports devices attached
  183. * to the IP protocol with the MUX/END interface or BSD Ethernet devices
  184. * attached to that protocol. Each device must be capable of sending broadcast
  185. * messages and the MTU size of the interface must be large enough to receive
  186. * a minimum IP datagram of 576 bytes.
  187. * RETURNS: OK, or ERROR if could not initialize.
  188. *
  189. * ERRNO: N/A
  190. *
  191. * NOMANUAL
  192. */
  193. STATUS dhcprInit
  194.     (
  195.     struct ifnet ** ppIf,  /* network devices used by server */
  196.     int numDev,  /* number of devices */
  197.     DHCP_TARGET_DESC *  pTargetTbl,  /* table of receiving DHCP servers */
  198.     int                 targetSize  /* size of DHCP server table */
  199.     )
  200.     {
  201.     struct if_info *pIf = NULL;          /* pointer to interface */
  202.     char bpfDevName [_DHCPR_MAX_DEVNAME];  /* "/bpf/dhcpr" + max unit number */
  203.     int bpfDev;
  204.     int loop;
  205.     int result;
  206.     struct ifreq ifr;
  207.     if (!dhcprInitialized)
  208.         return (ERROR);
  209.     if (ppIf == NULL)
  210.         return (ERROR);
  211.     if (numDev == 0)
  212.         return (ERROR);
  213.     if (bpfDevCreate ("/bpf/dhcpr", numDev, dhcprBufSize) == ERROR)
  214.         return (ERROR);
  215.     /* Validate the MTU size for each device. */
  216.     for (loop = 0; loop < numDev; loop++)
  217.         {
  218.         if (ppIf[loop]->if_mtu == 0)    /* No MTU size given: not attached? */
  219.             return (ERROR);
  220.         if (ppIf[loop]->if_mtu < DHCP_MSG_SIZE)
  221.             return (ERROR);
  222.         }
  223.     /*
  224.      * Alter the filter program to check for the correct length values and
  225.      * use the specified UDP destination port and maximum hop count.
  226.      */
  227.       /* IP length must at least equal a DHCP message with 4 option bytes. */
  228.     dhcpfilter [6].k = (DFLTDHCPLEN - DFLTOPTLEN + 4) + UDPHL + IPHL;
  229.     dhcpfilter [14].k = dhcpSPort;   /* Use actual destination port in test. */
  230.        /* UDP length must at least equal a DHCP message with 4 option bytes. */
  231.     dhcpfilter [16].k = (DFLTDHCPLEN - DFLTOPTLEN + 4) + UDPHL;
  232.     dhcpfilter [18].k = dhcpMaxHops;   /* Use real maximum hop count. */
  233.     /* Store the interface control information and get each BPF device. */
  234.     for (loop = 0; loop < numDev; loop++)
  235.         {
  236.         pIf = (struct if_info *)calloc (1, sizeof (struct if_info));
  237.         if (pIf == NULL) 
  238.             {
  239.             logMsg ("Memory allocation error.n", 0, 0, 0, 0, 0, 0);
  240.             dhcprCleanup (1);
  241.             return (ERROR);
  242.             }
  243.         pIf->buf = (char *)memalign (4, dhcprBufSize);
  244.         if (pIf->buf == NULL)
  245.             {
  246.             logMsg ("Memory allocation error.n", 0, 0, 0, 0, 0, 0);
  247.             dhcprCleanup (1);
  248.             return (ERROR);
  249.             }
  250.         bzero (pIf->buf, DHCP_MSG_SIZE);
  251.         sprintf (bpfDevName, "/bpf/dhcpr%d", loop);
  252.         bpfDev = open (bpfDevName, 0, 0);
  253.         if (bpfDev < 0)
  254.             {
  255.             logMsg ("BPF device creation error.n", 0, 0, 0, 0, 0, 0);
  256.             dhcprCleanup (1);
  257.             return (ERROR);
  258.             }
  259.         /* Enable immediate mode for reading messages. */
  260.         result = 1;
  261.         result = ioctl (bpfDev, BIOCIMMEDIATE, (int)&result);
  262.         if (result != 0)
  263.             {
  264.             logMsg ("BPF device creation error.n", 0, 0, 0, 0, 0, 0);
  265.             dhcprCleanup (1);
  266.             return (ERROR);
  267.             }
  268.         result = ioctl (bpfDev, BIOCSETF, (int)&dhcpread);
  269.         if (result != 0)
  270.             {
  271.             logMsg ("BPF filter assignment error.n", 0, 0, 0, 0, 0, 0);
  272.             dhcprCleanup (1);
  273.             return (ERROR);
  274.             }
  275.         bzero ( (char *)&ifr, sizeof (struct ifreq));
  276.         sprintf (ifr.ifr_name, "%s%d", ppIf[loop]->if_name,
  277.                                        ppIf[loop]->if_unit);
  278.         result = ioctl (bpfDev, BIOCSETIF, (int)&ifr);
  279.         if (result != 0)
  280.             {
  281.             logMsg ("BPF interface attachment error.n", 0, 0, 0, 0, 0, 0);
  282.             dhcprCleanup (1);
  283.             return (ERROR);
  284.             }
  285.         pIf->next = dhcprIntfaceList;
  286.         dhcprIntfaceList = pIf;
  287.         /* Fill in device name and hardware address. */
  288.         sprintf (pIf->name, "%s", ppIf[loop]->if_name);
  289.         pIf->unit = ppIf[loop]->if_unit;
  290.         pIf->bpfDev = bpfDev;
  291.         pIf->mtuSize = ppIf[loop]->if_mtu;
  292.         }
  293.     /* Access target DHCP server data. */
  294.     pDhcpRelayTargetTbl = pTargetTbl;
  295.   /* read database of DHCP servers */
  296.     if (targetSize != 0)
  297.         read_server_db (targetSize); 
  298.     if (dhcpNumTargets == 0)
  299.         {
  300.         logMsg ("DHCP relay agent server table is empty -- aborting.n",
  301.                 0, 0, 0, 0, 0, 0);
  302.         dhcprCleanup(2);
  303.         return (ERROR);
  304.         }
  305.     /* Use defined ports for client and server. */
  306.     dhcps_port = htons (dhcpSPort);
  307.     dhcpc_port = htons (dhcpCPort);
  308.     /* Fill in subnet mask and IP address for each monitored interface. */
  309.     pIf = dhcprIntfaceList;
  310.     while (pIf != NULL)
  311.         { 
  312.         if (open_if (pIf) < 0) 
  313.             {
  314.             dhcprCleanup (2);
  315.             return (ERROR);
  316.             }
  317.         pIf = pIf->next;
  318.         }
  319.     return (OK);
  320.     }
  321. /*******************************************************************************
  322. *
  323. * dhcprCleanup - remove data structures
  324. *
  325. * This routine frees all dynamically allocated memory obtained by the DHCP
  326. * relay agent.  It is called at multiple points before the program exits due to
  327. * an error occurring or manual shutdown.  The checkpoint parameter indicates 
  328. * which data structures have been created.
  329. *
  330. * RETURNS: N/A
  331. *
  332. * ERRNO: N/A
  333. *
  334. * NOMANUAL
  335. */
  336. void dhcprCleanup 
  337.     (
  338.     int checkpoint  /* Progress identifier indicating created resources */
  339.     )
  340.     {
  341.     int current = 0;
  342.     struct if_info *pIf;
  343.     DHCP_SERVER_DESC *  pServer;
  344.     int loop;
  345.     /* Checkpoint 0 is empty. */
  346.     current++;
  347.     if (current > checkpoint)
  348.         return;
  349.     while (dhcprIntfaceList != NULL)         /* Checkpoint 1 */
  350.         {
  351.         pIf = dhcprIntfaceList;
  352.         if (pIf->buf != NULL)
  353.             {
  354.             if (pIf->bpfDev >= 0)
  355.                 close (pIf->bpfDev);
  356.             free (pIf->buf);
  357.             }
  358.         dhcprIntfaceList = dhcprIntfaceList->next;
  359.         free (pIf);
  360.         }
  361.     bpfDevDelete ("/bpf/dhcpr");
  362.     current++;
  363.     if (current > checkpoint)
  364.         return;
  365.     /* Remove elements of circular list created by read_server_db(). */
  366.                                              /* Checkpoint 2 */
  367.     for (loop = 0; loop < dhcpNumTargets; loop++)
  368.         {
  369.         pServer = pDhcpTargetList;
  370.         pDhcpTargetList = pDhcpTargetList->next;
  371.         free (pServer);
  372.         }
  373.     current++;
  374.     if (current > checkpoint)
  375.         return;
  376.     return;
  377.     }