home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / routed / query / query.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  7.5 KB  |  290 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[] = "@(#)query.c    5.13 (Berkeley) 4/16/91";
  42. #endif /* not lint */
  43.  
  44. #include <sys/param.h>
  45. #include <sys/protosw.h>
  46. #include <sys/socket.h>
  47. #include <sys/time.h>
  48. #include <signal.h>
  49. #include <netinet/in.h>
  50. #include <protocols/routed.h>
  51. #include <arpa/inet.h>
  52. #include <netdb.h>
  53. #include <errno.h>
  54. #include <unistd.h>
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58.  
  59. #define    WTIME    5        /* Time to wait for all responses */
  60. #define    STIME    500000        /* usec to wait for another response */
  61.  
  62. int    s;
  63. int    timedout;
  64. void    timeout();
  65. char    packet[MAXPACKETSIZE];
  66. int    nflag;
  67.  
  68. main(argc, argv)
  69.     int argc;
  70.     char *argv[];
  71. {
  72.     extern char *optarg;
  73.     extern int optind;
  74.     int ch, cc, count, bits;
  75.     struct sockaddr from;
  76.     int fromlen = sizeof(from), size = 32*1024;
  77.     struct timeval shorttime;
  78.  
  79.     while ((ch = getopt(argc, argv, "n")) != EOF)
  80.         switch((char)ch) {
  81.         case 'n':
  82.             nflag++;
  83.             break;
  84.         case '?':
  85.         default:
  86.             goto usage;
  87.         }
  88.     argv += optind;
  89.  
  90.     if (!*argv) {
  91. usage:        printf("usage: query [-n] hosts...\n");
  92.         exit(1);
  93.     }
  94.  
  95.     s = socket(AF_INET, SOCK_DGRAM, 0);
  96.     if (s < 0) {
  97.         perror("socket");
  98.         exit(2);
  99.     }
  100.     if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
  101.         perror("setsockopt SO_RCVBUF");
  102.  
  103.     while (*argv) {
  104.         query(*argv++);
  105.         count++;
  106.     }
  107.  
  108.     /*
  109.      * Listen for returning packets;
  110.      * may be more than one packet per host.
  111.      */
  112.     bits = 1 << s;
  113.     bzero(&shorttime, sizeof(shorttime));
  114.     shorttime.tv_usec = STIME;
  115.     signal(SIGALRM, timeout);
  116.     alarm(WTIME);
  117.     while ((count > 0 && !timedout) ||
  118.         select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) {
  119.         cc = recvfrom(s, packet, sizeof (packet), 0,
  120.           &from, &fromlen);
  121.         if (cc <= 0) {
  122.             if (cc < 0) {
  123.                 if (errno == EINTR)
  124.                     continue;
  125.                 perror("recvfrom");
  126.                 (void) close(s);
  127.                 exit(1);
  128.             }
  129.             continue;
  130.         }
  131.         rip_input(&from, cc);
  132.         count--;
  133.     }
  134.     exit (count > 0 ? count : 0);
  135. }
  136.  
  137. query(host)
  138.     char *host;
  139. {
  140.     struct sockaddr_in router;
  141.     register struct rip *msg = (struct rip *)packet;
  142.     struct hostent *hp;
  143.     struct servent *sp;
  144.  
  145.     bzero((char *)&router, sizeof (router));
  146.     router.sin_family = AF_INET;
  147.     router.sin_addr.s_addr = inet_addr(host);
  148.     if (router.sin_addr.s_addr == -1) {
  149.         hp = gethostbyname(host);
  150.         if (hp == NULL) {
  151.             fprintf(stderr, "query: %s: ", host);
  152.             herror((char *)NULL);
  153.             exit(1);
  154.         }
  155.         bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
  156.     }
  157.     sp = getservbyname("router", "udp");
  158.     if (sp == 0) {
  159.         printf("udp/router: service unknown\n");
  160.         exit(1);
  161.     }
  162.     router.sin_port = sp->s_port;
  163.     msg->rip_cmd = RIPCMD_REQUEST;
  164.     msg->rip_vers = RIPVERSION;
  165.     msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
  166.     msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
  167.     if (sendto(s, packet, sizeof (struct rip), 0,
  168.       (struct sockaddr *)&router, sizeof(router)) < 0)
  169.         perror(host);
  170. }
  171.  
  172. /*
  173.  * Handle an incoming routing packet.
  174.  */
  175. rip_input(from, size)
  176.     struct sockaddr_in *from;
  177.     int size;
  178. {
  179.     register struct rip *msg = (struct rip *)packet;
  180.     register struct netinfo *n;
  181.     char *name;
  182.     int lna, net, subnet;
  183.     struct hostent *hp;
  184.     struct netent *np;
  185.  
  186.     if (msg->rip_cmd != RIPCMD_RESPONSE)
  187.         return;
  188.     printf("%d bytes from ", size);
  189.     if (nflag)
  190.         printf("%s:\n", inet_ntoa(from->sin_addr));
  191.     else {
  192.         hp = gethostbyaddr((char *)&from->sin_addr,
  193.             sizeof (struct in_addr), AF_INET);
  194.         name = hp == 0 ? "???" : hp->h_name;
  195.         printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
  196.     }
  197.     size -= sizeof (int);
  198.     n = msg->rip_nets;
  199.     while (size > 0) {
  200.         if (size < sizeof (struct netinfo))
  201.             break;
  202.         if (msg->rip_vers > 0) {
  203.             n->rip_dst.sa_family =
  204.                 ntohs(n->rip_dst.sa_family);
  205.             n->rip_metric = ntohl(n->rip_metric);
  206.         }
  207.         switch (n->rip_dst.sa_family) {
  208.  
  209.         case AF_INET:
  210.         { register struct sockaddr_in *sin;
  211.  
  212.         sin = (struct sockaddr_in *)&n->rip_dst;
  213.         net = inet_netof(sin->sin_addr);
  214.         subnet = inet_subnetof(sin->sin_addr);
  215.         lna = inet_lnaof(sin->sin_addr);
  216.         name = "???";
  217.         if (!nflag) {
  218.             if (sin->sin_addr.s_addr == 0)
  219.                 name = "default";
  220.             else if (lna == INADDR_ANY) {
  221.                 np = getnetbyaddr(net, AF_INET);
  222.                 if (np)
  223.                     name = np->n_name;
  224.                 else if (net == 0)
  225.                     name = "default";
  226.             } else if ((lna & 0xff) == 0 &&
  227.                 (np = getnetbyaddr(subnet, AF_INET))) {
  228.                 struct in_addr subnaddr, inet_makeaddr();
  229.  
  230.                 subnaddr = inet_makeaddr(subnet, INADDR_ANY);
  231.                 if (bcmp(&sin->sin_addr, &subnaddr,
  232.                     sizeof(subnaddr)) == 0)
  233.                     name = np->n_name;
  234.                 else
  235.                     goto host;
  236.             } else {
  237.     host:
  238.                 hp = gethostbyaddr((char *)&sin->sin_addr,
  239.                     sizeof (struct in_addr), AF_INET);
  240.                 if (hp)
  241.                     name = hp->h_name;
  242.             }
  243.             printf("\t%-17s metric %2d name %s\n",
  244.                 inet_ntoa(sin->sin_addr), n->rip_metric, name);
  245.         } else
  246.             printf("\t%-17s metric %2d\n",
  247.                 inet_ntoa(sin->sin_addr), n->rip_metric);
  248.         break;
  249.         }
  250.  
  251.         default:
  252.         { u_short *p = (u_short *)n->rip_dst.sa_data;
  253.  
  254.         printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
  255.             p[0], p[1], p[2], p[3], p[4], p[5], p[6],
  256.             n->rip_dst.sa_family,
  257.             n->rip_metric);
  258.         break;
  259.         }
  260.             
  261.         }
  262.         size -= sizeof (struct netinfo), n++;
  263.     }
  264. }
  265.  
  266. void
  267. timeout()
  268. {
  269.     timedout = 1;
  270. }
  271.  
  272. /*
  273.  * Return the possible subnetwork number from an internet address.
  274.  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
  275.  * INSIDE OF THE HOST PART.  We can only believe this if we have other
  276.  * information (e.g., we can find a name for this number).
  277.  */
  278. inet_subnetof(in)
  279.     struct in_addr in;
  280. {
  281.     register u_long i = ntohl(in.s_addr);
  282.  
  283.     if (IN_CLASSA(i))
  284.         return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
  285.     else if (IN_CLASSB(i))
  286.         return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
  287.     else
  288.         return ((i & 0xffffffc0) >> 28);
  289. }
  290.