148130Sbostic /*- 261541Sbostic * Copyright (c) 1982, 1986, 1993 361541Sbostic * The Regents of the University of California. All rights reserved. 433488Sbostic * 548130Sbostic * %sccs.include.redist.c% 622643Sdist */ 722643Sdist 86918Ssam #ifndef lint 961541Sbostic static char copyright[] = 1061541Sbostic "@(#) Copyright (c) 1982, 1986, 1993\n\ 1161541Sbostic The Regents of the University of California. All rights reserved.\n"; 1233488Sbostic #endif /* not lint */ 136918Ssam 1433488Sbostic #ifndef lint 15*69005Sbostic static char sccsid[] = "@(#)query.c 8.2 (Berkeley) 04/28/95"; 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; 5050635Skarels struct sigaction sigact; 5134708Skarels int fromlen = sizeof(from), size = 32*1024; 5227344Skarels struct timeval shorttime; 5335780Sbostic 5435780Sbostic while ((ch = getopt(argc, argv, "n")) != EOF) 5550635Skarels switch (ch) { 5635780Sbostic case 'n': 5735780Sbostic nflag++; 5835780Sbostic break; 5935780Sbostic case '?': 6035780Sbostic default: 6135780Sbostic goto usage; 6235780Sbostic } 6335780Sbostic argv += optind; 6435780Sbostic 6535780Sbostic if (!*argv) { 6635780Sbostic usage: printf("usage: query [-n] hosts...\n"); 676918Ssam exit(1); 686918Ssam } 6935780Sbostic 7015760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 716918Ssam if (s < 0) { 726918Ssam perror("socket"); 736918Ssam exit(2); 746918Ssam } 7534708Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) 7634708Skarels perror("setsockopt SO_RCVBUF"); 7715760Skarels 7835780Sbostic while (*argv) { 7935780Sbostic query(*argv++); 8028205Skarels count++; 816918Ssam } 826918Ssam 836918Ssam /* 8415760Skarels * Listen for returning packets; 8515760Skarels * may be more than one packet per host. 866918Ssam */ 8715760Skarels bits = 1 << s; 88*69005Sbostic memset(&shorttime, 0, sizeof(shorttime)); 8927344Skarels shorttime.tv_usec = STIME; 90*69005Sbostic memset(&sigact, 0, sizeof(sigact)); 9150635Skarels sigact.sa_handler = timeout; 9250635Skarels /*sigact.sa_flags = 0; /* no restart */ 9350635Skarels if (sigaction(SIGALRM, &sigact, (struct sigaction *)NULL) == -1) 9450635Skarels perror("sigaction"); 9522547Skarels alarm(WTIME); 9622547Skarels while ((count > 0 && !timedout) || 9746785Sbostic select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) { 9815760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 9915760Skarels &from, &fromlen); 1006918Ssam if (cc <= 0) { 1016918Ssam if (cc < 0) { 10222547Skarels if (errno == EINTR) 10322547Skarels continue; 10415760Skarels perror("recvfrom"); 1056918Ssam (void) close(s); 1066918Ssam exit(1); 1076918Ssam } 1086918Ssam continue; 1096918Ssam } 1106918Ssam rip_input(&from, cc); 1116918Ssam count--; 1126918Ssam } 11334708Skarels exit (count > 0 ? count : 0); 1146918Ssam } 1156918Ssam 1166918Ssam query(host) 1176918Ssam char *host; 1186918Ssam { 1196918Ssam struct sockaddr_in router; 1206918Ssam register struct rip *msg = (struct rip *)packet; 1218339Ssam struct hostent *hp; 1228339Ssam struct servent *sp; 1236918Ssam 124*69005Sbostic memset(&router, 0, sizeof (router)); 12526146Skarels router.sin_family = AF_INET; 12626146Skarels router.sin_addr.s_addr = inet_addr(host); 12726146Skarels if (router.sin_addr.s_addr == -1) { 12826146Skarels hp = gethostbyname(host); 12935780Sbostic if (hp == NULL) { 13035780Sbostic fprintf(stderr, "query: %s: ", host); 13135780Sbostic herror((char *)NULL); 13226146Skarels exit(1); 13326146Skarels } 134*69005Sbostic memmove(&router.sin_addr, hp->h_addr, hp->h_length); 1356918Ssam } 1368339Ssam sp = getservbyname("router", "udp"); 1378339Ssam if (sp == 0) { 1388339Ssam printf("udp/router: service unknown\n"); 1398339Ssam exit(1); 1408339Ssam } 14115760Skarels router.sin_port = sp->s_port; 1426918Ssam msg->rip_cmd = RIPCMD_REQUEST; 14315760Skarels msg->rip_vers = RIPVERSION; 14415760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 14515760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 14615760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 14746785Sbostic (struct sockaddr *)&router, sizeof(router)) < 0) 1486918Ssam perror(host); 1496918Ssam } 1506918Ssam 1516918Ssam /* 1526918Ssam * Handle an incoming routing packet. 1536918Ssam */ 1546918Ssam rip_input(from, size) 1556918Ssam struct sockaddr_in *from; 1566918Ssam int size; 1576918Ssam { 1586918Ssam register struct rip *msg = (struct rip *)packet; 15928205Skarels register struct netinfo *n; 1606918Ssam char *name; 16122547Skarels int lna, net, subnet; 1628339Ssam struct hostent *hp; 1638339Ssam struct netent *np; 1646918Ssam 1656918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1666918Ssam return; 16726959Skarels printf("%d bytes from ", size); 16826146Skarels if (nflag) 16926146Skarels printf("%s:\n", inet_ntoa(from->sin_addr)); 17026146Skarels else { 17146785Sbostic hp = gethostbyaddr((char *)&from->sin_addr, 17246785Sbostic sizeof (struct in_addr), AF_INET); 17326146Skarels name = hp == 0 ? "???" : hp->h_name; 17426146Skarels printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 17526146Skarels } 1766918Ssam size -= sizeof (int); 1776918Ssam n = msg->rip_nets; 1786918Ssam while (size > 0) { 17928205Skarels if (size < sizeof (struct netinfo)) 18028205Skarels break; 18128205Skarels if (msg->rip_vers > 0) { 18228205Skarels n->rip_dst.sa_family = 18328205Skarels ntohs(n->rip_dst.sa_family); 18428205Skarels n->rip_metric = ntohl(n->rip_metric); 18528205Skarels } 18628205Skarels switch (n->rip_dst.sa_family) { 1876918Ssam 18828205Skarels case AF_INET: 18928205Skarels { register struct sockaddr_in *sin; 19028205Skarels 1916918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 19222547Skarels net = inet_netof(sin->sin_addr); 19322547Skarels subnet = inet_subnetof(sin->sin_addr); 19422547Skarels lna = inet_lnaof(sin->sin_addr); 19522547Skarels name = "???"; 19626146Skarels if (!nflag) { 19728205Skarels if (sin->sin_addr.s_addr == 0) 19828205Skarels name = "default"; 19928205Skarels else if (lna == INADDR_ANY) { 20026146Skarels np = getnetbyaddr(net, AF_INET); 20126146Skarels if (np) 20226146Skarels name = np->n_name; 20326146Skarels else if (net == 0) 20426146Skarels name = "default"; 20526959Skarels } else if ((lna & 0xff) == 0 && 20626146Skarels (np = getnetbyaddr(subnet, AF_INET))) { 20726146Skarels struct in_addr subnaddr, inet_makeaddr(); 20822547Skarels 20926146Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 21026146Skarels if (bcmp(&sin->sin_addr, &subnaddr, 21126146Skarels sizeof(subnaddr)) == 0) 21226146Skarels name = np->n_name; 21326146Skarels else 21426146Skarels goto host; 21526146Skarels } else { 21626146Skarels host: 21746785Sbostic hp = gethostbyaddr((char *)&sin->sin_addr, 21826146Skarels sizeof (struct in_addr), AF_INET); 21926146Skarels if (hp) 22026146Skarels name = hp->h_name; 22126146Skarels } 22234708Skarels printf("\t%-17s metric %2d name %s\n", 22334708Skarels inet_ntoa(sin->sin_addr), n->rip_metric, name); 22426146Skarels } else 22534708Skarels printf("\t%-17s metric %2d\n", 22626146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 22728205Skarels break; 22828205Skarels } 22928205Skarels 23028205Skarels default: 23128205Skarels { u_short *p = (u_short *)n->rip_dst.sa_data; 23228205Skarels 23328205Skarels printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", 23428205Skarels p[0], p[1], p[2], p[3], p[4], p[5], p[6], 23528205Skarels n->rip_dst.sa_family, 23628205Skarels n->rip_metric); 23728205Skarels break; 23828205Skarels } 23928205Skarels 24028205Skarels } 24128205Skarels size -= sizeof (struct netinfo), n++; 2426918Ssam } 2436918Ssam } 24415760Skarels 24546785Sbostic void 24615760Skarels timeout() 24715760Skarels { 24815760Skarels timedout = 1; 24915760Skarels } 25022547Skarels 25122547Skarels /* 25222547Skarels * Return the possible subnetwork number from an internet address. 25322547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 25422547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 25522547Skarels * information (e.g., we can find a name for this number). 25622547Skarels */ 25722547Skarels inet_subnetof(in) 25822547Skarels struct in_addr in; 25922547Skarels { 26022547Skarels register u_long i = ntohl(in.s_addr); 26122547Skarels 26225382Skarels if (IN_CLASSA(i)) 26325382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 26425382Skarels else if (IN_CLASSB(i)) 26522547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 26625382Skarels else 26725382Skarels return ((i & 0xffffffc0) >> 28); 26822547Skarels } 269