1*48130Sbostic /*- 2*48130Sbostic * Copyright (c) 1982, 1986 The Regents of the University of California. 333488Sbostic * All rights reserved. 433488Sbostic * 5*48130Sbostic * %sccs.include.redist.c% 622643Sdist */ 722643Sdist 86918Ssam #ifndef lint 933488Sbostic char copyright[] = 10*48130Sbostic "@(#) Copyright (c) 1982, 1986 The Regents of the University of California.\n\ 1133488Sbostic All rights reserved.\n"; 1233488Sbostic #endif /* not lint */ 136918Ssam 1433488Sbostic #ifndef lint 15*48130Sbostic static char sccsid[] = "@(#)query.c 5.13 (Berkeley) 04/16/91"; 1633488Sbostic #endif /* not lint */ 1733488Sbostic 186918Ssam #include <sys/param.h> 196918Ssam #include <sys/protosw.h> 206918Ssam #include <sys/socket.h> 2115760Skarels #include <sys/time.h> 2246785Sbostic #include <signal.h> 2315760Skarels #include <netinet/in.h> 2446785Sbostic #include <protocols/routed.h> 2546785Sbostic #include <arpa/inet.h> 2646785Sbostic #include <netdb.h> 276918Ssam #include <errno.h> 2846785Sbostic #include <unistd.h> 296918Ssam #include <stdio.h> 3046785Sbostic #include <stdlib.h> 3146785Sbostic #include <string.h> 326918Ssam 3327344Skarels #define WTIME 5 /* Time to wait for all responses */ 3427344Skarels #define STIME 500000 /* usec to wait for another response */ 3515760Skarels 366918Ssam int s; 3746785Sbostic int timedout; 3846785Sbostic void timeout(); 396918Ssam char packet[MAXPACKETSIZE]; 4026146Skarels int nflag; 416918Ssam 426918Ssam main(argc, argv) 436918Ssam int argc; 446918Ssam char *argv[]; 456918Ssam { 4635780Sbostic extern char *optarg; 4735780Sbostic extern int optind; 4835780Sbostic int ch, cc, count, bits; 496918Ssam struct sockaddr from; 5034708Skarels int fromlen = sizeof(from), size = 32*1024; 5127344Skarels struct timeval shorttime; 5235780Sbostic 5335780Sbostic while ((ch = getopt(argc, argv, "n")) != EOF) 5435780Sbostic switch((char)ch) { 5535780Sbostic case 'n': 5635780Sbostic nflag++; 5735780Sbostic break; 5835780Sbostic case '?': 5935780Sbostic default: 6035780Sbostic goto usage; 6135780Sbostic } 6235780Sbostic argv += optind; 6335780Sbostic 6435780Sbostic if (!*argv) { 6535780Sbostic usage: printf("usage: query [-n] hosts...\n"); 666918Ssam exit(1); 676918Ssam } 6835780Sbostic 6915760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 706918Ssam if (s < 0) { 716918Ssam perror("socket"); 726918Ssam exit(2); 736918Ssam } 7434708Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) 7534708Skarels perror("setsockopt SO_RCVBUF"); 7615760Skarels 7735780Sbostic while (*argv) { 7835780Sbostic query(*argv++); 7928205Skarels count++; 806918Ssam } 816918Ssam 826918Ssam /* 8315760Skarels * Listen for returning packets; 8415760Skarels * may be more than one packet per host. 856918Ssam */ 8615760Skarels bits = 1 << s; 8727344Skarels bzero(&shorttime, sizeof(shorttime)); 8827344Skarels shorttime.tv_usec = STIME; 8922547Skarels signal(SIGALRM, timeout); 9022547Skarels alarm(WTIME); 9122547Skarels while ((count > 0 && !timedout) || 9246785Sbostic select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) { 9315760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 9415760Skarels &from, &fromlen); 956918Ssam if (cc <= 0) { 966918Ssam if (cc < 0) { 9722547Skarels if (errno == EINTR) 9822547Skarels continue; 9915760Skarels perror("recvfrom"); 1006918Ssam (void) close(s); 1016918Ssam exit(1); 1026918Ssam } 1036918Ssam continue; 1046918Ssam } 1056918Ssam rip_input(&from, cc); 1066918Ssam count--; 1076918Ssam } 10834708Skarels exit (count > 0 ? count : 0); 1096918Ssam } 1106918Ssam 1116918Ssam query(host) 1126918Ssam char *host; 1136918Ssam { 1146918Ssam struct sockaddr_in router; 1156918Ssam register struct rip *msg = (struct rip *)packet; 1168339Ssam struct hostent *hp; 1178339Ssam struct servent *sp; 1186918Ssam 1196918Ssam bzero((char *)&router, sizeof (router)); 12026146Skarels router.sin_family = AF_INET; 12126146Skarels router.sin_addr.s_addr = inet_addr(host); 12226146Skarels if (router.sin_addr.s_addr == -1) { 12326146Skarels hp = gethostbyname(host); 12435780Sbostic if (hp == NULL) { 12535780Sbostic fprintf(stderr, "query: %s: ", host); 12635780Sbostic herror((char *)NULL); 12726146Skarels exit(1); 12826146Skarels } 12926146Skarels bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 1306918Ssam } 1318339Ssam sp = getservbyname("router", "udp"); 1328339Ssam if (sp == 0) { 1338339Ssam printf("udp/router: service unknown\n"); 1348339Ssam exit(1); 1358339Ssam } 13615760Skarels router.sin_port = sp->s_port; 1376918Ssam msg->rip_cmd = RIPCMD_REQUEST; 13815760Skarels msg->rip_vers = RIPVERSION; 13915760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 14015760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 14115760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 14246785Sbostic (struct sockaddr *)&router, sizeof(router)) < 0) 1436918Ssam perror(host); 1446918Ssam } 1456918Ssam 1466918Ssam /* 1476918Ssam * Handle an incoming routing packet. 1486918Ssam */ 1496918Ssam rip_input(from, size) 1506918Ssam struct sockaddr_in *from; 1516918Ssam int size; 1526918Ssam { 1536918Ssam register struct rip *msg = (struct rip *)packet; 15428205Skarels register struct netinfo *n; 1556918Ssam char *name; 15622547Skarels int lna, net, subnet; 1578339Ssam struct hostent *hp; 1588339Ssam struct netent *np; 1596918Ssam 1606918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1616918Ssam return; 16226959Skarels printf("%d bytes from ", size); 16326146Skarels if (nflag) 16426146Skarels printf("%s:\n", inet_ntoa(from->sin_addr)); 16526146Skarels else { 16646785Sbostic hp = gethostbyaddr((char *)&from->sin_addr, 16746785Sbostic sizeof (struct in_addr), AF_INET); 16826146Skarels name = hp == 0 ? "???" : hp->h_name; 16926146Skarels printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 17026146Skarels } 1716918Ssam size -= sizeof (int); 1726918Ssam n = msg->rip_nets; 1736918Ssam while (size > 0) { 17428205Skarels if (size < sizeof (struct netinfo)) 17528205Skarels break; 17628205Skarels if (msg->rip_vers > 0) { 17728205Skarels n->rip_dst.sa_family = 17828205Skarels ntohs(n->rip_dst.sa_family); 17928205Skarels n->rip_metric = ntohl(n->rip_metric); 18028205Skarels } 18128205Skarels switch (n->rip_dst.sa_family) { 1826918Ssam 18328205Skarels case AF_INET: 18428205Skarels { register struct sockaddr_in *sin; 18528205Skarels 1866918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 18722547Skarels net = inet_netof(sin->sin_addr); 18822547Skarels subnet = inet_subnetof(sin->sin_addr); 18922547Skarels lna = inet_lnaof(sin->sin_addr); 19022547Skarels name = "???"; 19126146Skarels if (!nflag) { 19228205Skarels if (sin->sin_addr.s_addr == 0) 19328205Skarels name = "default"; 19428205Skarels else if (lna == INADDR_ANY) { 19526146Skarels np = getnetbyaddr(net, AF_INET); 19626146Skarels if (np) 19726146Skarels name = np->n_name; 19826146Skarels else if (net == 0) 19926146Skarels name = "default"; 20026959Skarels } else if ((lna & 0xff) == 0 && 20126146Skarels (np = getnetbyaddr(subnet, AF_INET))) { 20226146Skarels struct in_addr subnaddr, inet_makeaddr(); 20322547Skarels 20426146Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 20526146Skarels if (bcmp(&sin->sin_addr, &subnaddr, 20626146Skarels sizeof(subnaddr)) == 0) 20726146Skarels name = np->n_name; 20826146Skarels else 20926146Skarels goto host; 21026146Skarels } else { 21126146Skarels host: 21246785Sbostic hp = gethostbyaddr((char *)&sin->sin_addr, 21326146Skarels sizeof (struct in_addr), AF_INET); 21426146Skarels if (hp) 21526146Skarels name = hp->h_name; 21626146Skarels } 21734708Skarels printf("\t%-17s metric %2d name %s\n", 21834708Skarels inet_ntoa(sin->sin_addr), n->rip_metric, name); 21926146Skarels } else 22034708Skarels printf("\t%-17s metric %2d\n", 22126146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 22228205Skarels break; 22328205Skarels } 22428205Skarels 22528205Skarels default: 22628205Skarels { u_short *p = (u_short *)n->rip_dst.sa_data; 22728205Skarels 22828205Skarels printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", 22928205Skarels p[0], p[1], p[2], p[3], p[4], p[5], p[6], 23028205Skarels n->rip_dst.sa_family, 23128205Skarels n->rip_metric); 23228205Skarels break; 23328205Skarels } 23428205Skarels 23528205Skarels } 23628205Skarels size -= sizeof (struct netinfo), n++; 2376918Ssam } 2386918Ssam } 23915760Skarels 24046785Sbostic void 24115760Skarels timeout() 24215760Skarels { 24315760Skarels timedout = 1; 24415760Skarels } 24522547Skarels 24622547Skarels /* 24722547Skarels * Return the possible subnetwork number from an internet address. 24822547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 24922547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 25022547Skarels * information (e.g., we can find a name for this number). 25122547Skarels */ 25222547Skarels inet_subnetof(in) 25322547Skarels struct in_addr in; 25422547Skarels { 25522547Skarels register u_long i = ntohl(in.s_addr); 25622547Skarels 25725382Skarels if (IN_CLASSA(i)) 25825382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 25925382Skarels else if (IN_CLASSB(i)) 26022547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 26125382Skarels else 26225382Skarels return ((i & 0xffffffc0) >> 28); 26322547Skarels } 264