xref: /csrg-svn/sbin/routed/query/query.c (revision 33488)
122643Sdist /*
222643Sdist  * Copyright (c) 1980 Regents of the University of California.
3*33488Sbostic  * All rights reserved.
4*33488Sbostic  *
5*33488Sbostic  * Redistribution and use in source and binary forms are permitted
6*33488Sbostic  * provided that this notice is preserved and that due credit is given
7*33488Sbostic  * to the University of California at Berkeley. The name of the University
8*33488Sbostic  * may not be used to endorse or promote products derived from this
9*33488Sbostic  * software without specific prior written permission. This software
10*33488Sbostic  * is provided ``as is'' without express or implied warranty.
1122643Sdist  */
1222643Sdist 
136918Ssam #ifndef lint
14*33488Sbostic char copyright[] =
15*33488Sbostic "@(#) Copyright (c) 1980 Regents of the University of California.\n\
16*33488Sbostic  All rights reserved.\n";
17*33488Sbostic #endif /* not lint */
186918Ssam 
19*33488Sbostic #ifndef lint
20*33488Sbostic static char sccsid[] = "@(#)query.c	5.8 (Berkeley) 02/16/88";
21*33488Sbostic #endif /* not lint */
22*33488Sbostic 
236918Ssam #include <sys/param.h>
246918Ssam #include <sys/protosw.h>
256918Ssam #include <sys/socket.h>
2615760Skarels #include <sys/time.h>
2715760Skarels #include <netinet/in.h>
286918Ssam #include <errno.h>
296918Ssam #include <stdio.h>
308339Ssam #include <netdb.h>
3125382Skarels #include <protocols/routed.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;
3722547Skarels int	timedout, timeout();
386918Ssam char	packet[MAXPACKETSIZE];
3922547Skarels extern int errno;
4026146Skarels int	nflag;
416918Ssam 
426918Ssam main(argc, argv)
436918Ssam 	int argc;
446918Ssam 	char *argv[];
456918Ssam {
4628205Skarels 	int cc, count, bits;
476918Ssam 	struct sockaddr from;
4815760Skarels 	int fromlen = sizeof(from);
4927344Skarels 	struct timeval shorttime;
506918Ssam 
516918Ssam 	if (argc < 2) {
5226146Skarels usage:
5326146Skarels 		printf("usage: query [ -n ] hosts...\n");
546918Ssam 		exit(1);
556918Ssam 	}
5615760Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
576918Ssam 	if (s < 0) {
586918Ssam 		perror("socket");
596918Ssam 		exit(2);
606918Ssam 	}
6115760Skarels 
626918Ssam 	argv++, argc--;
6326146Skarels 	if (*argv[0] == '-') {
6426159Skarels 		switch (argv[0][1]) {
6526146Skarels 		case 'n':
6626146Skarels 			nflag++;
6726146Skarels 			break;
6826146Skarels 		default:
6926146Skarels 			goto usage;
7026146Skarels 		}
7126146Skarels 		argc--, argv++;
7226146Skarels 	}
736918Ssam 	while (argc > 0) {
746918Ssam 		query(*argv);
7528205Skarels 		count++;
766918Ssam 		argv++, argc--;
776918Ssam 	}
786918Ssam 
796918Ssam 	/*
8015760Skarels 	 * Listen for returning packets;
8115760Skarels 	 * may be more than one packet per host.
826918Ssam 	 */
8315760Skarels 	bits = 1 << s;
8427344Skarels 	bzero(&shorttime, sizeof(shorttime));
8527344Skarels 	shorttime.tv_usec = STIME;
8622547Skarels 	signal(SIGALRM, timeout);
8722547Skarels 	alarm(WTIME);
8822547Skarels 	while ((count > 0 && !timedout) ||
8927344Skarels 	    select(20, &bits, 0, 0, &shorttime) > 0) {
9015760Skarels 		cc = recvfrom(s, packet, sizeof (packet), 0,
9115760Skarels 		  &from, &fromlen);
926918Ssam 		if (cc <= 0) {
936918Ssam 			if (cc < 0) {
9422547Skarels 				if (errno == EINTR)
9522547Skarels 					continue;
9615760Skarels 				perror("recvfrom");
976918Ssam 				(void) close(s);
986918Ssam 				exit(1);
996918Ssam 			}
1006918Ssam 			continue;
1016918Ssam 		}
1026918Ssam 		rip_input(&from, cc);
1036918Ssam 		count--;
1046918Ssam 	}
1056918Ssam }
1066918Ssam 
1076918Ssam query(host)
1086918Ssam 	char *host;
1096918Ssam {
1106918Ssam 	struct sockaddr_in router;
1116918Ssam 	register struct rip *msg = (struct rip *)packet;
1128339Ssam 	struct hostent *hp;
1138339Ssam 	struct servent *sp;
1146918Ssam 
1156918Ssam 	bzero((char *)&router, sizeof (router));
11626146Skarels 	router.sin_family = AF_INET;
11726146Skarels 	router.sin_addr.s_addr = inet_addr(host);
11826146Skarels 	if (router.sin_addr.s_addr == -1) {
11926146Skarels 		hp = gethostbyname(host);
12026146Skarels 		if (hp == 0) {
12126146Skarels 			printf("%s: unknown\n", host);
12226146Skarels 			exit(1);
12326146Skarels 		}
12426146Skarels 		bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
1256918Ssam 	}
1268339Ssam 	sp = getservbyname("router", "udp");
1278339Ssam 	if (sp == 0) {
1288339Ssam 		printf("udp/router: service unknown\n");
1298339Ssam 		exit(1);
1308339Ssam 	}
13115760Skarels 	router.sin_port = sp->s_port;
1326918Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
13315760Skarels 	msg->rip_vers = RIPVERSION;
13415760Skarels 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
13515760Skarels 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
13615760Skarels 	if (sendto(s, packet, sizeof (struct rip), 0,
13715760Skarels 	  &router, sizeof(router)) < 0)
1386918Ssam 		perror(host);
1396918Ssam }
1406918Ssam 
1416918Ssam /*
1426918Ssam  * Handle an incoming routing packet.
1436918Ssam  */
1446918Ssam rip_input(from, size)
1456918Ssam 	struct sockaddr_in *from;
1466918Ssam 	int size;
1476918Ssam {
1486918Ssam 	register struct rip *msg = (struct rip *)packet;
14928205Skarels 	register struct netinfo *n;
1506918Ssam 	char *name;
15122547Skarels 	int lna, net, subnet;
1528339Ssam 	struct hostent *hp;
1538339Ssam 	struct netent *np;
1546918Ssam 
1556918Ssam 	if (msg->rip_cmd != RIPCMD_RESPONSE)
1566918Ssam 		return;
15726959Skarels 	printf("%d bytes from ", size);
15826146Skarels 	if (nflag)
15926146Skarels 		printf("%s:\n", inet_ntoa(from->sin_addr));
16026146Skarels 	else {
16126146Skarels 		hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr),
16226146Skarels 			AF_INET);
16326146Skarels 		name = hp == 0 ? "???" : hp->h_name;
16426146Skarels 		printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
16526146Skarels 	}
1666918Ssam 	size -= sizeof (int);
1676918Ssam 	n = msg->rip_nets;
1686918Ssam 	while (size > 0) {
16928205Skarels 	    if (size < sizeof (struct netinfo))
17028205Skarels 		    break;
17128205Skarels 	    if (msg->rip_vers > 0) {
17228205Skarels 		    n->rip_dst.sa_family =
17328205Skarels 			    ntohs(n->rip_dst.sa_family);
17428205Skarels 		    n->rip_metric = ntohl(n->rip_metric);
17528205Skarels 	    }
17628205Skarels 	    switch (n->rip_dst.sa_family) {
1776918Ssam 
17828205Skarels 	    case AF_INET:
17928205Skarels 		{ register struct sockaddr_in *sin;
18028205Skarels 
1816918Ssam 		sin = (struct sockaddr_in *)&n->rip_dst;
18222547Skarels 		net = inet_netof(sin->sin_addr);
18322547Skarels 		subnet = inet_subnetof(sin->sin_addr);
18422547Skarels 		lna = inet_lnaof(sin->sin_addr);
18522547Skarels 		name = "???";
18626146Skarels 		if (!nflag) {
18728205Skarels 			if (sin->sin_addr.s_addr == 0)
18828205Skarels 				name = "default";
18928205Skarels 			else if (lna == INADDR_ANY) {
19026146Skarels 				np = getnetbyaddr(net, AF_INET);
19126146Skarels 				if (np)
19226146Skarels 					name = np->n_name;
19326146Skarels 				else if (net == 0)
19426146Skarels 					name = "default";
19526959Skarels 			} else if ((lna & 0xff) == 0 &&
19626146Skarels 			    (np = getnetbyaddr(subnet, AF_INET))) {
19726146Skarels 				struct in_addr subnaddr, inet_makeaddr();
19822547Skarels 
19926146Skarels 				subnaddr = inet_makeaddr(subnet, INADDR_ANY);
20026146Skarels 				if (bcmp(&sin->sin_addr, &subnaddr,
20126146Skarels 				    sizeof(subnaddr)) == 0)
20226146Skarels 					name = np->n_name;
20326146Skarels 				else
20426146Skarels 					goto host;
20526146Skarels 			} else {
20626146Skarels 	host:
20726146Skarels 				hp = gethostbyaddr(&sin->sin_addr,
20826146Skarels 				    sizeof (struct in_addr), AF_INET);
20926146Skarels 				if (hp)
21026146Skarels 					name = hp->h_name;
21126146Skarels 			}
21226146Skarels 			printf("\t%s(%s), metric %d\n", name,
21326146Skarels 				inet_ntoa(sin->sin_addr), n->rip_metric);
21426146Skarels 		} else
21526146Skarels 			printf("\t%s, metric %d\n",
21626146Skarels 				inet_ntoa(sin->sin_addr), n->rip_metric);
21728205Skarels 		break;
21828205Skarels 		}
21928205Skarels 
22028205Skarels 	    default:
22128205Skarels 		{ u_short *p = (u_short *)n->rip_dst.sa_data;
22228205Skarels 
22328205Skarels 		printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
22428205Skarels 		    p[0], p[1], p[2], p[3], p[4], p[5], p[6],
22528205Skarels 		    n->rip_dst.sa_family,
22628205Skarels 		    n->rip_metric);
22728205Skarels 		break;
22828205Skarels 		}
22928205Skarels 
23028205Skarels 	    }
23128205Skarels 	    size -= sizeof (struct netinfo), n++;
2326918Ssam 	}
2336918Ssam }
23415760Skarels 
23515760Skarels timeout()
23615760Skarels {
23715760Skarels 	timedout = 1;
23815760Skarels }
23922547Skarels 
24022547Skarels /*
24122547Skarels  * Return the possible subnetwork number from an internet address.
24222547Skarels  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
24322547Skarels  * INSIDE OF THE HOST PART.  We can only believe this if we have other
24422547Skarels  * information (e.g., we can find a name for this number).
24522547Skarels  */
24622547Skarels inet_subnetof(in)
24722547Skarels 	struct in_addr in;
24822547Skarels {
24922547Skarels 	register u_long i = ntohl(in.s_addr);
25022547Skarels 
25125382Skarels 	if (IN_CLASSA(i))
25225382Skarels 		return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
25325382Skarels 	else if (IN_CLASSB(i))
25422547Skarels 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
25525382Skarels 	else
25625382Skarels 		return ((i & 0xffffffc0) >> 28);
25722547Skarels }
258