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

VxWorks

开发平台:

C/C++

  1. /* dhcpRelay.c - DHCP server and relay agent shared code library */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01e,07may02,wap  Put debug messages under DHCPR_DEBUG (SPR #76495)
  8. 01d,27mar02,wap  call ip_mloopback() rather than calling looutput() directly
  9.                  (SPR #72246)
  10. 01c,22mar02,wap  avoid division by zero in dhcpServerRelay() (SPR #74456)
  11. 01b,06dec01,wap  Add NPT support
  12. 01a,12oct01,rae  merge from truestack ver 01n, base 01f (SPR #69547)
  13. 01i,17nov00,spm  added support for BSD Ethernet devices
  14. 01h,24oct00,spm  fixed merge from tor3_x branch and updated mod history
  15. 01g,23oct00,niq  merged from version 01h of tor3_x branch (base version 01f)
  16. 01f,04dec97,spm  added code review modifications
  17. 01e,06oct97,spm  split interface name into device name and unit number; fixed
  18.                  errors in debugging output
  19. 01d,02jun97,spm  changed DHCP option tags to prevent name conflicts (SPR #8667)
  20.                  and updated man pages
  21. 01c,28apr97,spm  limited maximum number of hops to 16 for RFC compliance
  22. 01b,18apr97,spm  added conditional include DHCPR_DEBUG for displayed output
  23. 01a,07apr97,spm  created by modifying WIDE project DHCP implementation
  24. */
  25. /*
  26. DESCRIPTION
  27. This library contains the code used by the DHCP relay agent to transfer 
  28. packets between DHCP or BOOTP clients and DHCP servers. The DHCP server
  29. will also use this code if configured to act as a relay agent. The
  30. library also includes the shared transmit routine which sends unicast
  31. packets to a DHCP client without performing address resolution, since
  32. the destination IP address is not yet resolvable.
  33. INCLUDE_FILES: dhcprLib.h
  34. */
  35. /*
  36.  * WIDE Project DHCP Implementation
  37.  * Copyright (c) 1995 Akihiro Tominaga
  38.  * Copyright (c) 1995 WIDE Project
  39.  * All rights reserved.
  40.  *
  41.  * Permission to use, copy, modify and distribute this software and its
  42.  * documentation is hereby granted, provided only with the following
  43.  * conditions are satisfied:
  44.  *
  45.  * 1. Both the copyright notice and this permission notice appear in
  46.  *    all copies of the software, derivative works or modified versions,
  47.  *    and any portions thereof, and that both notices appear in
  48.  *    supporting documentation.
  49.  * 2. All advertising materials mentioning features or use of this software
  50.  *    must display the following acknowledgement:
  51.  *      This product includes software developed by WIDE Project and
  52.  *      its contributors.
  53.  * 3. Neither the name of WIDE Project nor the names of its contributors
  54.  *    may be used to endorse or promote products derived from this software
  55.  *    without specific prior written permission.
  56.  *
  57.  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND WIDE
  58.  * PROJECT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  59.  * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ALSO, THERE
  60.  * IS NO WARRANTY IMPLIED OR OTHERWISE, NOR IS SUPPORT PROVIDED.
  61.  *
  62.  * Feedback of the results generated from any improvements or
  63.  * extensions made to this software would be much appreciated.
  64.  * Any such feedback should be sent to:
  65.  * 
  66.  *  Akihiro Tominaga
  67.  *  WIDE Project
  68.  *  Keio University, Endo 5322, Kanagawa, Japan
  69.  *  (E-mail: dhcp-dist@wide.ad.jp)
  70.  *
  71.  * WIDE project has the rights to redistribute these changes.
  72.  */
  73. /* includes */
  74. #include "vxWorks.h"
  75. #include "vxLib.h"             /* checksum() declaration. */
  76. #include <stdio.h>
  77. #include <stdlib.h>
  78. #include <sys/ioctl.h>
  79. #include <netinet/in.h>
  80. #include <arpa/inet.h>
  81. #include "logLib.h"
  82. #include "sockLib.h"
  83. #include "ioLib.h"
  84. #include "ipProto.h"  /* IP_DRV_CTRL definition. */
  85. #include "muxLib.h"
  86. #include "tickLib.h"  /* tickGet() declaration. */
  87. #ifdef DHCPR_DEBUG
  88. #include "inetLib.h"
  89. #endif
  90. #include "dhcprLib.h"
  91. #include "dhcp/dhcp.h"
  92. #include "dhcp/common.h"
  93. #include "dhcp/common_subr.h"
  94. /* globals */
  95. #ifndef VIRTUAL_STACK
  96. DHCP_TARGET_DESC *pDhcpRelayTargetTbl;
  97. struct server *pDhcpTargetList = NULL;
  98. int dhcpNumTargets = 0;
  99. struct msg dhcpMsgIn;
  100. struct msg dhcprMsgOut;
  101. u_short dhcps_port;
  102. u_short dhcpc_port;
  103. #else
  104. #include "netinet/vsLib.h"
  105. #include "netinet/vsDhcps.h"
  106. #endif /* VIRTUAL_STACK */
  107. /* forward declarations */
  108. IMPORT void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *,
  109.                     struct rtentry *rt);
  110. void dhcpServerRelay (struct if_info *);
  111. void dhcpClientRelay (struct if_info *, int, char *);
  112. LOCAL STATUS forwarding();
  113. /*******************************************************************************
  114. *
  115. * dhcpsSend - transmit an outgoing DHCP message
  116. *
  117. * This routine uses the MUX interface to send an IP packet containing a
  118. * DHCP message independently of the link level type. It is derived from
  119. * the ipOutput() routine in the ipProto.c module, but uses the available
  120. * hardware address of the original sender as the destination link-level
  121. * address instead of performing address resolution.
  122. *
  123. * Bypassing the normal address resolution process is required since the
  124. * destination IP address has not yet been assigned so (for instance)
  125. * ARP requests would fail, preventing delivery of the reply.
  126. *
  127. * RETURNS: OK, or ERROR if send fails.
  128. *
  129. * ERRNO: N/A
  130. *
  131. * NOMANUAL
  132. */
  133. STATUS dhcpsSend
  134.     (
  135.     struct ifnet *  pIf,      /* interface for sending message */
  136.     char *  pHwAddr,  /* destination link-level address */
  137.     int  hlen,     /* size of link-level address, in bytes */
  138.     struct sockaddr_in * pDest,   /* destination IP address for message */
  139.     char *  pData,    /* IP packet containing DHCP message */
  140.     int  size,     /* amount of data to send */
  141.     BOOL  broadcastFlag   /* broadcast packet? */
  142.     )
  143.     {
  144.     IP_DRV_CTRL * pDrvCtrl;     /* Protocol-specific information. */
  145.     void *        pIpCookie;    /* Result of muxBind() routine for device */
  146.     struct mbuf * pMbuf;
  147.     u_short etype;
  148.     int s;
  149.     if ((pIf->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  150.         return (ERROR);    /* ENETDOWN */
  151.     pDrvCtrl = (IP_DRV_CTRL *)pIf->pCookie;
  152.     if (pDrvCtrl == NULL)    /* Undefined error in original transmit code. */
  153.         return (ERROR);
  154.     pIpCookie = pDrvCtrl->pIpCookie;
  155.     if (pIpCookie == NULL)
  156.         return (ERROR);    /* EINVAL */
  157.     pMbuf = bcopy_to_mbufs (pData, size, 0, pIf, NONE);
  158.     if (pMbuf == NULL)
  159.         return (ERROR);    /* ENOBUFS */
  160.     s = splnet ();
  161.     pIf->if_lastchange = tickGet ();
  162.     /* Setup existing mBlk structures and build link-level header. */
  163.     etype = htons (ETHERTYPE_IP);
  164.     pDrvCtrl->pSrc->m_data = (char *)&((struct arpcom *)pIf)->ac_enaddr;
  165.     bcopy (pHwAddr, (char *)pDrvCtrl->pDstAddr, hlen);
  166.     pDrvCtrl->pDst->mBlkHdr.reserved = etype;
  167.     pDrvCtrl->pSrc->mBlkHdr.reserved = etype;
  168.     if (broadcastFlag)
  169.         {
  170.         /*
  171.          * Use the registered resolve routine to get the link-level broadcast.
  172.          */
  173.         pMbuf->mBlkHdr.mFlags |= M_BCAST;
  174.         /* Loopback a copy of the data if using a simplex interface. */
  175.         if (pIf->if_flags & IFF_SIMPLEX)
  176.             {
  177.             ip_mloopback (pIf, pMbuf, (struct sockaddr_in *)pDest, NULL);
  178.             }
  179.         }
  180.     if (pDrvCtrl->nptFlag)
  181.         {
  182.         if (pIf->if_addrlen)
  183.             {
  184.             M_PREPEND(pMbuf, pIf->if_addrlen, M_DONTWAIT);
  185.             if (pMbuf == NULL)
  186.                 {
  187.                 netMblkClChainFree (pMbuf);
  188.                 return(ERROR);
  189.                 }
  190.             ((M_BLK_ID)pMbuf)->mBlkPktHdr.rcvif = 0;
  191.             /* Store the destination address. */
  192.             bcopy (pDrvCtrl->pDstAddr, pMbuf->m_data, pIf->if_addrlen);
  193.             }
  194.         /* Save the network protocol type. */
  195.         ((M_BLK_ID)pMbuf)->mBlkHdr.reserved = etype;
  196.         }
  197.     else
  198.         {
  199.         pMbuf = muxLinkHeaderCreate (pDrvCtrl->pIpCookie, pMbuf,
  200.                                      pDrvCtrl->pSrc,
  201.                                      pDrvCtrl->pDst, broadcastFlag);
  202.         if (pMbuf == NULL)
  203.             {
  204.             netMblkClChainFree (pMbuf);
  205.             return (ERROR);    /* ENOBUFS */
  206.             }
  207.         }
  208.     /*
  209.      * Queue message on interface, and start output if interface
  210.      * not yet active.
  211.      */
  212.     if (IF_QFULL(&pIf->if_snd))
  213.         {
  214.         IF_DROP(&pIf->if_snd);
  215.         splx(s);
  216.         netMblkClChainFree (pMbuf);
  217.         return (ERROR);    /* ENOBUFS */
  218.         }
  219.     IF_ENQUEUE(&pIf->if_snd, pMbuf);
  220.     pIf->if_start (pIf);
  221.     pIf->if_obytes += pMbuf->mBlkHdr.mLen;
  222.     if (pMbuf->m_flags & M_MCAST || pMbuf->m_flags & M_BCAST)
  223.         pIf->if_omcasts++;
  224.     splx(s);
  225.     return (OK);
  226.     }
  227. /*******************************************************************************
  228. *
  229. * dhcpServerRelay - send incoming DHCP/BOOTP message to client port
  230. *
  231. * This routine relays a DHCP or BOOTP message to the client port of 
  232. * every DHCP server or relay agent whose IP address is contained in the 
  233. * circular linked list of targets. That list is constructed during startup of 
  234. * the relay agent (or server, if configured to relay messages). The routine
  235. * accesses global pointers already set to indicate the outgoing message. 
  236. * All messages are discarded after the hops field exceeds 16 to comply with
  237. * the relay agent behavior specified in RFC 1542. The relay agent normally
  238. * discards such messages before this routine is called. They will only
  239. * be received by this routine if the user ignores the instructions in the
  240. * manual and sets the value of DHCP_MAX_HOPS higher than 16.
  241. *
  242. * RETURNS: N/A
  243. *
  244. * ERRNO: N/A
  245. *
  246. * NOMANUAL
  247. */
  248. void dhcpServerRelay
  249.     (
  250.     struct if_info *ifp
  251.     )
  252.     {
  253.     unsigned int hash;
  254.     int i;
  255.     struct server *srvp;
  256.     dhcpMsgIn.dhcp->hops++;
  257.     if (dhcpMsgIn.dhcp->hops >= 17)    /* RFC limits to 16 hops - ignore. */
  258.         return;
  259.     /*
  260.      * If the target table is empty, bail, otherwise
  261.      * trying to do the hash computation below will yield a
  262.      * division by zero.
  263.      */
  264.     if (dhcpNumTargets == 0)
  265.         return;
  266.     if (dhcpMsgIn.dhcp->giaddr.s_addr == 0)
  267.         dhcpMsgIn.dhcp->giaddr.s_addr = ifp->ipaddr.s_addr;
  268.     /* Quick and dirty load balancing - pick starting point in circular list. */
  269.     hash = (unsigned)checksum( (u_short *)dhcpMsgIn.dhcp->chaddr, 
  270.                                (MAX_HLEN / 2));
  271.     hash %= dhcpNumTargets;
  272.     srvp = pDhcpTargetList;
  273.     for (i = 0; i < hash; i++)
  274.         srvp = srvp->next;
  275.     forwarding (srvp);
  276.     return;
  277.     }
  278. /*******************************************************************************
  279. *
  280. * forwarding - send DHCP/BOOTP message to target address
  281. *
  282. * This routine relays a DHCP or BOOTP message to the specified target address.
  283. *
  284. * RETURNS: N/A
  285. *
  286. * ERRNO: N/A
  287. *
  288. * NOMANUAL
  289. */
  290. static STATUS forwarding
  291.     (
  292.     struct server *srvp
  293.     )
  294.     {
  295.     int i, n;
  296.     int sockfd = -1;
  297.     int msgsize = DHCPLEN (dhcpMsgIn.udp);
  298.     struct sockaddr_in my_addr, serv_addr;
  299.     int result;
  300. #ifdef DHCPR_DEBUG
  301.     char output [INET_ADDR_LEN];
  302. #endif
  303.     if ( (sockfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) 
  304.         {
  305. #ifdef DHCPR_DEBUG
  306.         logMsg ("socket() error in forwarding()n", 0, 0, 0, 0, 0, 0);
  307. #endif
  308.         return (ERROR);
  309.         }
  310.     bzero ((char *)&my_addr, sizeof (my_addr));
  311.     my_addr.sin_family = AF_INET;
  312.     my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
  313.     my_addr.sin_port = dhcpc_port;  /* Servers expect client port. */
  314.     if (bind (sockfd, (struct sockaddr *) &my_addr, sizeof (my_addr)) < 0) 
  315.         {
  316. #ifdef DHCPR_DEBUG
  317.         logMsg("bind() error in forwarding()n", 0, 0, 0, 0, 0, 0);
  318. #endif
  319.         close (sockfd);
  320.         return (ERROR);
  321.         }
  322.     dhcprMsgOut.dhcp = dhcpMsgIn.dhcp;
  323.     result = setsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, 
  324.                          (char *)&msgsize, sizeof (msgsize));
  325.     if (result < 0) 
  326.         {
  327. #ifdef DHCPR_DEBUG
  328.         logMsg ("Warning: can't set send buffer in forwarding().n",
  329.                  0, 0, 0, 0, 0, 0);
  330. #endif
  331.         close (sockfd);
  332.         return (ERROR);
  333.         }
  334.   
  335.     n = sizeof(serv_addr);
  336.     for (i = 0; i < dhcpNumTargets; i++) 
  337.         {
  338.         bzero ((char *)&serv_addr, n);
  339.         serv_addr.sin_family = AF_INET;
  340.         serv_addr.sin_addr.s_addr = srvp->ip.s_addr;
  341.         serv_addr.sin_port = dhcps_port;
  342. #ifdef DHCPR_DEBUG
  343.         inet_ntoa_b (srvp->ip, output);
  344.         printf ("Server relay: sending %d bytes to %s.n", 
  345.                 msgsize, output);
  346. #endif
  347.         sendto (sockfd, (char *)dhcprMsgOut.dhcp, msgsize, 0, 
  348.                   (struct sockaddr *)&serv_addr, n);
  349.         srvp = srvp->next;
  350.         }
  351.     close (sockfd);
  352.     return (OK);
  353.     }
  354. /*******************************************************************************
  355. *
  356. * dhcpClientRelay - send DHCP/BOOTP replies to client
  357. *
  358. * This routine relays a DHCP or BOOTP reply to the client which generated
  359. * the initial request. The routine accesses global pointers already set to 
  360. * indicate the reply. All messages are discarded after the hops field exceeds 
  361. * 16 to comply with the relay agent behavior specified in RFC 1542. The relay 
  362. * agent normally discards such messages before this routine is called. They 
  363. * will only be received by this routine if the user ignores the instructions 
  364. * in the manual and sets the value of DHCP_MAX_HOPS higher than 16.
  365. *
  366. * RETURNS: N/A
  367. *
  368. * ERRNO: N/A
  369. *
  370. * NOMANUAL
  371. */
  372. void dhcpClientRelay
  373.     (
  374.     struct if_info *list,
  375.     int dhcplen,
  376.     char * pSendBuf    /* Transmit buffer for fragmented message. */
  377.     )
  378.     {
  379.     int total;
  380.     char devName [10];
  381.     struct if_info *ifp;
  382.     struct sockaddr_in dest;
  383.     BOOL bcastFlag;
  384.     int msgtype = 0;
  385.     char *option = NULL;
  386.     struct ifnet *pIf;
  387.     STATUS result;
  388. #ifdef DHCPR_DEBUG
  389.     char srcAddr [INET_ADDR_LEN];
  390.     char dstAddr [INET_ADDR_LEN];
  391. #endif
  392.     if (dhcpMsgIn.dhcp->hops >= 17)    /* RFC limits to 16 hops - ignore. */
  393.         return;
  394.     ifp = list;
  395.     while (ifp != NULL) 
  396.         {
  397.         if (ifp->ipaddr.s_addr == dhcpMsgIn.dhcp->giaddr.s_addr)
  398.             break;
  399.         ifp = ifp->next;
  400.         }
  401.     if (ifp == NULL) 
  402.         { 
  403. #ifdef DHCPR_DEBUG
  404.         inet_ntoa_b (dhcpMsgIn.ip->ip_src, srcAddr);
  405.         logMsg ("Warning: DHCP message from server(%s) has no interface.n",
  406.          srcAddr, 0, 0, 0, 0, 0);
  407. #endif
  408.         return;
  409.         }
  410.     sprintf (devName, "%s%d", ifp->name, ifp->unit);
  411.     pIf = ifunit (devName);
  412.     if (pIf == NULL)
  413.         {
  414. #ifdef DHCPR_DEBUG
  415.         logMsg ("Warning: couldn't access network interface %s.n", 
  416.                  (int)ifp->name, 0, 0, 0, 0, 0);
  417. #endif
  418.         return;
  419.         }
  420.     if ( (option = pickup_opt (dhcpMsgIn.dhcp, dhcplen, _DHCP_MSGTYPE_TAG)) 
  421.           != NULL) 
  422.         msgtype = *OPTBODY(option);
  423.      /* There is already space for the IP and UDP headers. */
  424.     dhcprMsgOut.dhcp = dhcpMsgIn.dhcp;
  425.     dhcprMsgOut.udp = dhcpMsgIn.udp;
  426.     dhcprMsgOut.ip = dhcpMsgIn.ip;
  427. #ifdef DHCPR_DEBUG
  428.     logMsg ("Client relay: Headers found.n", 0, 0, 0, 0, 0, 0);
  429. #endif
  430. #ifdef DHCPR_DEBUG
  431.     logMsg ("Setting parameters.n", 0, 0, 0, 0, 0, 0);
  432. #endif
  433.     bzero ( (char *)&dest, sizeof (struct sockaddr_in));
  434.     dest.sin_len = sizeof (struct sockaddr_in);
  435.     dest.sin_family = AF_INET;
  436.     if (ISBRDCST (dhcpMsgIn.dhcp->flags)) 
  437.         {
  438. #ifdef DHCPR_DEBUG
  439.         logMsg ("Broadcasting reply.n", 0, 0, 0, 0, 0, 0);
  440. #endif
  441.         dest.sin_addr.s_addr = dhcprMsgOut.ip->ip_dst.s_addr = 0xffffffff;
  442.         dhcprMsgOut.ip->ip_src.s_addr = ifp->ipaddr.s_addr;
  443.         bcastFlag = TRUE;
  444.         } 
  445.     else 
  446.         {
  447.         if (msgtype == DHCPNAK)
  448.             {
  449.             dest.sin_addr.s_addr = dhcprMsgOut.ip->ip_dst.s_addr = 0xffffffff;
  450.             bcastFlag = TRUE;
  451.             }
  452.         else
  453.             {
  454.             dhcprMsgOut.ip->ip_dst.s_addr = dhcpMsgIn.dhcp->yiaddr.s_addr;
  455.             dest.sin_addr.s_addr = dhcpMsgIn.dhcp->yiaddr.s_addr;
  456.             bcastFlag = FALSE;
  457.             }
  458.         dhcprMsgOut.ip->ip_src.s_addr = ifp->ipaddr.s_addr;
  459. #ifdef DHCPR_DEBUG
  460.         inet_ntoa_b (dhcprMsgOut.ip->ip_src, srcAddr);
  461.         inet_ntoa_b (dhcprMsgOut.ip->ip_dst, dstAddr);
  462.         logMsg ("Sending reply from %s to %s.n", srcAddr, dstAddr,
  463.                  0, 0, 0, 0);
  464. #endif
  465.         }
  466.     dhcprMsgOut.udp->uh_sport = dhcps_port;
  467.     dhcprMsgOut.udp->uh_dport = dhcpc_port;
  468.     dhcprMsgOut.udp->uh_ulen = htons (dhcplen + UDPHL);
  469.     dhcprMsgOut.udp->uh_sum = get_udpsum (dhcprMsgOut.ip, dhcprMsgOut.udp);
  470.     dhcprMsgOut.ip->ip_v = IPVERSION;
  471.     dhcprMsgOut.ip->ip_hl = IPHL >> 2;
  472.     dhcprMsgOut.ip->ip_tos = 0;
  473.     dhcprMsgOut.ip->ip_len = htons (dhcplen + UDPHL + IPHL);
  474.     dhcprMsgOut.ip->ip_id = dhcprMsgOut.udp->uh_sum;
  475.     dhcprMsgOut.ip->ip_ttl = 0x20;                       /* XXX */
  476.     dhcprMsgOut.ip->ip_p = IPPROTO_UDP;
  477.     total = dhcplen + IPHL + UDPHL;
  478.     if (total <= pIf->if_mtu) 
  479.         {
  480.         /*
  481.          * The message fits within the MTU size of the outgoing interface.
  482.          * Send it "in place", altering the UDP and IP headers of the
  483.          * original (incoming) message's buffer.
  484.          */
  485.         dhcprMsgOut.ip->ip_off = 0;
  486.         dhcprMsgOut.ip->ip_sum = get_ipsum (dhcprMsgOut.ip);
  487. #ifdef DHCPR_DEBUG
  488.         logMsg ("Writing %d bytes.n", total, 0, 0, 0, 0, 0);
  489. #endif
  490.         result = dhcpsSend (pIf,
  491.                             dhcprMsgOut.dhcp->chaddr, dhcprMsgOut.dhcp->hlen,
  492.                             &dest, (char *)dhcprMsgOut.ip, total, bcastFlag);
  493. #ifdef DHCPR_DEBUG
  494.        if (result != OK)
  495.             logMsg ("Error %d relaying message to client.n", errno, 
  496.                     0, 0, 0, 0, 0);
  497. #endif
  498.         } 
  499.     else 
  500.         {
  501.         /*
  502.          * The message exceeds the MTU size of the outgoing interface.
  503.          * Split it into fragments and send them using the provided
  504.          * transmit buffer.
  505.          */
  506.         char *n, *end, *begin;
  507.         begin = (char *) dhcprMsgOut.udp;
  508.         end = &begin [total];
  509.         total = pIf->if_mtu - IPHL;
  510.         for (n = begin; n < end; n += total) 
  511.             {
  512.             if ((end - n) >= total) 
  513.                 {
  514.                 dhcprMsgOut.ip->ip_len = htons (pIf->if_mtu);
  515.                 dhcprMsgOut.ip->ip_off = htons(IP_MF | ((((n - begin) / 8)) & 0x1fff));
  516.                 dhcprMsgOut.ip->ip_sum = get_ipsum (dhcprMsgOut.ip);
  517.                 bcopy ( (char *)dhcprMsgOut.ip, pSendBuf, IPHL);
  518.                 bcopy ( (char *)n, &pSendBuf [IPHL], total); 
  519.                 } 
  520.             else 
  521.                 {
  522.                 /* Last fragment of message. */
  523.                 dhcprMsgOut.ip->ip_len = htons (IPHL + end - n);
  524.                 dhcprMsgOut.ip->ip_off = htons(((n - begin) / 8) & 0x1fff);
  525.                 dhcprMsgOut.ip->ip_sum = get_ipsum(dhcprMsgOut.ip);
  526.                 bcopy ( (char *)dhcprMsgOut.ip, pSendBuf, IPHL);
  527.                 bcopy ( (char *)n, &pSendBuf [IPHL], end - n); 
  528.                 }
  529.             dhcpsSend (pIf,
  530.                        dhcprMsgOut.dhcp->chaddr, dhcprMsgOut.dhcp->hlen,
  531.                        &dest, pSendBuf, ntohs (dhcprMsgOut.ip->ip_len),
  532.                        bcastFlag);
  533.             }
  534.         /* Send complete: clean the transmit buffer before later use. */
  535.         bzero (pSendBuf, total + IPHL);
  536.         }
  537.     return;
  538.     }
  539. /*******************************************************************************
  540. *
  541. * read_server_db - read IP addresses to receive relayed packets
  542. *
  543. * This routine extracts the IP address entries hard-coded into usrNetwork.c as 
  544. * dhcpTargetTbl[] and stores them in a circular linked list. Each of these 
  545. * address entries must be on a different subnet from the calling server
  546. * or relay agent. Each entry in the list will receive a copy of every DHCP or
  547. * BOOTP message arriving at the client port.
  548. *
  549. * RETURNS: N/A
  550. *
  551. * ERRNO: N/A
  552. *
  553. * NOMANUAL
  554. */
  555. void read_server_db (int dbsize)
  556.     {
  557.     char targetIP [sizeof ("255.255.255.255")];
  558.     struct server *srvp = NULL;
  559.     struct server *lastp = NULL;
  560.     int loop;
  561.     /* Read IP addresses of target servers or relay agents. */
  562.     for (loop = 0; (loop < dbsize) &&
  563.  (pDhcpRelayTargetTbl [loop].pAddress); loop++)
  564.         {
  565.         sprintf (targetIP, "%s", pDhcpRelayTargetTbl [loop].pAddress);
  566.         srvp = (struct server *)calloc (1, sizeof (struct server));
  567.         if (srvp == NULL) 
  568.             {
  569. #ifdef DHCPR_DEBUG
  570.             logMsg ("Memory allocation error reading relay target database.n", 
  571.                      0, 0, 0, 0, 0, 0);
  572. #endif
  573.             break;
  574.             }
  575.    
  576.         srvp->ip.s_addr = inet_addr (targetIP);
  577.         if (srvp->ip.s_addr == -1) 
  578.             {
  579. #ifdef DHCPR_DEBUG
  580.             logMsg ("Conversion error reading relay target database.n",
  581.                      0, 0, 0, 0, 0, 0);
  582. #endif
  583.             free (srvp);
  584.             continue;
  585.             }
  586.         dhcpNumTargets++;
  587.         srvp->next = pDhcpTargetList;
  588.         if (pDhcpTargetList == NULL)
  589.             lastp = srvp;
  590.         pDhcpTargetList = srvp;
  591.         }
  592.     if (lastp == NULL)                /* No target DHCP servers. */
  593.         return;
  594.     /* Create circular list of DHCP server addresses. */
  595.     lastp->next = pDhcpTargetList;
  596. #ifdef DHCPR_DEBUG
  597.     logMsg ("read %d entries from relay target database", dhcpNumTargets, 
  598.              0, 0, 0, 0, 0);
  599. #endif
  600.     return;
  601.     }