xref: /csrg-svn/sbin/routed/query/query.c (revision 22643)
1*22643Sdist /*
2*22643Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22643Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22643Sdist  * specifies the terms and conditions for redistribution.
5*22643Sdist  */
6*22643Sdist 
76918Ssam #ifndef lint
8*22643Sdist static char sccsid[] = "@(#)query.c	5.1 (Berkeley) 06/07/85";
9*22643Sdist #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>
1915760Skarels #include "../protocol.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;
13015760Skarels 	printf("from %s(%s):\n", name, inet_ntoa(from->sin_addr));
1316918Ssam 	size -= sizeof (int);
1326918Ssam 	n = msg->rip_nets;
1336918Ssam 	while (size > 0) {
1346918Ssam 		register struct sockaddr_in *sin;
1356918Ssam 
1366918Ssam 		if (size < sizeof (struct netinfo))
1376918Ssam 			break;
13815760Skarels 		if (msg->rip_vers > 0) {
13915760Skarels 			n->rip_dst.sa_family =
14015760Skarels 				ntohs(n->rip_dst.sa_family);
14115760Skarels 			n->rip_metric = ntohl(n->rip_metric);
14215760Skarels 		}
1436918Ssam 		sin = (struct sockaddr_in *)&n->rip_dst;
14422547Skarels 		net = inet_netof(sin->sin_addr);
14522547Skarels 		subnet = inet_subnetof(sin->sin_addr);
14622547Skarels 		lna = inet_lnaof(sin->sin_addr);
14722547Skarels 		name = "???";
14822547Skarels 		if (lna == INADDR_ANY) {
14922547Skarels 			np = getnetbyaddr(net, AF_INET);
15022547Skarels 			if (np)
15122547Skarels 				name = np->n_name;
15222547Skarels 			else if (net == 0)
15322547Skarels 				name = "default";
15422547Skarels 		} else if ((subnet != net) && ((lna & 0xff) == 0) &&
15522547Skarels 		    (np = getnetbyaddr(subnet, AF_INET))) {
15622547Skarels 			struct in_addr subnaddr, inet_makeaddr();
15722547Skarels 
15822547Skarels 			subnaddr = inet_makeaddr(subnet, INADDR_ANY);
15922547Skarels 			if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0)
16022547Skarels 				name = np->n_name;
16122547Skarels 			else
16222547Skarels 				goto host;
1638339Ssam 		} else {
16422547Skarels host:
1658339Ssam 			hp = gethostbyaddr(&sin->sin_addr,
16622547Skarels 			    sizeof (struct in_addr), AF_INET);
16722547Skarels 			if (hp)
16822547Skarels 				name = hp->h_name;
1698339Ssam 		}
17015760Skarels 		printf("\t%s(%s), metric %d\n", name,
17115760Skarels 			inet_ntoa(sin->sin_addr), n->rip_metric);
1726918Ssam 		size -= sizeof (struct netinfo), n++;
1736918Ssam 	}
1746918Ssam }
17515760Skarels 
17615760Skarels timeout()
17715760Skarels {
17815760Skarels 	timedout = 1;
17915760Skarels }
18022547Skarels 
18122547Skarels /*
18222547Skarels  * Return the possible subnetwork number from an internet address.
18322547Skarels  * If the address is of the form of a subnet address (most significant
18422547Skarels  * bit of the host part is set), believe the subnet exists.
18522547Skarels  * Otherwise, return the network number.
18622547Skarels  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
18722547Skarels  * INSIDE OF THE HOST PART.  We can only believe this if we have other
18822547Skarels  * information (e.g., we can find a name for this number).
18922547Skarels  */
19022547Skarels inet_subnetof(in)
19122547Skarels 	struct in_addr in;
19222547Skarels {
19322547Skarels 	register u_long i = ntohl(in.s_addr);
19422547Skarels 
19522547Skarels 	if (IN_CLASSA(i)) {
19622547Skarels 		if (IN_SUBNETA(i))
19722547Skarels 			return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT);
19822547Skarels 		else
19922547Skarels 			return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
20022547Skarels 	} else if (IN_CLASSB(i)) {
20122547Skarels 		if (IN_SUBNETB(i))
20222547Skarels 			return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT);
20322547Skarels 		else
20422547Skarels 			return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
20522547Skarels 	} else
20622547Skarels 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
20722547Skarels }
208