xref: /original-bsd/sbin/routed/query/query.c (revision 8be56b44)
1d68e9e89Sbostic /*-
2b85741d3Sbostic  * Copyright (c) 1982, 1986, 1993
3b85741d3Sbostic  *	The Regents of the University of California.  All rights reserved.
471649b73Sbostic  *
5d68e9e89Sbostic  * %sccs.include.redist.c%
61396dbf7Sdist  */
71396dbf7Sdist 
89b365abaSsam #ifndef lint
9b85741d3Sbostic static char copyright[] =
10b85741d3Sbostic "@(#) Copyright (c) 1982, 1986, 1993\n\
11b85741d3Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1271649b73Sbostic #endif /* not lint */
1371649b73Sbostic 
1471649b73Sbostic #ifndef lint
15*8be56b44Sbostic static char sccsid[] = "@(#)query.c	8.3 (Berkeley) 04/28/95";
1671649b73Sbostic #endif /* not lint */
179b365abaSsam 
189b365abaSsam #include <sys/param.h>
199b365abaSsam #include <sys/protosw.h>
209b365abaSsam #include <sys/socket.h>
21cdf54960Skarels #include <sys/time.h>
225b91b0bdSbostic #include <signal.h>
23cdf54960Skarels #include <netinet/in.h>
2497e0edb5Skarels #include <protocols/routed.h>
255b91b0bdSbostic #include <arpa/inet.h>
265b91b0bdSbostic #include <netdb.h>
275b91b0bdSbostic #include <errno.h>
285b91b0bdSbostic #include <unistd.h>
295b91b0bdSbostic #include <stdio.h>
305b91b0bdSbostic #include <stdlib.h>
315b91b0bdSbostic #include <string.h>
32cdf54960Skarels 
33f90b58b9Skarels #define	WTIME	5		/* Time to wait for all responses */
34f90b58b9Skarels #define	STIME	500000		/* usec to wait for another response */
359b365abaSsam 
369b365abaSsam int	s;
375b91b0bdSbostic int	timedout;
385b91b0bdSbostic void	timeout();
399b365abaSsam char	packet[MAXPACKETSIZE];
400bfbf616Skarels int	nflag;
419b365abaSsam 
main(argc,argv)429b365abaSsam main(argc, argv)
439b365abaSsam 	int argc;
449b365abaSsam 	char *argv[];
459b365abaSsam {
46cc7332b2Sbostic 	extern char *optarg;
47cc7332b2Sbostic 	extern int optind;
48cc7332b2Sbostic 	int ch, cc, count, bits;
499b365abaSsam 	struct sockaddr from;
50da6e0decSkarels 	struct sigaction sigact;
5159042548Skarels 	int fromlen = sizeof(from), size = 32*1024;
52f90b58b9Skarels 	struct timeval shorttime;
539b365abaSsam 
54cc7332b2Sbostic 	while ((ch = getopt(argc, argv, "n")) != EOF)
55da6e0decSkarels 		switch (ch) {
56cc7332b2Sbostic 		case 'n':
57cc7332b2Sbostic 			nflag++;
58cc7332b2Sbostic 			break;
59cc7332b2Sbostic 		case '?':
60cc7332b2Sbostic 		default:
61cc7332b2Sbostic 			goto usage;
62cc7332b2Sbostic 		}
63cc7332b2Sbostic 	argv += optind;
64cc7332b2Sbostic 
65cc7332b2Sbostic 	if (!*argv) {
66cc7332b2Sbostic usage:		printf("usage: query [-n] hosts...\n");
679b365abaSsam 		exit(1);
689b365abaSsam 	}
69cc7332b2Sbostic 
70cdf54960Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
719b365abaSsam 	if (s < 0) {
729b365abaSsam 		perror("socket");
739b365abaSsam 		exit(2);
749b365abaSsam 	}
7559042548Skarels 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
7659042548Skarels 		perror("setsockopt SO_RCVBUF");
77cdf54960Skarels 
78cc7332b2Sbostic 	while (*argv) {
79cc7332b2Sbostic 		query(*argv++);
802814c884Skarels 		count++;
819b365abaSsam 	}
829b365abaSsam 
839b365abaSsam 	/*
84cdf54960Skarels 	 * Listen for returning packets;
85cdf54960Skarels 	 * may be more than one packet per host.
869b365abaSsam 	 */
87cdf54960Skarels 	bits = 1 << s;
8814bb8275Sbostic 	memset(&shorttime, 0, sizeof(shorttime));
89f90b58b9Skarels 	shorttime.tv_usec = STIME;
9014bb8275Sbostic 	memset(&sigact, 0, sizeof(sigact));
91da6e0decSkarels 	sigact.sa_handler = timeout;
92da6e0decSkarels 	/*sigact.sa_flags = 0;		/* no restart */
93da6e0decSkarels 	if (sigaction(SIGALRM, &sigact, (struct sigaction *)NULL) == -1)
94da6e0decSkarels 		perror("sigaction");
954b268ed2Skarels 	alarm(WTIME);
964b268ed2Skarels 	while ((count > 0 && !timedout) ||
975b91b0bdSbostic 	    select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) {
98cdf54960Skarels 		cc = recvfrom(s, packet, sizeof (packet), 0,
99cdf54960Skarels 		  &from, &fromlen);
1009b365abaSsam 		if (cc <= 0) {
1019b365abaSsam 			if (cc < 0) {
1024b268ed2Skarels 				if (errno == EINTR)
1034b268ed2Skarels 					continue;
104cdf54960Skarels 				perror("recvfrom");
1059b365abaSsam 				(void) close(s);
1069b365abaSsam 				exit(1);
1079b365abaSsam 			}
1089b365abaSsam 			continue;
1099b365abaSsam 		}
1109b365abaSsam 		rip_input(&from, cc);
1119b365abaSsam 		count--;
1129b365abaSsam 	}
11359042548Skarels 	exit (count > 0 ? count : 0);
1149b365abaSsam }
1159b365abaSsam 
query(host)1169b365abaSsam query(host)
1179b365abaSsam 	char *host;
1189b365abaSsam {
1199b365abaSsam 	struct sockaddr_in router;
1209b365abaSsam 	register struct rip *msg = (struct rip *)packet;
121dee006a4Ssam 	struct hostent *hp;
122dee006a4Ssam 	struct servent *sp;
1239b365abaSsam 
12414bb8275Sbostic 	memset(&router, 0, sizeof (router));
1250bfbf616Skarels 	router.sin_family = AF_INET;
1260bfbf616Skarels 	router.sin_addr.s_addr = inet_addr(host);
1270bfbf616Skarels 	if (router.sin_addr.s_addr == -1) {
128dee006a4Ssam 		hp = gethostbyname(host);
129cc7332b2Sbostic 		if (hp == NULL) {
130cc7332b2Sbostic 			fprintf(stderr, "query: %s: ", host);
131cc7332b2Sbostic 			herror((char *)NULL);
1329b365abaSsam 			exit(1);
1339b365abaSsam 		}
13414bb8275Sbostic 		memmove(&router.sin_addr, hp->h_addr, hp->h_length);
1350bfbf616Skarels 	}
136dee006a4Ssam 	sp = getservbyname("router", "udp");
137dee006a4Ssam 	if (sp == 0) {
138dee006a4Ssam 		printf("udp/router: service unknown\n");
139dee006a4Ssam 		exit(1);
140dee006a4Ssam 	}
141cdf54960Skarels 	router.sin_port = sp->s_port;
1429b365abaSsam 	msg->rip_cmd = RIPCMD_REQUEST;
143cdf54960Skarels 	msg->rip_vers = RIPVERSION;
144cdf54960Skarels 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
145cdf54960Skarels 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
146cdf54960Skarels 	if (sendto(s, packet, sizeof (struct rip), 0,
1475b91b0bdSbostic 	  (struct sockaddr *)&router, sizeof(router)) < 0)
1489b365abaSsam 		perror(host);
1499b365abaSsam }
1509b365abaSsam 
1519b365abaSsam /*
1529b365abaSsam  * Handle an incoming routing packet.
1539b365abaSsam  */
1549b365abaSsam rip_input(from, size)
1559b365abaSsam 	struct sockaddr_in *from;
1569b365abaSsam 	int size;
1579b365abaSsam {
1589b365abaSsam 	register struct rip *msg = (struct rip *)packet;
1592814c884Skarels 	register struct netinfo *n;
1609b365abaSsam 	char *name;
1614b268ed2Skarels 	int lna, net, subnet;
162dee006a4Ssam 	struct hostent *hp;
163dee006a4Ssam 	struct netent *np;
1649b365abaSsam 
1659b365abaSsam 	if (msg->rip_cmd != RIPCMD_RESPONSE)
1669b365abaSsam 		return;
1678d03b013Skarels 	printf("%d bytes from ", size);
1680bfbf616Skarels 	if (nflag)
1690bfbf616Skarels 		printf("%s:\n", inet_ntoa(from->sin_addr));
1700bfbf616Skarels 	else {
1715b91b0bdSbostic 		hp = gethostbyaddr((char *)&from->sin_addr,
1725b91b0bdSbostic 		    sizeof (struct in_addr), AF_INET);
173dee006a4Ssam 		name = hp == 0 ? "???" : hp->h_name;
1740bfbf616Skarels 		printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
1750bfbf616Skarels 	}
1769b365abaSsam 	size -= sizeof (int);
1779b365abaSsam 	n = msg->rip_nets;
1789b365abaSsam 	while (size > 0) {
1799b365abaSsam 	    if (size < sizeof (struct netinfo))
1809b365abaSsam 		    break;
181cdf54960Skarels 	    if (msg->rip_vers > 0) {
182cdf54960Skarels 		    n->rip_dst.sa_family =
183cdf54960Skarels 			    ntohs(n->rip_dst.sa_family);
184cdf54960Skarels 		    n->rip_metric = ntohl(n->rip_metric);
185cdf54960Skarels 	    }
1862814c884Skarels 	    switch (n->rip_dst.sa_family) {
1872814c884Skarels 
1882814c884Skarels 	    case AF_INET:
1892814c884Skarels 		{ register struct sockaddr_in *sin;
1902814c884Skarels 
1919b365abaSsam 		sin = (struct sockaddr_in *)&n->rip_dst;
1924b268ed2Skarels 		net = inet_netof(sin->sin_addr);
1934b268ed2Skarels 		subnet = inet_subnetof(sin->sin_addr);
1944b268ed2Skarels 		lna = inet_lnaof(sin->sin_addr);
1954b268ed2Skarels 		name = "???";
1960bfbf616Skarels 		if (!nflag) {
1972814c884Skarels 			if (sin->sin_addr.s_addr == 0)
1982814c884Skarels 				name = "default";
1992814c884Skarels 			else if (lna == INADDR_ANY) {
2004b268ed2Skarels 				np = getnetbyaddr(net, AF_INET);
2014b268ed2Skarels 				if (np)
2024b268ed2Skarels 					name = np->n_name;
2034b268ed2Skarels 				else if (net == 0)
2044b268ed2Skarels 					name = "default";
2058d03b013Skarels 			} else if ((lna & 0xff) == 0 &&
2064b268ed2Skarels 			    (np = getnetbyaddr(subnet, AF_INET))) {
2074b268ed2Skarels 				struct in_addr subnaddr, inet_makeaddr();
2084b268ed2Skarels 
2094b268ed2Skarels 				subnaddr = inet_makeaddr(subnet, INADDR_ANY);
210*8be56b44Sbostic 				if (memcmp(&sin->sin_addr, &subnaddr,
2110bfbf616Skarels 				    sizeof(subnaddr)) == 0)
2124b268ed2Skarels 					name = np->n_name;
2134b268ed2Skarels 				else
2144b268ed2Skarels 					goto host;
215dee006a4Ssam 			} else {
2164b268ed2Skarels 	host:
2175b91b0bdSbostic 				hp = gethostbyaddr((char *)&sin->sin_addr,
218c285633cSsam 				    sizeof (struct in_addr), AF_INET);
2194b268ed2Skarels 				if (hp)
2204b268ed2Skarels 					name = hp->h_name;
221dee006a4Ssam 			}
22259042548Skarels 			printf("\t%-17s metric %2d name %s\n",
22359042548Skarels 				inet_ntoa(sin->sin_addr), n->rip_metric, name);
2240bfbf616Skarels 		} else
22559042548Skarels 			printf("\t%-17s metric %2d\n",
2260bfbf616Skarels 				inet_ntoa(sin->sin_addr), n->rip_metric);
2272814c884Skarels 		break;
2282814c884Skarels 		}
2292814c884Skarels 
2302814c884Skarels 	    default:
2312814c884Skarels 		{ u_short *p = (u_short *)n->rip_dst.sa_data;
2322814c884Skarels 
2332814c884Skarels 		printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
2342814c884Skarels 		    p[0], p[1], p[2], p[3], p[4], p[5], p[6],
2352814c884Skarels 		    n->rip_dst.sa_family,
2362814c884Skarels 		    n->rip_metric);
2372814c884Skarels 		break;
2382814c884Skarels 		}
2392814c884Skarels 
2402814c884Skarels 	    }
2419b365abaSsam 	    size -= sizeof (struct netinfo), n++;
2429b365abaSsam 	}
2439b365abaSsam }
244cdf54960Skarels 
2455b91b0bdSbostic void
timeout()246cdf54960Skarels timeout()
247cdf54960Skarels {
248cdf54960Skarels 	timedout = 1;
249cdf54960Skarels }
2504b268ed2Skarels 
2514b268ed2Skarels /*
2524b268ed2Skarels  * Return the possible subnetwork number from an internet address.
2534b268ed2Skarels  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
2544b268ed2Skarels  * INSIDE OF THE HOST PART.  We can only believe this if we have other
2554b268ed2Skarels  * information (e.g., we can find a name for this number).
2564b268ed2Skarels  */
2574b268ed2Skarels inet_subnetof(in)
2584b268ed2Skarels 	struct in_addr in;
2594b268ed2Skarels {
2604b268ed2Skarels 	register u_long i = ntohl(in.s_addr);
2614b268ed2Skarels 
26297e0edb5Skarels 	if (IN_CLASSA(i))
2634b268ed2Skarels 		return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
26497e0edb5Skarels 	else if (IN_CLASSB(i))
2654b268ed2Skarels 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
26697e0edb5Skarels 	else
26797e0edb5Skarels 		return ((i & 0xffffffc0) >> 28);
2684b268ed2Skarels }
269