home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / nb_agent / nba.c < prev    next >
C/C++ Source or Header  |  1992-07-09  |  18KB  |  655 lines

  1. /*
  2.  
  3. ----------------------------------------------------------------------------
  4.  
  5.         Copyright (C) 1990 Novell, Inc.
  6.     
  7.         This software may be freely copied and distributed, provided the 
  8.         above copyright notice is included. It may not be sold, in whole
  9.         or in part, without the prior written consent of Novell, Inc.
  10.  
  11. ----------------------------------------------------------------------------
  12.  
  13.         NBA.C  Netbios Broadcast Agent    /BSB
  14.  
  15.     This is SAMPLE source code, NOT a Novell product, 
  16.         and will not be supported by the technical staff of Novell.
  17.  
  18.     DESCRIPTION:
  19.  
  20.     This program provides an example of how to forward name service
  21.       broadcasts to remote netbios networks connected via gateways or
  22.     routers which do not usually forward such packets.  It is designed
  23.     to be run in either Server mode or Agent mode.
  24.         Server mode requires that this program (NBA) be run on the local
  25.     network. It receives netbios name query broadcasts (status=0x110) and
  26.     replies with a query response (status=0x8500), if the query name and
  27.     internet address entry is found in the HOSTS file.  No reply packet
  28.     is sent if the name is not found in the HOSTS file.
  29.         Agent mode involves running one NBA on the local net, and one on
  30.     the remote network.  The local NBA receives broadcasts on the local
  31.     network, saves pertinent packet information such as client address,
  32.     port, transaction ID, etc., in a control block (header).  The
  33.     packet is then prepended with the NBA header, and then forwarded to
  34.     the remote NBA.  When it is received, the remote NBA strips off
  35.     the header, saves (enqueues) the header, and then the original
  36.     (de-encapsulated) netbios packet is broadcast on the remote network.
  37.     When the remote NBA receive a reply, if at all, to the broadcast,
  38.     the header information is dequeued based on the the transaction id of
  39.     the reply packet.  The destination address, port, and tid of the
  40.      reply packet is then set to the (client) values stored in the
  41.     dequeued NBA header and the resulting packet is sent (directed) back
  42.     to the the client node which made the original broadcast.
  43.         This forwarding of the broadcast and reply packets, in effect,
  44.     internets the name service.
  45.  
  46.     FEATURES/LIMITATIONS:
  47.  
  48.     *    NBA is written to be very portable.  It will run on 680xx
  49.             and Sparc Unix machines as well as 80286/386 OS2 machines and
  50.         should be easily ported to DOS.
  51.  
  52.     *    This program makes extensive use of the HOSTS file.
  53.         Entries must exist for BROADCAST, LOCALHOST, as well
  54.         as any names requiring a response when running NBA in
  55.         server mode.  If subnetting is in use on the network
  56.         the BROADCAST address of the form WW.YY.0xff.0xff may
  57.         not work on some BSD implementations.  In this case an
  58.         appropriate subnet broadcast address should be used.
  59.         A subnet broadcast address has the form:
  60.  
  61.          WW.XX.YY.ZZ   where
  62.  
  63.          WW.XX = the network portion address
  64.             ZZ = the host portion address (all set)
  65.             YY = for a node with a subnet mask of 0xfc, this
  66.                  defines the upper 6 bits of the byte as the subnet
  67.                  portion (set to the subnet value) and the lower
  68.                  2 bits (both set) as part of the host portion.
  69.  
  70.          example:      subnet mask = 0xfc
  71.                        network     = 0x82.0x39
  72.                        broadcast on subnet 1 = 0x82.0x39.0x07.0xff
  73.  
  74.     *    In order to run NBA (port 137) on Unix requires    super-user privilige 
  75.         The port value should only be changed during testing, and
  76.         should always be 137 as this is the UDP name service port.
  77.  
  78.     *       When running NBA in server mode, entries in the HOSTS file
  79.             should be in upper case.
  80.  
  81.     *    Although an agent may receive NBA packets from any number
  82.         of remote NBA agents, it will only forward broadcasts to one remote
  83.         NBA agent.  In other words, an NBA will not simultaneously forward
  84.         a packet to multiple remote NBA's.  This can be accomplished by
  85.         running multiple NBA's on the local net (on different machines)
  86.         each of which will receive broadcasts, but forward the packets to
  87.         different remote agents/networks.
  88.  
  89.     ENHANCEMENTS:
  90.  
  91.         * Change the queuing mechanism to a more dynamic one. At 
  92.                   present the queue is a static array.
  93.         * Make this program run as a detached process, TSR, or
  94.             PM application with an improved user interface.
  95.         * Provide for the support of multiple remote agents as described in
  96.           the LIMITATIONS section above.
  97.  
  98.     BUILD TOOLS:
  99.  
  100.         OS2
  101.  
  102.         This program was built using Novell's Lan Workplace for OS/2 (BSD 4.3
  103.         sockets), MSC 5.10, MS link 5.01.21, POLYTRON Polymake V3.1.
  104.  
  105.         UNIX
  106.  
  107.         C compiler
  108.  
  109.     BUILD INSTRUCTIONS:
  110.  
  111.         required files are:  nba.c, nba.h, name.h, makefile(os2)
  112.  
  113.         unix> cc nba.c
  114.         os2> make nba
  115.  
  116.     USAGE:
  117.  
  118.         nba [[-d] [[-a]{ipaddr}] [[-p]{port}] [[-w]{wport}]]
  119.           where     ipaddr = the Internet Address of the remote NBA Agent.
  120.                  port   = the port used for name service transactions.
  121.                           Default is 137 (UDP Name Service Port)
  122.                  wkport = the "well known port" used for NBA
  123.                           transactions. Default is 3000
  124.                  -d     = Debug flag.  Debug mode prints messages to
  125.                              STDERR.
  126.  
  127.         examples:
  128.  
  129.         >nba
  130.         runs in silent server mode, port 137
  131.  
  132.         >nba -d
  133.         runs in debug server mode, port 137
  134.  
  135.         >nba -d -a130.50.5.115 -p2000 -w5000
  136.         runs in agent mode (for testing), port 2000, NBA port 5000,
  137.         forwarding broadcasts to the remote agent at address 130.50.5.115.
  138.  
  139.  
  140. */
  141.  
  142. #include <stdio.h>
  143. #include <time.h>
  144. #include <ctype.h>
  145. #include <sys/types.h>
  146. #include <sys/socket.h>
  147. #include <netinet/in.h>
  148. #include <netdb.h>
  149. #include <errno.h>
  150. #include <signal.h>
  151. #include "name.h"
  152. #include "nba.h"
  153. #ifdef OS2
  154. #include <bsd43.h>
  155. #endif
  156.  
  157. struct sockaddr_in sock = {AF_INET};
  158. struct sockaddr_in bcast = {AF_INET};
  159. struct sockaddr_in from = {AF_INET};
  160. struct namepkt  nspkt;
  161. struct ba_pkt   bapkt;
  162. struct ba_header baheader;
  163. struct ba_header baq[BAQSIZE];
  164. struct hostent *host;
  165. struct in_addr  inetaddr;
  166. struct in_addr  inet_makeaddr();
  167. ULONG           host_addr = 0L;
  168. ULONG           bcast_addr = 0L;
  169. ULONG           agent_addr = 0L;
  170. ULONG           ipaddr;
  171. ULONG           ipnet;
  172. USHORT          baqindex = 0;
  173. int             nspkt_size, bapkt_size;
  174. USHORT          port = NAME_SERVICE_UDP_PORT;    /* the ns listen port */
  175. USHORT          wkport = NBA_WK_PORT;    /* the ba listen port */
  176. ULONG           batidx = 0;
  177. int             len = sizeof(from);
  178. int             debug = 0;
  179. int             sig();
  180. int             fd, fda;
  181. char            myname[16];
  182. char            othername[16];
  183. BOOL            use_host_file = FALSE;
  184. fd_set          sockset;
  185.  
  186. main(argc, argv)
  187.     int             argc;
  188.     char          **argv;
  189. {
  190.     char           *s;
  191.     int             nfound;
  192.     int             setres, optval;
  193.  
  194.     signal(SIGINT /* SIGHUP */ , sig);
  195.     setbuf(stdout, 0);
  196.     setbuf(stderr, 0);
  197.     while (--argc > 0 && (*++argv)[0] == '-') {
  198.         s = argv[0] + 1;
  199.         switch (*s) {
  200.         case 'd':
  201.             debug = 1;
  202.             fprintf(stderr, "debug enabled\n");
  203.             break;
  204.         case 'p':
  205.             port = atoi(++s);
  206.             break;
  207.         case 'w':
  208.             wkport = atoi(++s);
  209.             break;
  210.         case 'a':
  211. #ifdef    OS2
  212.             ipnet = inet_addr(++s);
  213.             ipaddr = inet_network(s);
  214.             ipaddr = htons((short) ipaddr);
  215.             agent_addr = (ipaddr << 16) | ipnet;
  216.             /* inetaddr = inet_makeaddr(ipnet,ipaddr);  */
  217.             /* agent_addr = inetaddr.S_un.S_addr;          */
  218. #else
  219.             agent_addr = inet_addr(++s);
  220. #endif
  221.             break;
  222.         default:
  223.             fprintf(stderr, "usage: %s nba [[-d] [[-a]{ipaddr}] [[-p]{port}] [[-w]{wport}]]\n", argv[0]);
  224.             exit(1);
  225.         }
  226.     }
  227.  
  228.     if (!agent_addr)
  229.         use_host_file = TRUE;
  230.  
  231.     /* get local network information */
  232.     if (gethostname(myname, sizeof(myname) - 1)) {
  233.         perror("nba: gethostname()");
  234.         exit(1);
  235.     }
  236.     if (debug)
  237.         fprintf(stderr, "nba: myname = %s\n", myname);
  238.     if (strlen(myname) > 15) {
  239.         fprintf(stderr, "nba: - name too long\n");
  240.         exit(1);
  241.     }
  242.     host = gethostbyname(myname);
  243.     if (host) {
  244.         bcopy(host->h_addr, (char *) &host_addr, host->h_length);
  245.     } else {
  246.         perror("nba: gethostbyname() \n");
  247.         exit(1);
  248.     }
  249.  
  250.     if (debug)
  251.         fprintf(stderr, "host_addr  :0x%lx\n", ntohl(host_addr));
  252.     if (debug && (agent_addr))
  253.         fprintf(stderr, "agent_addr :0x%lx\n", ntohl(agent_addr));
  254.  
  255.     /* get broadcast IP Address */
  256.     host = gethostbyname("broadcast");
  257.     if (host) {
  258.         bcopy(host->h_addr, (char *) &bcast_addr, host->h_length);
  259.     } else {
  260.         perror("nba: gethostbyname() \n");
  261.         exit(1);
  262.     }
  263.  
  264.     cvt(myname);        /* convert to upper case */
  265.  
  266.     /* get and bind a socket for netbios name service */
  267.     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  268.         perror("nba: socket()");
  269.         exit(1);
  270.     }
  271.     sock.sin_port = htons(port);
  272.     sock.sin_addr.S_un.S_addr = 0l;
  273.     if (bind(fd, &sock, sizeof(sock)) < 0) {
  274.         perror("nba: bind()");
  275.         exit(1);
  276.     }
  277.     /* get and bind a socket for agent receive */
  278.     if ((fda = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  279.         perror("nba: socket()");
  280.         exit(1);
  281.     }
  282.     sock.sin_port = htons(wkport);
  283.     sock.sin_addr.S_un.S_addr = host_addr;
  284.     if (bind(fda, &sock, sizeof(sock)) < 0) {
  285.         perror("nba: bind()");
  286.         exit(1);
  287.     }
  288.     /* process all Broadcast Repeater (BA) and Name Service (NS) packets */
  289.     while (1) {
  290.         FD_ZERO(&sockset);
  291.         FD_SET(fd, &sockset);
  292.         FD_SET(fda, &sockset);
  293.         /* wait for a pkt on one of the two sockets */
  294.         if ((nfound = select(32, &sockset, NULL, NULL, NULL)) < 0) {
  295.             perror("nba: select()");
  296.             exit(1);
  297.         }
  298.         /* test for NS socket has data */
  299.         if (FD_ISSET(fd, &sockset)) {
  300.             process_ns();    /* process NS packets */
  301.         }
  302.         /* test for BA socket has data */
  303.         if (FD_ISSET(fda, &sockset)) {
  304.             process_ba();    /* process BA packets */
  305.         }
  306.     }
  307. }                /* ba */
  308.  
  309.  
  310. /*
  311.  * process_ba() - process incoming BA agent packets
  312.  */
  313.  
  314. process_ba()
  315. {
  316.     int             i, chsent;
  317.  
  318.  
  319.     /* read the socket */
  320.     if ((bapkt_size = recvfrom(fda, &bapkt,
  321.                   sizeof(struct ba_pkt), 0, &from, &len)) < 0) {
  322.         perror("nba: recvfrom()");
  323.         exit(1);
  324.     }
  325.     if (debug) {
  326.         fprintf(stderr, "|-- NBA PKT -------------------------------\n");
  327.         fprintf(stderr, "| size   = 0x%x\n", bapkt_size);
  328.         fprintf(stderr, "| port   = 0x%x\n", ntohs(from.sin_port));
  329.         fprintf(stderr, "| addr   = 0x%lx\n", ntohl(from.sin_addr.S_un.S_addr));
  330.         fprintf(stderr, "|----------------------------------------\n");
  331.     }
  332.     /* set up the agent tid and change the pkt tid */
  333.     bapkt.baheader.ba_tid = htonl(++batidx);
  334.     bapkt.namepkt.header.nm_tid = NLtoNS(bapkt.baheader.ba_tid);
  335.  
  336.     /* enqueue the header */
  337.     while (baenq(&bapkt)) {
  338.     };            /* keep trying until success (a header
  339.                  * expires) */
  340.  
  341.     /* forward (broadcast) the packet to local net */
  342.     sock.sin_port = htons(port);
  343.     sock.sin_addr.S_un.S_addr = bcast_addr;
  344.  
  345.     if ((chsent = sendto(fd, &bapkt.namepkt, (int) (bapkt_size - BAHEADERSIZE), 0,
  346.                  &sock, SOCKADDRSIZE)) < 0) {
  347.         perror("nba: sendto()");
  348.         exit(1);
  349.     }
  350.     if (debug)
  351.         fprintf(stderr, ">>> Broadcast 0x%x bytes to    Port:0x%x  Addr:0x%lx\n",
  352.             chsent, ntohs(sock.sin_port), ntohl(sock.sin_addr.S_un.S_addr));
  353.  
  354.  
  355. }                /* process_ba */
  356.  
  357.  
  358. /*
  359.  * process_ns() - process incoming name service packets
  360.  */
  361.  
  362. process_ns()
  363. {
  364.     int             i, chsent;
  365.     struct ba_header *phdr;
  366.  
  367.  
  368.     /* read the socket */
  369.     if ((nspkt_size = recvfrom(fd, &bapkt.namepkt,
  370.                  sizeof(struct namepkt), 0, &from, &len)) < 0) {
  371.         perror("nba: recvfrom()");
  372.         exit(1);
  373.     }
  374.     /* if broadcast encapsulate the NS packet and send to BA agent */
  375.     if (!(ntohs(bapkt.namepkt.header.status) & NS_RES_MASK)) {
  376.         /* skip the broadcast if it came from this node */
  377.         if (from.sin_addr.S_un.S_addr != host_addr) {
  378.  
  379.             if (debug) {
  380.                 fprintf(stderr, "|-- NETBIOS PKT --------------------------\n");
  381.                 fprintf(stderr, "| size = 0x%x\n", nspkt_size);
  382.                 fprintf(stderr, "| port = 0x%x\n", ntohs(from.sin_port));
  383.                 fprintf(stderr, "| addr = 0x%lx\n", ntohl(from.sin_addr.S_un.S_addr));
  384.                 fprintf(stderr, "| tid  = 0x%x\n", ntohs(bapkt.namepkt.header.nm_tid));
  385.                 fprintf(stderr, "| type = 0x%x\n", ntohs(bapkt.namepkt.header.status));
  386.                 fprintf(stderr, "|--------------------------------------\n");
  387.             }
  388.             /*
  389.              * if we are running in server mode process the pkt
  390.              * locally
  391.              */
  392.             if (use_host_file) {
  393.                 respond_local(&bapkt.namepkt);
  394.                 return;
  395.             }
  396.             /* set up the baheader */
  397.             baheader.client_addr = from.sin_addr.S_un.S_addr;
  398.             baheader.client_port = NStoNL(from.sin_port);
  399.             baheader.host_addr = host_addr;
  400.             baheader.ns_tid = NStoNL(bapkt.namepkt.header.nm_tid);
  401.  
  402.             /*
  403.              * prepend the packet (in bapkt.namepkt) with the
  404.              * baheader
  405.              */
  406.             bcopy((char *) &baheader, (char *) &bapkt, BAHEADERSIZE);
  407.  
  408.             /* send the packet to the other agent */
  409.             sock.sin_port = htons(wkport);    /* BA "well known" port */
  410.             sock.sin_addr.S_un.S_addr = agent_addr;    /* BA agent address     */
  411.  
  412.  
  413.             if ((chsent = sendto(fd, &bapkt, (int) (nspkt_size + BAHEADERSIZE), 0,
  414.                          &sock, SOCKADDRSIZE)) < 0) {
  415.                 perror("nba: sendto()");
  416.                 exit(1);
  417.             }
  418.             if (debug)
  419.                 fprintf(stderr, ">>> Sent 0x%x bytes to    Port:0x%x  Addr:0x%lx\n",
  420.                     chsent, ntohs(sock.sin_port), ntohl(sock.sin_addr.S_un.S_addr));
  421.         }
  422.     }
  423.     /* not a broadcast. Lookup in the queue, set up reply pkt if found */
  424.     else {
  425.         if (debug) {
  426.             fprintf(stderr, "|-- NETBIOS PKT --------------------------\n");
  427.             fprintf(stderr, "| size = 0x%x\n", nspkt_size);
  428.             fprintf(stderr, "| port = 0x%x\n", ntohs(from.sin_port));
  429.             fprintf(stderr, "| addr = 0x%lx\n", ntohl(from.sin_addr.S_un.S_addr));
  430.             fprintf(stderr, "| tid  = 0x%x\n", ntohs(bapkt.namepkt.header.nm_tid));
  431.             fprintf(stderr, "| type = 0x%x\n", ntohs(bapkt.namepkt.header.status));
  432.             fprintf(stderr, "|--------------------------------------\n");
  433.         }
  434.         /* dequeue based on the nm_tid */
  435.         if (!(badeq(NStoNL(bapkt.namepkt.header.nm_tid), &bapkt))) {
  436.  
  437.             /* restore the pkt tid */
  438.             bapkt.namepkt.header.nm_tid = NLtoNS(bapkt.baheader.ns_tid);
  439.  
  440.             /* send the packet to the remote client */
  441.             sock.sin_port = NLtoNS(bapkt.baheader.client_port);
  442.             sock.sin_addr.S_un.S_addr = bapkt.baheader.client_addr;
  443.  
  444.             if ((chsent = sendto(fd, &bapkt.namepkt, nspkt_size, 0,
  445.                          &sock, SOCKADDRSIZE)) < 0) {
  446.                 perror("nba: sendto()");
  447.                 exit(1);
  448.             }
  449.             if (debug)
  450.                 fprintf(stderr, ">>> Sent 0x%x bytes to    Port:0x%x  Addr:0x%lx\n",
  451.                     chsent, ntohs(sock.sin_port), ntohl(sock.sin_addr.S_un.S_addr));
  452.         }
  453.     }
  454. }                /* process_ns */
  455.  
  456.  
  457. /*
  458.  * baenq - enqueue a BA header. returns: 0 if success At present the queue is
  459.  * just an array of headers.
  460.  */
  461. int 
  462. baenq(header)
  463.     struct ba_header *header;
  464. {
  465.     int             i;
  466.     ULONG           t;
  467.  
  468.     /* place the header at an empty (expired) location */
  469.     for (i = 0; i < BAQSIZE; i++) {
  470.         time(&t);
  471.         if ((t - baq[i].time) > BAPKTLIFE) {
  472.             bcopy((char *) header, (char *) &baq[i], BAHEADERSIZE);
  473.             baq[i].time = t;    /* time stamp the header */
  474.             return (0);
  475.         }
  476.     }
  477.  
  478.     if (debug)
  479.         fprintf(stderr, "XXX Queue full.\n");
  480.  
  481.     return (1);
  482. }
  483.  
  484. /*
  485.  * badeq - dequeue a baheader based on a BATID returns: 0 if success At
  486.  * present the queue is just an array of headers.
  487.  */
  488. int 
  489. badeq(tid, header)
  490.     ULONG           tid;
  491.     struct ba_header *header;
  492. {
  493.     int             i;
  494.     ULONG           t;
  495.  
  496.     /* search for header ba_tid matching the tid */
  497.     for (i = 0; i < BAQSIZE; i++) {
  498.         time(&t);
  499.         /* skip the dead ones */
  500.         if ((t - baq[i].time) < BAPKTLIFE) {
  501.             if (baq[i].ba_tid == tid) {
  502.                 bcopy((char *) header, (char *) &baq[i], BAHEADERSIZE);
  503.                 return (0);
  504.             }
  505.         }
  506.     }
  507.  
  508.     if (debug)
  509.         fprintf(stderr, "XXX Header not found.\n");
  510.  
  511.     return (1);
  512. }
  513.  
  514.  
  515. /*
  516.  * cvt - convert MYNAME to upper case
  517.  */
  518.  
  519. cvt(src)
  520.     char           *src;
  521. {
  522.     int             i;
  523.  
  524.     for (i = 0; i < strlen(src); i++) {
  525.         if (isalpha(src[i]))
  526.             src[i] = toupper(src[i]);
  527.     }
  528.  
  529.     /* fill with blanks */
  530.  
  531.     for (; i <= 15; i++)
  532.         src[i] = ' ';
  533. }
  534.  
  535. /*
  536.  * sig - signal handling
  537.  */
  538.  
  539. sig()
  540. {
  541. #ifdef OS2
  542.     soclose(fd);
  543.     soclose(fda);
  544. #endif
  545.     exit(1);
  546. }
  547.  
  548.  
  549. /*
  550.  * dns2nb - convert DNS name to NETBIOS name
  551.  */
  552.  
  553. dns2nb(dnsp, nbp)
  554.     char           *dnsp;    /* ptr to a DNS name */
  555.     char           *nbp;    /* ptr to a 16 byte buffer */
  556.  
  557. {
  558.     unsigned char   idx;
  559.     unsigned char   left;
  560.     unsigned char   right;
  561.  
  562.     /*
  563.      * a compressed Netbios name is always 32 bytes long, so we can loop
  564.      * for a fixed amount, as long as the initial length byte is skipped
  565.      */
  566.  
  567.     for (dnsp++, idx = 0; (idx < SZ_NCBNAME); idx++, nbp++) {
  568.         left = (*dnsp++ - 'A') << 4;
  569.         right = (*dnsp++ - 'A');
  570.         *nbp = left + right;
  571.     }
  572. }                /* end dns2nb() */
  573.  
  574.  
  575. /*
  576.  * nb2dns - convert NETBIOS name to DNS (first level encoded) name
  577.  */
  578.  
  579. nb2dns(nbp, dnsp)
  580.     char           *dnsp;    /* ptr to a 32 byte DNS name */
  581.     char           *nbp;    /* ptr to a 16 byte buffer */
  582.  
  583. {
  584.     unsigned char   idx;
  585.     unsigned char   left;
  586.     unsigned char   right;
  587.  
  588.     for (idx = 0; (idx < SZ_NCBNAME); idx++, nbp++, dnsp++) {
  589.         *dnsp = (*nbp >> 4) + 'A';
  590.         *(++dnsp) = (*nbp & 0x0f) + 'A';
  591.     }
  592. }                /* end dns2nb() */
  593.  
  594.  
  595. /*
  596.  * respond_local - look up name in the hosts file and respond to the query if
  597.  * found.
  598.  */
  599.  
  600. respond_local(nspkt)
  601.     struct namepkt *nspkt;
  602. {
  603.  
  604.     char            nbname[16];
  605.     char            temp[17];
  606.     char           *chp;
  607.     struct rr_trailer *trailer;
  608.     struct rr_info *info;
  609.     int             count;
  610.  
  611.  
  612.     dns2nb(nspkt->records, nbname);
  613.  
  614.     /* strip the trailing spaces (null terminate it) */
  615.     for (chp = nbname; isalpha(*chp); chp++);
  616.     *chp = 0;
  617.  
  618.     if (debug)
  619.         fprintf(stderr, "Hosts file look-up of \"%s\" \n", nbname);
  620.  
  621.     /* get the address from the hosts file */
  622.     host = gethostbyname(nbname);
  623.  
  624.     if (host) {
  625.         if (debug)
  626.             fprintf(stderr, "Address found : 0x%lx\n",
  627.                 ntohl(*(long *) host->h_addr));
  628.  
  629.         trailer = (struct rr_trailer *) ((char *) nspkt + nspkt_size - 4);
  630.         nspkt->header.status = htons(NM_QRY_RES);
  631.         nspkt->header.qdcount = 0;
  632.         nspkt->header.ancount = htons(1);
  633.         trailer->ttl = htons(1);
  634.         trailer->length = htons(6);
  635.         info = (struct rr_info *) trailer;
  636.         info->flags = 0;
  637.         info->nbaddr = ntohl(*(long *) host->h_addr);
  638.  
  639.         /* send the response packet (back) to the client */
  640.         if ((count = sendto(fd, nspkt,
  641.                     nspkt_size + sizeof(struct rr_info) - 4,
  642.                   0, &from, sizeof(struct sockaddr))) < 0) {
  643.             perror("nsd: sendto()");
  644.             exit(1);
  645.         }
  646.         if (debug)
  647.             fprintf(stderr, ">>> Sent 0x%x bytes to    Port:0x%x  Addr:0x%lx\n",
  648.                 count, ntohs(from.sin_port), ntohl(from.sin_addr.S_un.S_addr));
  649.  
  650.     } else {        /* gethostbyname() failed */
  651.         if (debug)
  652.             fprintf(stderr, "Address not found.\n");
  653.     }
  654. }
  655.