122643Sdist /* 222643Sdist * Copyright (c) 1980 Regents of the University of California. 333488Sbostic * All rights reserved. 433488Sbostic * 533488Sbostic * Redistribution and use in source and binary forms are permitted 634770Sbostic * provided that the above copyright notice and this paragraph are 734770Sbostic * duplicated in all such forms and that any documentation, 834770Sbostic * advertising materials, and other materials related to such 934770Sbostic * distribution and use acknowledge that the software was developed 1034770Sbostic * by the University of California, Berkeley. The name of the 1134770Sbostic * University may not be used to endorse or promote products derived 1234770Sbostic * from this software without specific prior written permission. 1334770Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434770Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534770Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622643Sdist */ 1722643Sdist 186918Ssam #ifndef lint 1933488Sbostic char copyright[] = 2033488Sbostic "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 2133488Sbostic All rights reserved.\n"; 2233488Sbostic #endif /* not lint */ 236918Ssam 2433488Sbostic #ifndef lint 25*46785Sbostic static char sccsid[] = "@(#)query.c 5.12 (Berkeley) 02/28/91"; 2633488Sbostic #endif /* not lint */ 2733488Sbostic 286918Ssam #include <sys/param.h> 296918Ssam #include <sys/protosw.h> 306918Ssam #include <sys/socket.h> 3115760Skarels #include <sys/time.h> 32*46785Sbostic #include <signal.h> 3315760Skarels #include <netinet/in.h> 34*46785Sbostic #include <protocols/routed.h> 35*46785Sbostic #include <arpa/inet.h> 36*46785Sbostic #include <netdb.h> 376918Ssam #include <errno.h> 38*46785Sbostic #include <unistd.h> 396918Ssam #include <stdio.h> 40*46785Sbostic #include <stdlib.h> 41*46785Sbostic #include <string.h> 426918Ssam 4327344Skarels #define WTIME 5 /* Time to wait for all responses */ 4427344Skarels #define STIME 500000 /* usec to wait for another response */ 4515760Skarels 466918Ssam int s; 47*46785Sbostic int timedout; 48*46785Sbostic void timeout(); 496918Ssam char packet[MAXPACKETSIZE]; 5026146Skarels int nflag; 516918Ssam 526918Ssam main(argc, argv) 536918Ssam int argc; 546918Ssam char *argv[]; 556918Ssam { 5635780Sbostic extern char *optarg; 5735780Sbostic extern int optind; 5835780Sbostic int ch, cc, count, bits; 596918Ssam struct sockaddr from; 6034708Skarels int fromlen = sizeof(from), size = 32*1024; 6127344Skarels struct timeval shorttime; 6235780Sbostic 6335780Sbostic while ((ch = getopt(argc, argv, "n")) != EOF) 6435780Sbostic switch((char)ch) { 6535780Sbostic case 'n': 6635780Sbostic nflag++; 6735780Sbostic break; 6835780Sbostic case '?': 6935780Sbostic default: 7035780Sbostic goto usage; 7135780Sbostic } 7235780Sbostic argv += optind; 7335780Sbostic 7435780Sbostic if (!*argv) { 7535780Sbostic usage: printf("usage: query [-n] hosts...\n"); 766918Ssam exit(1); 776918Ssam } 7835780Sbostic 7915760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 806918Ssam if (s < 0) { 816918Ssam perror("socket"); 826918Ssam exit(2); 836918Ssam } 8434708Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) 8534708Skarels perror("setsockopt SO_RCVBUF"); 8615760Skarels 8735780Sbostic while (*argv) { 8835780Sbostic query(*argv++); 8928205Skarels count++; 906918Ssam } 916918Ssam 926918Ssam /* 9315760Skarels * Listen for returning packets; 9415760Skarels * may be more than one packet per host. 956918Ssam */ 9615760Skarels bits = 1 << s; 9727344Skarels bzero(&shorttime, sizeof(shorttime)); 9827344Skarels shorttime.tv_usec = STIME; 9922547Skarels signal(SIGALRM, timeout); 10022547Skarels alarm(WTIME); 10122547Skarels while ((count > 0 && !timedout) || 102*46785Sbostic select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) { 10315760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 10415760Skarels &from, &fromlen); 1056918Ssam if (cc <= 0) { 1066918Ssam if (cc < 0) { 10722547Skarels if (errno == EINTR) 10822547Skarels continue; 10915760Skarels perror("recvfrom"); 1106918Ssam (void) close(s); 1116918Ssam exit(1); 1126918Ssam } 1136918Ssam continue; 1146918Ssam } 1156918Ssam rip_input(&from, cc); 1166918Ssam count--; 1176918Ssam } 11834708Skarels exit (count > 0 ? count : 0); 1196918Ssam } 1206918Ssam 1216918Ssam query(host) 1226918Ssam char *host; 1236918Ssam { 1246918Ssam struct sockaddr_in router; 1256918Ssam register struct rip *msg = (struct rip *)packet; 1268339Ssam struct hostent *hp; 1278339Ssam struct servent *sp; 1286918Ssam 1296918Ssam bzero((char *)&router, sizeof (router)); 13026146Skarels router.sin_family = AF_INET; 13126146Skarels router.sin_addr.s_addr = inet_addr(host); 13226146Skarels if (router.sin_addr.s_addr == -1) { 13326146Skarels hp = gethostbyname(host); 13435780Sbostic if (hp == NULL) { 13535780Sbostic fprintf(stderr, "query: %s: ", host); 13635780Sbostic herror((char *)NULL); 13726146Skarels exit(1); 13826146Skarels } 13926146Skarels bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 1406918Ssam } 1418339Ssam sp = getservbyname("router", "udp"); 1428339Ssam if (sp == 0) { 1438339Ssam printf("udp/router: service unknown\n"); 1448339Ssam exit(1); 1458339Ssam } 14615760Skarels router.sin_port = sp->s_port; 1476918Ssam msg->rip_cmd = RIPCMD_REQUEST; 14815760Skarels msg->rip_vers = RIPVERSION; 14915760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 15015760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 15115760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 152*46785Sbostic (struct sockaddr *)&router, sizeof(router)) < 0) 1536918Ssam perror(host); 1546918Ssam } 1556918Ssam 1566918Ssam /* 1576918Ssam * Handle an incoming routing packet. 1586918Ssam */ 1596918Ssam rip_input(from, size) 1606918Ssam struct sockaddr_in *from; 1616918Ssam int size; 1626918Ssam { 1636918Ssam register struct rip *msg = (struct rip *)packet; 16428205Skarels register struct netinfo *n; 1656918Ssam char *name; 16622547Skarels int lna, net, subnet; 1678339Ssam struct hostent *hp; 1688339Ssam struct netent *np; 1696918Ssam 1706918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1716918Ssam return; 17226959Skarels printf("%d bytes from ", size); 17326146Skarels if (nflag) 17426146Skarels printf("%s:\n", inet_ntoa(from->sin_addr)); 17526146Skarels else { 176*46785Sbostic hp = gethostbyaddr((char *)&from->sin_addr, 177*46785Sbostic sizeof (struct in_addr), AF_INET); 17826146Skarels name = hp == 0 ? "???" : hp->h_name; 17926146Skarels printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 18026146Skarels } 1816918Ssam size -= sizeof (int); 1826918Ssam n = msg->rip_nets; 1836918Ssam while (size > 0) { 18428205Skarels if (size < sizeof (struct netinfo)) 18528205Skarels break; 18628205Skarels if (msg->rip_vers > 0) { 18728205Skarels n->rip_dst.sa_family = 18828205Skarels ntohs(n->rip_dst.sa_family); 18928205Skarels n->rip_metric = ntohl(n->rip_metric); 19028205Skarels } 19128205Skarels switch (n->rip_dst.sa_family) { 1926918Ssam 19328205Skarels case AF_INET: 19428205Skarels { register struct sockaddr_in *sin; 19528205Skarels 1966918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 19722547Skarels net = inet_netof(sin->sin_addr); 19822547Skarels subnet = inet_subnetof(sin->sin_addr); 19922547Skarels lna = inet_lnaof(sin->sin_addr); 20022547Skarels name = "???"; 20126146Skarels if (!nflag) { 20228205Skarels if (sin->sin_addr.s_addr == 0) 20328205Skarels name = "default"; 20428205Skarels else if (lna == INADDR_ANY) { 20526146Skarels np = getnetbyaddr(net, AF_INET); 20626146Skarels if (np) 20726146Skarels name = np->n_name; 20826146Skarels else if (net == 0) 20926146Skarels name = "default"; 21026959Skarels } else if ((lna & 0xff) == 0 && 21126146Skarels (np = getnetbyaddr(subnet, AF_INET))) { 21226146Skarels struct in_addr subnaddr, inet_makeaddr(); 21322547Skarels 21426146Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 21526146Skarels if (bcmp(&sin->sin_addr, &subnaddr, 21626146Skarels sizeof(subnaddr)) == 0) 21726146Skarels name = np->n_name; 21826146Skarels else 21926146Skarels goto host; 22026146Skarels } else { 22126146Skarels host: 222*46785Sbostic hp = gethostbyaddr((char *)&sin->sin_addr, 22326146Skarels sizeof (struct in_addr), AF_INET); 22426146Skarels if (hp) 22526146Skarels name = hp->h_name; 22626146Skarels } 22734708Skarels printf("\t%-17s metric %2d name %s\n", 22834708Skarels inet_ntoa(sin->sin_addr), n->rip_metric, name); 22926146Skarels } else 23034708Skarels printf("\t%-17s metric %2d\n", 23126146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 23228205Skarels break; 23328205Skarels } 23428205Skarels 23528205Skarels default: 23628205Skarels { u_short *p = (u_short *)n->rip_dst.sa_data; 23728205Skarels 23828205Skarels printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", 23928205Skarels p[0], p[1], p[2], p[3], p[4], p[5], p[6], 24028205Skarels n->rip_dst.sa_family, 24128205Skarels n->rip_metric); 24228205Skarels break; 24328205Skarels } 24428205Skarels 24528205Skarels } 24628205Skarels size -= sizeof (struct netinfo), n++; 2476918Ssam } 2486918Ssam } 24915760Skarels 250*46785Sbostic void 25115760Skarels timeout() 25215760Skarels { 25315760Skarels timedout = 1; 25415760Skarels } 25522547Skarels 25622547Skarels /* 25722547Skarels * Return the possible subnetwork number from an internet address. 25822547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 25922547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 26022547Skarels * information (e.g., we can find a name for this number). 26122547Skarels */ 26222547Skarels inet_subnetof(in) 26322547Skarels struct in_addr in; 26422547Skarels { 26522547Skarels register u_long i = ntohl(in.s_addr); 26622547Skarels 26725382Skarels if (IN_CLASSA(i)) 26825382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 26925382Skarels else if (IN_CLASSB(i)) 27022547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 27125382Skarels else 27225382Skarels return ((i & 0xffffffc0) >> 28); 27322547Skarels } 274