home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / routed / query / query.c
Encoding:
C/C++ Source or Header  |  1993-12-17  |  7.6 KB  |  291 lines

  1. /*-
  2.  * Copyright (c) 1982, 1986 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1982, 1986 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. /*static char sccsid[] = "from: @(#)query.c    5.13 (Berkeley) 4/16/91";*/
  42. static char rcsid[] = "$Id: query.c,v 1.4 1993/08/01 18:24:51 mycroft Exp $";
  43. #endif /* not lint */
  44.  
  45. #include <sys/param.h>
  46. #include <sys/protosw.h>
  47. #include <sys/socket.h>
  48. #include <sys/time.h>
  49. #include <signal.h>
  50. #include <netinet/in.h>
  51. #include <protocols/routed.h>
  52. #include <arpa/inet.h>
  53. #include <netdb.h>
  54. #include <errno.h>
  55. #include <unistd.h>
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59.  
  60. #define    WTIME    5        /* Time to wait for all responses */
  61. #define    STIME    500000        /* usec to wait for another response */
  62.  
  63. int    s;
  64. int    timedout;
  65. void    timeout();
  66. char    packet[MAXPACKETSIZE];
  67. int    nflag;
  68.  
  69. main(argc, argv)
  70.     int argc;
  71.     char *argv[];
  72. {
  73.     extern char *optarg;
  74.     extern int optind;
  75.     int ch, cc, count, bits;
  76.     struct sockaddr from;
  77.     int fromlen = sizeof(from), size = 32*1024;
  78.     struct timeval shorttime;
  79.  
  80.     while ((ch = getopt(argc, argv, "n")) != EOF)
  81.         switch((char)ch) {
  82.         case 'n':
  83.             nflag++;
  84.             break;
  85.         case '?':
  86.         default:
  87.             goto usage;
  88.         }
  89.     argv += optind;
  90.  
  91.     if (!*argv) {
  92. usage:        printf("usage: query [-n] hosts...\n");
  93.         exit(1);
  94.     }
  95.  
  96.     s = socket(AF_INET, SOCK_DGRAM, 0);
  97.     if (s < 0) {
  98.         perror("socket");
  99.         exit(2);
  100.     }
  101.     if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
  102.         perror("setsockopt SO_RCVBUF");
  103.  
  104.     while (*argv) {
  105.         query(*argv++);
  106.         count++;
  107.     }
  108.  
  109.     /*
  110.      * Listen for returning packets;
  111.      * may be more than one packet per host.
  112.      */
  113.     bits = 1 << s;
  114.     bzero(&shorttime, sizeof(shorttime));
  115.     shorttime.tv_usec = STIME;
  116.     signal(SIGALRM, timeout);
  117.     alarm(WTIME);
  118.     while ((count > 0 && !timedout) ||
  119.         select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) {
  120.         cc = recvfrom(s, packet, sizeof (packet), 0,
  121.           &from, &fromlen);
  122.         if (cc <= 0) {
  123.             if (cc < 0) {
  124.                 if (errno == EINTR)
  125.                     continue;
  126.                 perror("recvfrom");
  127.                 (void) close(s);
  128.                 exit(1);
  129.             }
  130.             continue;
  131.         }
  132.         rip_input(&from, cc);
  133.         count--;
  134.     }
  135.     exit (count > 0 ? count : 0);
  136. }
  137.  
  138. query(host)
  139.     char *host;
  140. {
  141.     struct sockaddr_in router;
  142.     register struct rip *msg = (struct rip *)packet;
  143.     struct hostent *hp;
  144.     struct servent *sp;
  145.  
  146.     bzero((char *)&router, sizeof (router));
  147.     router.sin_family = AF_INET;
  148.     router.sin_addr.s_addr = inet_addr(host);
  149.     if (router.sin_addr.s_addr == -1) {
  150.         hp = gethostbyname(host);
  151.         if (hp == NULL) {
  152.             fprintf(stderr, "query: %s: ", host);
  153.             herror((char *)NULL);
  154.             exit(1);
  155.         }
  156.         bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
  157.     }
  158.     sp = getservbyname("router", "udp");
  159.     if (sp == 0) {
  160.         printf("udp/router: service unknown\n");
  161.         exit(1);
  162.     }
  163.     router.sin_port = sp->s_port;
  164.     msg->rip_cmd = RIPCMD_REQUEST;
  165.     msg->rip_vers = RIPVERSION;
  166.     msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
  167.     msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
  168.     if (sendto(s, packet, sizeof (struct rip), 0,
  169.       (struct sockaddr *)&router, sizeof(router)) < 0)
  170.         perror(host);
  171. }
  172.  
  173. /*
  174.  * Handle an incoming routing packet.
  175.  */
  176. rip_input(from, size)
  177.     struct sockaddr_in *from;
  178.     int size;
  179. {
  180.     register struct rip *msg = (struct rip *)packet;
  181.     register struct netinfo *n;
  182.     char *name;
  183.     int lna, net, subnet;
  184.     struct hostent *hp;
  185.     struct netent *np;
  186.  
  187.     if (msg->rip_cmd != RIPCMD_RESPONSE)
  188.         return;
  189.     printf("%d bytes from ", size);
  190.     if (nflag)
  191.         printf("%s:\n", inet_ntoa(from->sin_addr));
  192.     else {
  193.         hp = gethostbyaddr((char *)&from->sin_addr,
  194.             sizeof (struct in_addr), AF_INET);
  195.         name = hp == 0 ? "???" : hp->h_name;
  196.         printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
  197.     }
  198.     size -= sizeof (int);
  199.     n = msg->rip_nets;
  200.     while (size > 0) {
  201.         if (size < sizeof (struct netinfo))
  202.             break;
  203.         if (msg->rip_vers > 0) {
  204.             n->rip_dst.sa_family =
  205.                 ntohs(n->rip_dst.sa_family);
  206.             n->rip_metric = ntohl(n->rip_metric);
  207.         }
  208.         switch (n->rip_dst.sa_family) {
  209.  
  210.         case AF_INET:
  211.         { register struct sockaddr_in *sin;
  212.  
  213.         sin = (struct sockaddr_in *)&n->rip_dst;
  214.         net = inet_netof(sin->sin_addr);
  215.         subnet = inet_subnetof(sin->sin_addr);
  216.         lna = inet_lnaof(sin->sin_addr);
  217.         name = "???";
  218.         if (!nflag) {
  219.             if (sin->sin_addr.s_addr == 0)
  220.                 name = "default";
  221.             else if (lna == INADDR_ANY) {
  222.                 np = getnetbyaddr(net, AF_INET);
  223.                 if (np)
  224.                     name = np->n_name;
  225.                 else if (net == 0)
  226.                     name = "default";
  227.             } else if ((lna & 0xff) == 0 &&
  228.                 (np = getnetbyaddr(subnet, AF_INET))) {
  229.                 struct in_addr subnaddr, inet_makeaddr();
  230.  
  231.                 subnaddr = inet_makeaddr(subnet, INADDR_ANY);
  232.                 if (bcmp(&sin->sin_addr, &subnaddr,
  233.                     sizeof(subnaddr)) == 0)
  234.                     name = np->n_name;
  235.                 else
  236.                     goto host;
  237.             } else {
  238.     host:
  239.                 hp = gethostbyaddr((char *)&sin->sin_addr,
  240.                     sizeof (struct in_addr), AF_INET);
  241.                 if (hp)
  242.                     name = hp->h_name;
  243.             }
  244.             printf("\t%-17s metric %2d name %s\n",
  245.                 inet_ntoa(sin->sin_addr), n->rip_metric, name);
  246.         } else
  247.             printf("\t%-17s metric %2d\n",
  248.                 inet_ntoa(sin->sin_addr), n->rip_metric);
  249.         break;
  250.         }
  251.  
  252.         default:
  253.         { u_short *p = (u_short *)n->rip_dst.sa_data;
  254.  
  255.         printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
  256.             p[0], p[1], p[2], p[3], p[4], p[5], p[6],
  257.             n->rip_dst.sa_family,
  258.             n->rip_metric);
  259.         break;
  260.         }
  261.             
  262.         }
  263.         size -= sizeof (struct netinfo), n++;
  264.     }
  265. }
  266.  
  267. void
  268. timeout()
  269. {
  270.     timedout = 1;
  271. }
  272.  
  273. /*
  274.  * Return the possible subnetwork number from an internet address.
  275.  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
  276.  * INSIDE OF THE HOST PART.  We can only believe this if we have other
  277.  * information (e.g., we can find a name for this number).
  278.  */
  279. inet_subnetof(in)
  280.     struct in_addr in;
  281. {
  282.     register u_long i = ntohl(in.s_addr);
  283.  
  284.     if (IN_CLASSA(i))
  285.         return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
  286.     else if (IN_CLASSB(i))
  287.         return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
  288.     else
  289.         return ((i & 0xffffffc0) >> 28);
  290. }
  291.