delay deletion from internal tables when cur router deletes
[unix-history] / usr / src / sbin / routed / query / query.c
index 92dbea6..fe7adc3 100644 (file)
@@ -1,50 +1,87 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)query.c    4.4 %G%";
-#endif
+static char sccsid[] = "@(#)query.c    5.7 (Berkeley) %G%";
+#endif not lint
 
 #include <sys/param.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 
 #include <sys/param.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
-#include <net/in.h>
+#include <sys/time.h>
+#include <netinet/in.h>
 #include <errno.h>
 #include <stdio.h>
 #include <netdb.h>
 #include <errno.h>
 #include <stdio.h>
 #include <netdb.h>
-#include "rip.h"
+#include <protocols/routed.h>
+
+#define        WTIME   5               /* Time to wait for all responses */
+#define        STIME   500000          /* usec to wait for another response */
 
 int    s;
 
 int    s;
+int    timedout, timeout();
 char   packet[MAXPACKETSIZE];
 char   packet[MAXPACKETSIZE];
+extern int errno;
+int    nflag;
 
 main(argc, argv)
        int argc;
        char *argv[];
 {
 
 main(argc, argv)
        int argc;
        char *argv[];
 {
-       int cc, count;
+       int cc, count, bits;
        struct sockaddr from;
        struct sockaddr from;
+       int fromlen = sizeof(from);
+       struct timeval shorttime;
        
        if (argc < 2) {
        
        if (argc < 2) {
-               printf("usage: query hosts...\n");
+usage:
+               printf("usage: query [ -n ] hosts...\n");
                exit(1);
        }
                exit(1);
        }
-       s = socket(SOCK_DGRAM, 0, 0, 0);
+       s = socket(AF_INET, SOCK_DGRAM, 0);
        if (s < 0) {
                perror("socket");
                exit(2);
        }
        if (s < 0) {
                perror("socket");
                exit(2);
        }
+
        argv++, argc--;
        argv++, argc--;
-       count = argc;
+       if (*argv[0] == '-') {
+               switch (argv[0][1]) {
+               case 'n':
+                       nflag++;
+                       break;
+               default:
+                       goto usage;
+               }
+               argc--, argv++;
+       }
        while (argc > 0) {
                query(*argv);
        while (argc > 0) {
                query(*argv);
+               count++;
                argv++, argc--;
        }
 
        /*
                argv++, argc--;
        }
 
        /*
-        * Listen for returning packets
+        * Listen for returning packets;
+        * may be more than one packet per host.
         */
         */
-       while (count > 0) {
-               cc = receive(s, &from, packet, sizeof (packet));
+       bits = 1 << s;
+       bzero(&shorttime, sizeof(shorttime));
+       shorttime.tv_usec = STIME;
+       signal(SIGALRM, timeout);
+       alarm(WTIME);
+       while ((count > 0 && !timedout) ||
+           select(20, &bits, 0, 0, &shorttime) > 0) {
+               cc = recvfrom(s, packet, sizeof (packet), 0,
+                 &from, &fromlen);
                if (cc <= 0) {
                        if (cc < 0) {
                if (cc <= 0) {
                        if (cc < 0) {
-                               perror("receive");
+                               if (errno == EINTR)
+                                       continue;
+                               perror("recvfrom");
                                (void) close(s);
                                exit(1);
                        }
                                (void) close(s);
                                exit(1);
                        }
@@ -64,23 +101,28 @@ query(host)
        struct servent *sp;
 
        bzero((char *)&router, sizeof (router));
        struct servent *sp;
 
        bzero((char *)&router, sizeof (router));
-       hp = gethostbyname(host);
-       if (hp == 0) {
-               printf("%s: unknown\n", host);
-               exit(1);
-       }
-       bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
        router.sin_family = AF_INET;
        router.sin_family = AF_INET;
+       router.sin_addr.s_addr = inet_addr(host);
+       if (router.sin_addr.s_addr == -1) {
+               hp = gethostbyname(host);
+               if (hp == 0) {
+                       printf("%s: unknown\n", host);
+                       exit(1);
+               }
+               bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
+       }
        sp = getservbyname("router", "udp");
        if (sp == 0) {
                printf("udp/router: service unknown\n");
                exit(1);
        }
        sp = getservbyname("router", "udp");
        if (sp == 0) {
                printf("udp/router: service unknown\n");
                exit(1);
        }
-       router.sin_port = htons(sp->s_port);
+       router.sin_port = sp->s_port;
        msg->rip_cmd = RIPCMD_REQUEST;
        msg->rip_cmd = RIPCMD_REQUEST;
-       msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
-       msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
-       if (send(s, &router, packet, sizeof (struct rip)) < 0)
+       msg->rip_vers = RIPVERSION;
+       msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
+       msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
+       if (sendto(s, packet, sizeof (struct rip), 0,
+         &router, sizeof(router)) < 0)
                perror(host);
 }
 
                perror(host);
 }
 
@@ -92,75 +134,112 @@ rip_input(from, size)
        int size;
 {
        register struct rip *msg = (struct rip *)packet;
        int size;
 {
        register struct rip *msg = (struct rip *)packet;
-       struct netinfo *n;
+       register struct netinfo *n;
        char *name;
        char *name;
+       int lna, net, subnet;
        struct hostent *hp;
        struct netent *np;
 
        if (msg->rip_cmd != RIPCMD_RESPONSE)
                return;
        struct hostent *hp;
        struct netent *np;
 
        if (msg->rip_cmd != RIPCMD_RESPONSE)
                return;
-       hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), AF_INET);
-       name = hp == 0 ? "???" : hp->h_name;
-       printf("from %s(%x):\n", name, from->sin_addr);
+       printf("%d bytes from ", size);
+       if (nflag)
+               printf("%s:\n", inet_ntoa(from->sin_addr));
+       else {
+               hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr),
+                       AF_INET);
+               name = hp == 0 ? "???" : hp->h_name;
+               printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
+       }
        size -= sizeof (int);
        n = msg->rip_nets;
        while (size > 0) {
        size -= sizeof (int);
        n = msg->rip_nets;
        while (size > 0) {
-               register struct sockaddr_in *sin;
+           if (size < sizeof (struct netinfo))
+                   break;
+           if (msg->rip_vers > 0) {
+                   n->rip_dst.sa_family =
+                           ntohs(n->rip_dst.sa_family);
+                   n->rip_metric = ntohl(n->rip_metric);
+           }
+           switch (n->rip_dst.sa_family) {
+
+           case AF_INET:
+               { register struct sockaddr_in *sin;
 
 
-               if (size < sizeof (struct netinfo))
-                       break;
                sin = (struct sockaddr_in *)&n->rip_dst;
                sin = (struct sockaddr_in *)&n->rip_dst;
-               if (in_lnaof(sin->sin_addr) == INADDR_ANY) {
-                       np = getnetbyaddr(in_netof(sin->sin_addr), AF_INET);
-                       name = np ? np->n_name : "???";
-               } else {
-                       hp = gethostbyaddr(&sin->sin_addr,
-                               sizeof (struct in_addr), AF_INET);
-                       name = hp ? hp->h_name : "???";
+               net = inet_netof(sin->sin_addr);
+               subnet = inet_subnetof(sin->sin_addr);
+               lna = inet_lnaof(sin->sin_addr);
+               name = "???";
+               if (!nflag) {
+                       if (sin->sin_addr.s_addr == 0)
+                               name = "default";
+                       else if (lna == INADDR_ANY) {
+                               np = getnetbyaddr(net, AF_INET);
+                               if (np)
+                                       name = np->n_name;
+                               else if (net == 0)
+                                       name = "default";
+                       } else if ((lna & 0xff) == 0 &&
+                           (np = getnetbyaddr(subnet, AF_INET))) {
+                               struct in_addr subnaddr, inet_makeaddr();
+
+                               subnaddr = inet_makeaddr(subnet, INADDR_ANY);
+                               if (bcmp(&sin->sin_addr, &subnaddr,
+                                   sizeof(subnaddr)) == 0)
+                                       name = np->n_name;
+                               else
+                                       goto host;
+                       } else {
+       host:
+                               hp = gethostbyaddr(&sin->sin_addr,
+                                   sizeof (struct in_addr), AF_INET);
+                               if (hp)
+                                       name = hp->h_name;
+                       }
+                       printf("\t%s(%s), metric %d\n", name,
+                               inet_ntoa(sin->sin_addr), n->rip_metric);
+               } else
+                       printf("\t%s, metric %d\n",
+                               inet_ntoa(sin->sin_addr), n->rip_metric);
+               break;
+               }
+
+           default:
+               { u_short *p = (u_short *)n->rip_dst.sa_data;
+
+               printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
+                   p[0], p[1], p[2], p[3], p[4], p[5], p[6],
+                   n->rip_dst.sa_family,
+                   n->rip_metric);
+               break;
                }
                }
-               printf("\t%s(%x), metric %d\n", name,
-                       sin->sin_addr, n->rip_metric);
-               size -= sizeof (struct netinfo), n++;
+                       
+           }
+           size -= sizeof (struct netinfo), n++;
        }
 }
 
        }
 }
 
-/*
- * Return the network number from an internet
- * address; handles class a/b/c network #'s.
- */
-in_netof(in)
-       struct in_addr in;
+timeout()
 {
 {
-#if vax || pdp11
-       register u_long net;
-
-       if ((in.s_addr&IN_CLASSA) == 0)
-               return (in.s_addr & IN_CLASSA_NET);
-       if ((in.s_addr&IN_CLASSB) == 0)
-               return ((int)htons((u_short)(in.s_addr & IN_CLASSB_NET)));
-       net = htonl((u_long)(in.s_addr & IN_CLASSC_NET));
-       net >>= 8;
-       return ((int)net);
-#else
-       return (IN_NETOF(in));
-#endif
+       timedout = 1;
 }
 
 /*
 }
 
 /*
- * Return the local network address portion of an
- * internet address; handles class a/b/c network
- * number formats.
+ * Return the possible subnetwork number from an internet address.
+ * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
+ * INSIDE OF THE HOST PART.  We can only believe this if we have other
+ * information (e.g., we can find a name for this number).
  */
  */
-in_lnaof(in)
+inet_subnetof(in)
        struct in_addr in;
 {
        struct in_addr in;
 {
-#if vax || pdp11
-#define        IN_LNAOF(in) \
-       (((in).s_addr&IN_CLASSA) == 0 ? (in).s_addr&IN_CLASSA_LNA : \
-               ((in).s_addr&IN_CLASSB) == 0 ? (in).s_addr&IN_CLASSB_LNA : \
-                       (in).s_addr&IN_CLASSC_LNA)
-       return ((int)htonl((u_long)IN_LNAOF(in)));
-#else
-       return (IN_LNAOF(in));
-#endif
+       register u_long i = ntohl(in.s_addr);
+
+       if (IN_CLASSA(i))
+               return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
+       else if (IN_CLASSB(i))
+               return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
+       else
+               return ((i & 0xffffffc0) >> 28);
 }
 }