xref: /csrg-svn/sbin/routed/query/query.c (revision 28205)
122643Sdist /*
222643Sdist  * Copyright (c) 1980 Regents of the University of California.
322643Sdist  * All rights reserved.  The Berkeley software License Agreement
422643Sdist  * specifies the terms and conditions for redistribution.
522643Sdist  */
622643Sdist 
76918Ssam #ifndef lint
8*28205Skarels static char sccsid[] = "@(#)query.c	5.7 (Berkeley) 05/15/86";
922643Sdist #endif not lint
106918Ssam 
116918Ssam #include <sys/param.h>
126918Ssam #include <sys/protosw.h>
136918Ssam #include <sys/socket.h>
1415760Skarels #include <sys/time.h>
1515760Skarels #include <netinet/in.h>
166918Ssam #include <errno.h>
176918Ssam #include <stdio.h>
188339Ssam #include <netdb.h>
1925382Skarels #include <protocols/routed.h>
206918Ssam 
2127344Skarels #define	WTIME	5		/* Time to wait for all responses */
2227344Skarels #define	STIME	500000		/* usec to wait for another response */
2315760Skarels 
246918Ssam int	s;
2522547Skarels int	timedout, timeout();
266918Ssam char	packet[MAXPACKETSIZE];
2722547Skarels extern int errno;
2826146Skarels int	nflag;
296918Ssam 
306918Ssam main(argc, argv)
316918Ssam 	int argc;
326918Ssam 	char *argv[];
336918Ssam {
34*28205Skarels 	int cc, count, bits;
356918Ssam 	struct sockaddr from;
3615760Skarels 	int fromlen = sizeof(from);
3727344Skarels 	struct timeval shorttime;
386918Ssam 
396918Ssam 	if (argc < 2) {
4026146Skarels usage:
4126146Skarels 		printf("usage: query [ -n ] hosts...\n");
426918Ssam 		exit(1);
436918Ssam 	}
4415760Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
456918Ssam 	if (s < 0) {
466918Ssam 		perror("socket");
476918Ssam 		exit(2);
486918Ssam 	}
4915760Skarels 
506918Ssam 	argv++, argc--;
5126146Skarels 	if (*argv[0] == '-') {
5226159Skarels 		switch (argv[0][1]) {
5326146Skarels 		case 'n':
5426146Skarels 			nflag++;
5526146Skarels 			break;
5626146Skarels 		default:
5726146Skarels 			goto usage;
5826146Skarels 		}
5926146Skarels 		argc--, argv++;
6026146Skarels 	}
616918Ssam 	while (argc > 0) {
626918Ssam 		query(*argv);
63*28205Skarels 		count++;
646918Ssam 		argv++, argc--;
656918Ssam 	}
666918Ssam 
676918Ssam 	/*
6815760Skarels 	 * Listen for returning packets;
6915760Skarels 	 * may be more than one packet per host.
706918Ssam 	 */
7115760Skarels 	bits = 1 << s;
7227344Skarels 	bzero(&shorttime, sizeof(shorttime));
7327344Skarels 	shorttime.tv_usec = STIME;
7422547Skarels 	signal(SIGALRM, timeout);
7522547Skarels 	alarm(WTIME);
7622547Skarels 	while ((count > 0 && !timedout) ||
7727344Skarels 	    select(20, &bits, 0, 0, &shorttime) > 0) {
7815760Skarels 		cc = recvfrom(s, packet, sizeof (packet), 0,
7915760Skarels 		  &from, &fromlen);
806918Ssam 		if (cc <= 0) {
816918Ssam 			if (cc < 0) {
8222547Skarels 				if (errno == EINTR)
8322547Skarels 					continue;
8415760Skarels 				perror("recvfrom");
856918Ssam 				(void) close(s);
866918Ssam 				exit(1);
876918Ssam 			}
886918Ssam 			continue;
896918Ssam 		}
906918Ssam 		rip_input(&from, cc);
916918Ssam 		count--;
926918Ssam 	}
936918Ssam }
946918Ssam 
956918Ssam query(host)
966918Ssam 	char *host;
976918Ssam {
986918Ssam 	struct sockaddr_in router;
996918Ssam 	register struct rip *msg = (struct rip *)packet;
1008339Ssam 	struct hostent *hp;
1018339Ssam 	struct servent *sp;
1026918Ssam 
1036918Ssam 	bzero((char *)&router, sizeof (router));
10426146Skarels 	router.sin_family = AF_INET;
10526146Skarels 	router.sin_addr.s_addr = inet_addr(host);
10626146Skarels 	if (router.sin_addr.s_addr == -1) {
10726146Skarels 		hp = gethostbyname(host);
10826146Skarels 		if (hp == 0) {
10926146Skarels 			printf("%s: unknown\n", host);
11026146Skarels 			exit(1);
11126146Skarels 		}
11226146Skarels 		bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
1136918Ssam 	}
1148339Ssam 	sp = getservbyname("router", "udp");
1158339Ssam 	if (sp == 0) {
1168339Ssam 		printf("udp/router: service unknown\n");
1178339Ssam 		exit(1);
1188339Ssam 	}
11915760Skarels 	router.sin_port = sp->s_port;
1206918Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
12115760Skarels 	msg->rip_vers = RIPVERSION;
12215760Skarels 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
12315760Skarels 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
12415760Skarels 	if (sendto(s, packet, sizeof (struct rip), 0,
12515760Skarels 	  &router, sizeof(router)) < 0)
1266918Ssam 		perror(host);
1276918Ssam }
1286918Ssam 
1296918Ssam /*
1306918Ssam  * Handle an incoming routing packet.
1316918Ssam  */
1326918Ssam rip_input(from, size)
1336918Ssam 	struct sockaddr_in *from;
1346918Ssam 	int size;
1356918Ssam {
1366918Ssam 	register struct rip *msg = (struct rip *)packet;
137*28205Skarels 	register struct netinfo *n;
1386918Ssam 	char *name;
13922547Skarels 	int lna, net, subnet;
1408339Ssam 	struct hostent *hp;
1418339Ssam 	struct netent *np;
1426918Ssam 
1436918Ssam 	if (msg->rip_cmd != RIPCMD_RESPONSE)
1446918Ssam 		return;
14526959Skarels 	printf("%d bytes from ", size);
14626146Skarels 	if (nflag)
14726146Skarels 		printf("%s:\n", inet_ntoa(from->sin_addr));
14826146Skarels 	else {
14926146Skarels 		hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr),
15026146Skarels 			AF_INET);
15126146Skarels 		name = hp == 0 ? "???" : hp->h_name;
15226146Skarels 		printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
15326146Skarels 	}
1546918Ssam 	size -= sizeof (int);
1556918Ssam 	n = msg->rip_nets;
1566918Ssam 	while (size > 0) {
157*28205Skarels 	    if (size < sizeof (struct netinfo))
158*28205Skarels 		    break;
159*28205Skarels 	    if (msg->rip_vers > 0) {
160*28205Skarels 		    n->rip_dst.sa_family =
161*28205Skarels 			    ntohs(n->rip_dst.sa_family);
162*28205Skarels 		    n->rip_metric = ntohl(n->rip_metric);
163*28205Skarels 	    }
164*28205Skarels 	    switch (n->rip_dst.sa_family) {
1656918Ssam 
166*28205Skarels 	    case AF_INET:
167*28205Skarels 		{ register struct sockaddr_in *sin;
168*28205Skarels 
1696918Ssam 		sin = (struct sockaddr_in *)&n->rip_dst;
17022547Skarels 		net = inet_netof(sin->sin_addr);
17122547Skarels 		subnet = inet_subnetof(sin->sin_addr);
17222547Skarels 		lna = inet_lnaof(sin->sin_addr);
17322547Skarels 		name = "???";
17426146Skarels 		if (!nflag) {
175*28205Skarels 			if (sin->sin_addr.s_addr == 0)
176*28205Skarels 				name = "default";
177*28205Skarels 			else if (lna == INADDR_ANY) {
17826146Skarels 				np = getnetbyaddr(net, AF_INET);
17926146Skarels 				if (np)
18026146Skarels 					name = np->n_name;
18126146Skarels 				else if (net == 0)
18226146Skarels 					name = "default";
18326959Skarels 			} else if ((lna & 0xff) == 0 &&
18426146Skarels 			    (np = getnetbyaddr(subnet, AF_INET))) {
18526146Skarels 				struct in_addr subnaddr, inet_makeaddr();
18622547Skarels 
18726146Skarels 				subnaddr = inet_makeaddr(subnet, INADDR_ANY);
18826146Skarels 				if (bcmp(&sin->sin_addr, &subnaddr,
18926146Skarels 				    sizeof(subnaddr)) == 0)
19026146Skarels 					name = np->n_name;
19126146Skarels 				else
19226146Skarels 					goto host;
19326146Skarels 			} else {
19426146Skarels 	host:
19526146Skarels 				hp = gethostbyaddr(&sin->sin_addr,
19626146Skarels 				    sizeof (struct in_addr), AF_INET);
19726146Skarels 				if (hp)
19826146Skarels 					name = hp->h_name;
19926146Skarels 			}
20026146Skarels 			printf("\t%s(%s), metric %d\n", name,
20126146Skarels 				inet_ntoa(sin->sin_addr), n->rip_metric);
20226146Skarels 		} else
20326146Skarels 			printf("\t%s, metric %d\n",
20426146Skarels 				inet_ntoa(sin->sin_addr), n->rip_metric);
205*28205Skarels 		break;
206*28205Skarels 		}
207*28205Skarels 
208*28205Skarels 	    default:
209*28205Skarels 		{ u_short *p = (u_short *)n->rip_dst.sa_data;
210*28205Skarels 
211*28205Skarels 		printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
212*28205Skarels 		    p[0], p[1], p[2], p[3], p[4], p[5], p[6],
213*28205Skarels 		    n->rip_dst.sa_family,
214*28205Skarels 		    n->rip_metric);
215*28205Skarels 		break;
216*28205Skarels 		}
217*28205Skarels 
218*28205Skarels 	    }
219*28205Skarels 	    size -= sizeof (struct netinfo), n++;
2206918Ssam 	}
2216918Ssam }
22215760Skarels 
22315760Skarels timeout()
22415760Skarels {
22515760Skarels 	timedout = 1;
22615760Skarels }
22722547Skarels 
22822547Skarels /*
22922547Skarels  * Return the possible subnetwork number from an internet address.
23022547Skarels  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
23122547Skarels  * INSIDE OF THE HOST PART.  We can only believe this if we have other
23222547Skarels  * information (e.g., we can find a name for this number).
23322547Skarels  */
23422547Skarels inet_subnetof(in)
23522547Skarels 	struct in_addr in;
23622547Skarels {
23722547Skarels 	register u_long i = ntohl(in.s_addr);
23822547Skarels 
23925382Skarels 	if (IN_CLASSA(i))
24025382Skarels 		return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
24125382Skarels 	else if (IN_CLASSB(i))
24222547Skarels 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
24325382Skarels 	else
24425382Skarels 		return ((i & 0xffffffc0) >> 28);
24522547Skarels }
246