xref: /csrg-svn/sbin/routed/query/query.c (revision 22547)
16918Ssam #ifndef lint
2*22547Skarels static char sccsid[] = "@(#)query.c	4.7 06/06/85";
36918Ssam #endif
46918Ssam 
56918Ssam #include <sys/param.h>
66918Ssam #include <sys/protosw.h>
76918Ssam #include <sys/socket.h>
815760Skarels #include <sys/time.h>
915760Skarels #include <netinet/in.h>
106918Ssam #include <errno.h>
116918Ssam #include <stdio.h>
128339Ssam #include <netdb.h>
1315760Skarels #include "../protocol.h"
146918Ssam 
1515760Skarels #define	WTIME	5		/* Time to wait for responses */
1615760Skarels 
176918Ssam int	s;
18*22547Skarels int	timedout, timeout();
196918Ssam char	packet[MAXPACKETSIZE];
20*22547Skarels extern int errno;
216918Ssam 
226918Ssam main(argc, argv)
236918Ssam 	int argc;
246918Ssam 	char *argv[];
256918Ssam {
2615760Skarels 	int cc, count, bits;
276918Ssam 	struct sockaddr from;
2815760Skarels 	int fromlen = sizeof(from);
2915760Skarels 	struct timeval notime;
306918Ssam 
316918Ssam 	if (argc < 2) {
326918Ssam 		printf("usage: query hosts...\n");
336918Ssam 		exit(1);
346918Ssam 	}
3515760Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
366918Ssam 	if (s < 0) {
376918Ssam 		perror("socket");
386918Ssam 		exit(2);
396918Ssam 	}
4015760Skarels 
416918Ssam 	argv++, argc--;
426918Ssam 	count = argc;
436918Ssam 	while (argc > 0) {
446918Ssam 		query(*argv);
456918Ssam 		argv++, argc--;
466918Ssam 	}
476918Ssam 
486918Ssam 	/*
4915760Skarels 	 * Listen for returning packets;
5015760Skarels 	 * may be more than one packet per host.
516918Ssam 	 */
5215760Skarels 	bits = 1 << s;
5315760Skarels 	bzero(&notime, sizeof(notime));
54*22547Skarels 	signal(SIGALRM, timeout);
55*22547Skarels 	alarm(WTIME);
56*22547Skarels 	while ((count > 0 && !timedout) ||
57*22547Skarels 	    select(20, &bits, 0, 0, &notime) > 0) {
5815760Skarels 		cc = recvfrom(s, packet, sizeof (packet), 0,
5915760Skarels 		  &from, &fromlen);
606918Ssam 		if (cc <= 0) {
616918Ssam 			if (cc < 0) {
62*22547Skarels 				if (errno == EINTR)
63*22547Skarels 					continue;
6415760Skarels 				perror("recvfrom");
656918Ssam 				(void) close(s);
666918Ssam 				exit(1);
676918Ssam 			}
686918Ssam 			continue;
696918Ssam 		}
706918Ssam 		rip_input(&from, cc);
716918Ssam 		count--;
726918Ssam 	}
736918Ssam }
746918Ssam 
756918Ssam query(host)
766918Ssam 	char *host;
776918Ssam {
786918Ssam 	struct sockaddr_in router;
796918Ssam 	register struct rip *msg = (struct rip *)packet;
808339Ssam 	struct hostent *hp;
818339Ssam 	struct servent *sp;
826918Ssam 
836918Ssam 	bzero((char *)&router, sizeof (router));
848339Ssam 	hp = gethostbyname(host);
858339Ssam 	if (hp == 0) {
866918Ssam 		printf("%s: unknown\n", host);
876918Ssam 		exit(1);
886918Ssam 	}
898339Ssam 	bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
906918Ssam 	router.sin_family = AF_INET;
918339Ssam 	sp = getservbyname("router", "udp");
928339Ssam 	if (sp == 0) {
938339Ssam 		printf("udp/router: service unknown\n");
948339Ssam 		exit(1);
958339Ssam 	}
9615760Skarels 	router.sin_port = sp->s_port;
976918Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
9815760Skarels 	msg->rip_vers = RIPVERSION;
9915760Skarels 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
10015760Skarels 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
10115760Skarels 	if (sendto(s, packet, sizeof (struct rip), 0,
10215760Skarels 	  &router, sizeof(router)) < 0)
1036918Ssam 		perror(host);
1046918Ssam }
1056918Ssam 
1066918Ssam /*
1076918Ssam  * Handle an incoming routing packet.
1086918Ssam  */
1096918Ssam rip_input(from, size)
1106918Ssam 	struct sockaddr_in *from;
1116918Ssam 	int size;
1126918Ssam {
1136918Ssam 	register struct rip *msg = (struct rip *)packet;
1146918Ssam 	struct netinfo *n;
1156918Ssam 	char *name;
116*22547Skarels 	int lna, net, subnet;
1178339Ssam 	struct hostent *hp;
1188339Ssam 	struct netent *np;
1196918Ssam 
1206918Ssam 	if (msg->rip_cmd != RIPCMD_RESPONSE)
1216918Ssam 		return;
1228344Ssam 	hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), AF_INET);
1238339Ssam 	name = hp == 0 ? "???" : hp->h_name;
12415760Skarels 	printf("from %s(%s):\n", name, inet_ntoa(from->sin_addr));
1256918Ssam 	size -= sizeof (int);
1266918Ssam 	n = msg->rip_nets;
1276918Ssam 	while (size > 0) {
1286918Ssam 		register struct sockaddr_in *sin;
1296918Ssam 
1306918Ssam 		if (size < sizeof (struct netinfo))
1316918Ssam 			break;
13215760Skarels 		if (msg->rip_vers > 0) {
13315760Skarels 			n->rip_dst.sa_family =
13415760Skarels 				ntohs(n->rip_dst.sa_family);
13515760Skarels 			n->rip_metric = ntohl(n->rip_metric);
13615760Skarels 		}
1376918Ssam 		sin = (struct sockaddr_in *)&n->rip_dst;
138*22547Skarels 		net = inet_netof(sin->sin_addr);
139*22547Skarels 		subnet = inet_subnetof(sin->sin_addr);
140*22547Skarels 		lna = inet_lnaof(sin->sin_addr);
141*22547Skarels 		name = "???";
142*22547Skarels 		if (lna == INADDR_ANY) {
143*22547Skarels 			np = getnetbyaddr(net, AF_INET);
144*22547Skarels 			if (np)
145*22547Skarels 				name = np->n_name;
146*22547Skarels 			else if (net == 0)
147*22547Skarels 				name = "default";
148*22547Skarels 		} else if ((subnet != net) && ((lna & 0xff) == 0) &&
149*22547Skarels 		    (np = getnetbyaddr(subnet, AF_INET))) {
150*22547Skarels 			struct in_addr subnaddr, inet_makeaddr();
151*22547Skarels 
152*22547Skarels 			subnaddr = inet_makeaddr(subnet, INADDR_ANY);
153*22547Skarels 			if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0)
154*22547Skarels 				name = np->n_name;
155*22547Skarels 			else
156*22547Skarels 				goto host;
1578339Ssam 		} else {
158*22547Skarels host:
1598339Ssam 			hp = gethostbyaddr(&sin->sin_addr,
160*22547Skarels 			    sizeof (struct in_addr), AF_INET);
161*22547Skarels 			if (hp)
162*22547Skarels 				name = hp->h_name;
1638339Ssam 		}
16415760Skarels 		printf("\t%s(%s), metric %d\n", name,
16515760Skarels 			inet_ntoa(sin->sin_addr), n->rip_metric);
1666918Ssam 		size -= sizeof (struct netinfo), n++;
1676918Ssam 	}
1686918Ssam }
16915760Skarels 
17015760Skarels timeout()
17115760Skarels {
17215760Skarels 	timedout = 1;
17315760Skarels }
174*22547Skarels 
175*22547Skarels /*
176*22547Skarels  * Return the possible subnetwork number from an internet address.
177*22547Skarels  * If the address is of the form of a subnet address (most significant
178*22547Skarels  * bit of the host part is set), believe the subnet exists.
179*22547Skarels  * Otherwise, return the network number.
180*22547Skarels  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
181*22547Skarels  * INSIDE OF THE HOST PART.  We can only believe this if we have other
182*22547Skarels  * information (e.g., we can find a name for this number).
183*22547Skarels  */
184*22547Skarels inet_subnetof(in)
185*22547Skarels 	struct in_addr in;
186*22547Skarels {
187*22547Skarels 	register u_long i = ntohl(in.s_addr);
188*22547Skarels 
189*22547Skarels 	if (IN_CLASSA(i)) {
190*22547Skarels 		if (IN_SUBNETA(i))
191*22547Skarels 			return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT);
192*22547Skarels 		else
193*22547Skarels 			return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
194*22547Skarels 	} else if (IN_CLASSB(i)) {
195*22547Skarels 		if (IN_SUBNETB(i))
196*22547Skarels 			return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT);
197*22547Skarels 		else
198*22547Skarels 			return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
199*22547Skarels 	} else
200*22547Skarels 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
201*22547Skarels }
202