xref: /csrg-svn/sbin/routed/query/query.c (revision 25382)
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*25382Skarels static char sccsid[] = "@(#)query.c	5.2 (Berkeley) 11/04/85";
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>
19*25382Skarels #include <protocols/routed.h>
206918Ssam 
2115760Skarels #define	WTIME	5		/* Time to wait for responses */
2215760Skarels 
236918Ssam int	s;
2422547Skarels int	timedout, timeout();
256918Ssam char	packet[MAXPACKETSIZE];
2622547Skarels extern int errno;
276918Ssam 
286918Ssam main(argc, argv)
296918Ssam 	int argc;
306918Ssam 	char *argv[];
316918Ssam {
3215760Skarels 	int cc, count, bits;
336918Ssam 	struct sockaddr from;
3415760Skarels 	int fromlen = sizeof(from);
3515760Skarels 	struct timeval notime;
366918Ssam 
376918Ssam 	if (argc < 2) {
386918Ssam 		printf("usage: query hosts...\n");
396918Ssam 		exit(1);
406918Ssam 	}
4115760Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
426918Ssam 	if (s < 0) {
436918Ssam 		perror("socket");
446918Ssam 		exit(2);
456918Ssam 	}
4615760Skarels 
476918Ssam 	argv++, argc--;
486918Ssam 	count = argc;
496918Ssam 	while (argc > 0) {
506918Ssam 		query(*argv);
516918Ssam 		argv++, argc--;
526918Ssam 	}
536918Ssam 
546918Ssam 	/*
5515760Skarels 	 * Listen for returning packets;
5615760Skarels 	 * may be more than one packet per host.
576918Ssam 	 */
5815760Skarels 	bits = 1 << s;
5915760Skarels 	bzero(&notime, sizeof(notime));
6022547Skarels 	signal(SIGALRM, timeout);
6122547Skarels 	alarm(WTIME);
6222547Skarels 	while ((count > 0 && !timedout) ||
6322547Skarels 	    select(20, &bits, 0, 0, &notime) > 0) {
6415760Skarels 		cc = recvfrom(s, packet, sizeof (packet), 0,
6515760Skarels 		  &from, &fromlen);
666918Ssam 		if (cc <= 0) {
676918Ssam 			if (cc < 0) {
6822547Skarels 				if (errno == EINTR)
6922547Skarels 					continue;
7015760Skarels 				perror("recvfrom");
716918Ssam 				(void) close(s);
726918Ssam 				exit(1);
736918Ssam 			}
746918Ssam 			continue;
756918Ssam 		}
766918Ssam 		rip_input(&from, cc);
776918Ssam 		count--;
786918Ssam 	}
796918Ssam }
806918Ssam 
816918Ssam query(host)
826918Ssam 	char *host;
836918Ssam {
846918Ssam 	struct sockaddr_in router;
856918Ssam 	register struct rip *msg = (struct rip *)packet;
868339Ssam 	struct hostent *hp;
878339Ssam 	struct servent *sp;
886918Ssam 
896918Ssam 	bzero((char *)&router, sizeof (router));
908339Ssam 	hp = gethostbyname(host);
918339Ssam 	if (hp == 0) {
926918Ssam 		printf("%s: unknown\n", host);
936918Ssam 		exit(1);
946918Ssam 	}
958339Ssam 	bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
966918Ssam 	router.sin_family = AF_INET;
978339Ssam 	sp = getservbyname("router", "udp");
988339Ssam 	if (sp == 0) {
998339Ssam 		printf("udp/router: service unknown\n");
1008339Ssam 		exit(1);
1018339Ssam 	}
10215760Skarels 	router.sin_port = sp->s_port;
1036918Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
10415760Skarels 	msg->rip_vers = RIPVERSION;
10515760Skarels 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
10615760Skarels 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
10715760Skarels 	if (sendto(s, packet, sizeof (struct rip), 0,
10815760Skarels 	  &router, sizeof(router)) < 0)
1096918Ssam 		perror(host);
1106918Ssam }
1116918Ssam 
1126918Ssam /*
1136918Ssam  * Handle an incoming routing packet.
1146918Ssam  */
1156918Ssam rip_input(from, size)
1166918Ssam 	struct sockaddr_in *from;
1176918Ssam 	int size;
1186918Ssam {
1196918Ssam 	register struct rip *msg = (struct rip *)packet;
1206918Ssam 	struct netinfo *n;
1216918Ssam 	char *name;
12222547Skarels 	int lna, net, subnet;
1238339Ssam 	struct hostent *hp;
1248339Ssam 	struct netent *np;
1256918Ssam 
1266918Ssam 	if (msg->rip_cmd != RIPCMD_RESPONSE)
1276918Ssam 		return;
1288344Ssam 	hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), AF_INET);
1298339Ssam 	name = hp == 0 ? "???" : hp->h_name;
130*25382Skarels 	printf("%d bytes from %s(%s):\n", size, name,
131*25382Skarels 		inet_ntoa(from->sin_addr));
1326918Ssam 	size -= sizeof (int);
1336918Ssam 	n = msg->rip_nets;
1346918Ssam 	while (size > 0) {
1356918Ssam 		register struct sockaddr_in *sin;
1366918Ssam 
1376918Ssam 		if (size < sizeof (struct netinfo))
1386918Ssam 			break;
13915760Skarels 		if (msg->rip_vers > 0) {
14015760Skarels 			n->rip_dst.sa_family =
14115760Skarels 				ntohs(n->rip_dst.sa_family);
14215760Skarels 			n->rip_metric = ntohl(n->rip_metric);
14315760Skarels 		}
1446918Ssam 		sin = (struct sockaddr_in *)&n->rip_dst;
14522547Skarels 		net = inet_netof(sin->sin_addr);
14622547Skarels 		subnet = inet_subnetof(sin->sin_addr);
14722547Skarels 		lna = inet_lnaof(sin->sin_addr);
14822547Skarels 		name = "???";
14922547Skarels 		if (lna == INADDR_ANY) {
15022547Skarels 			np = getnetbyaddr(net, AF_INET);
15122547Skarels 			if (np)
15222547Skarels 				name = np->n_name;
15322547Skarels 			else if (net == 0)
15422547Skarels 				name = "default";
15522547Skarels 		} else if ((subnet != net) && ((lna & 0xff) == 0) &&
15622547Skarels 		    (np = getnetbyaddr(subnet, AF_INET))) {
15722547Skarels 			struct in_addr subnaddr, inet_makeaddr();
15822547Skarels 
15922547Skarels 			subnaddr = inet_makeaddr(subnet, INADDR_ANY);
16022547Skarels 			if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0)
16122547Skarels 				name = np->n_name;
16222547Skarels 			else
16322547Skarels 				goto host;
1648339Ssam 		} else {
16522547Skarels host:
1668339Ssam 			hp = gethostbyaddr(&sin->sin_addr,
16722547Skarels 			    sizeof (struct in_addr), AF_INET);
16822547Skarels 			if (hp)
16922547Skarels 				name = hp->h_name;
1708339Ssam 		}
17115760Skarels 		printf("\t%s(%s), metric %d\n", name,
17215760Skarels 			inet_ntoa(sin->sin_addr), n->rip_metric);
1736918Ssam 		size -= sizeof (struct netinfo), n++;
1746918Ssam 	}
1756918Ssam }
17615760Skarels 
17715760Skarels timeout()
17815760Skarels {
17915760Skarels 	timedout = 1;
18015760Skarels }
18122547Skarels 
18222547Skarels /*
18322547Skarels  * Return the possible subnetwork number from an internet address.
18422547Skarels  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
18522547Skarels  * INSIDE OF THE HOST PART.  We can only believe this if we have other
18622547Skarels  * information (e.g., we can find a name for this number).
18722547Skarels  */
18822547Skarels inet_subnetof(in)
18922547Skarels 	struct in_addr in;
19022547Skarels {
19122547Skarels 	register u_long i = ntohl(in.s_addr);
19222547Skarels 
193*25382Skarels 	if (IN_CLASSA(i))
194*25382Skarels 		return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
195*25382Skarels 	else if (IN_CLASSB(i))
19622547Skarels 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
197*25382Skarels 	else
198*25382Skarels 		return ((i & 0xffffffc0) >> 28);
19922547Skarels }
200