xref: /csrg-svn/sbin/routed/query/query.c (revision 46785)
122643Sdist /*
222643Sdist  * Copyright (c) 1980 Regents of the University of California.
333488Sbostic  * All rights reserved.
433488Sbostic  *
533488Sbostic  * Redistribution and use in source and binary forms are permitted
634770Sbostic  * provided that the above copyright notice and this paragraph are
734770Sbostic  * duplicated in all such forms and that any documentation,
834770Sbostic  * advertising materials, and other materials related to such
934770Sbostic  * distribution and use acknowledge that the software was developed
1034770Sbostic  * by the University of California, Berkeley.  The name of the
1134770Sbostic  * University may not be used to endorse or promote products derived
1234770Sbostic  * from this software without specific prior written permission.
1334770Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434770Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534770Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622643Sdist  */
1722643Sdist 
186918Ssam #ifndef lint
1933488Sbostic char copyright[] =
2033488Sbostic "@(#) Copyright (c) 1980 Regents of the University of California.\n\
2133488Sbostic  All rights reserved.\n";
2233488Sbostic #endif /* not lint */
236918Ssam 
2433488Sbostic #ifndef lint
25*46785Sbostic static char sccsid[] = "@(#)query.c	5.12 (Berkeley) 02/28/91";
2633488Sbostic #endif /* not lint */
2733488Sbostic 
286918Ssam #include <sys/param.h>
296918Ssam #include <sys/protosw.h>
306918Ssam #include <sys/socket.h>
3115760Skarels #include <sys/time.h>
32*46785Sbostic #include <signal.h>
3315760Skarels #include <netinet/in.h>
34*46785Sbostic #include <protocols/routed.h>
35*46785Sbostic #include <arpa/inet.h>
36*46785Sbostic #include <netdb.h>
376918Ssam #include <errno.h>
38*46785Sbostic #include <unistd.h>
396918Ssam #include <stdio.h>
40*46785Sbostic #include <stdlib.h>
41*46785Sbostic #include <string.h>
426918Ssam 
4327344Skarels #define	WTIME	5		/* Time to wait for all responses */
4427344Skarels #define	STIME	500000		/* usec to wait for another response */
4515760Skarels 
466918Ssam int	s;
47*46785Sbostic int	timedout;
48*46785Sbostic void	timeout();
496918Ssam char	packet[MAXPACKETSIZE];
5026146Skarels int	nflag;
516918Ssam 
526918Ssam main(argc, argv)
536918Ssam 	int argc;
546918Ssam 	char *argv[];
556918Ssam {
5635780Sbostic 	extern char *optarg;
5735780Sbostic 	extern int optind;
5835780Sbostic 	int ch, cc, count, bits;
596918Ssam 	struct sockaddr from;
6034708Skarels 	int fromlen = sizeof(from), size = 32*1024;
6127344Skarels 	struct timeval shorttime;
6235780Sbostic 
6335780Sbostic 	while ((ch = getopt(argc, argv, "n")) != EOF)
6435780Sbostic 		switch((char)ch) {
6535780Sbostic 		case 'n':
6635780Sbostic 			nflag++;
6735780Sbostic 			break;
6835780Sbostic 		case '?':
6935780Sbostic 		default:
7035780Sbostic 			goto usage;
7135780Sbostic 		}
7235780Sbostic 	argv += optind;
7335780Sbostic 
7435780Sbostic 	if (!*argv) {
7535780Sbostic usage:		printf("usage: query [-n] hosts...\n");
766918Ssam 		exit(1);
776918Ssam 	}
7835780Sbostic 
7915760Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
806918Ssam 	if (s < 0) {
816918Ssam 		perror("socket");
826918Ssam 		exit(2);
836918Ssam 	}
8434708Skarels 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
8534708Skarels 		perror("setsockopt SO_RCVBUF");
8615760Skarels 
8735780Sbostic 	while (*argv) {
8835780Sbostic 		query(*argv++);
8928205Skarels 		count++;
906918Ssam 	}
916918Ssam 
926918Ssam 	/*
9315760Skarels 	 * Listen for returning packets;
9415760Skarels 	 * may be more than one packet per host.
956918Ssam 	 */
9615760Skarels 	bits = 1 << s;
9727344Skarels 	bzero(&shorttime, sizeof(shorttime));
9827344Skarels 	shorttime.tv_usec = STIME;
9922547Skarels 	signal(SIGALRM, timeout);
10022547Skarels 	alarm(WTIME);
10122547Skarels 	while ((count > 0 && !timedout) ||
102*46785Sbostic 	    select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) {
10315760Skarels 		cc = recvfrom(s, packet, sizeof (packet), 0,
10415760Skarels 		  &from, &fromlen);
1056918Ssam 		if (cc <= 0) {
1066918Ssam 			if (cc < 0) {
10722547Skarels 				if (errno == EINTR)
10822547Skarels 					continue;
10915760Skarels 				perror("recvfrom");
1106918Ssam 				(void) close(s);
1116918Ssam 				exit(1);
1126918Ssam 			}
1136918Ssam 			continue;
1146918Ssam 		}
1156918Ssam 		rip_input(&from, cc);
1166918Ssam 		count--;
1176918Ssam 	}
11834708Skarels 	exit (count > 0 ? count : 0);
1196918Ssam }
1206918Ssam 
1216918Ssam query(host)
1226918Ssam 	char *host;
1236918Ssam {
1246918Ssam 	struct sockaddr_in router;
1256918Ssam 	register struct rip *msg = (struct rip *)packet;
1268339Ssam 	struct hostent *hp;
1278339Ssam 	struct servent *sp;
1286918Ssam 
1296918Ssam 	bzero((char *)&router, sizeof (router));
13026146Skarels 	router.sin_family = AF_INET;
13126146Skarels 	router.sin_addr.s_addr = inet_addr(host);
13226146Skarels 	if (router.sin_addr.s_addr == -1) {
13326146Skarels 		hp = gethostbyname(host);
13435780Sbostic 		if (hp == NULL) {
13535780Sbostic 			fprintf(stderr, "query: %s: ", host);
13635780Sbostic 			herror((char *)NULL);
13726146Skarels 			exit(1);
13826146Skarels 		}
13926146Skarels 		bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
1406918Ssam 	}
1418339Ssam 	sp = getservbyname("router", "udp");
1428339Ssam 	if (sp == 0) {
1438339Ssam 		printf("udp/router: service unknown\n");
1448339Ssam 		exit(1);
1458339Ssam 	}
14615760Skarels 	router.sin_port = sp->s_port;
1476918Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
14815760Skarels 	msg->rip_vers = RIPVERSION;
14915760Skarels 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
15015760Skarels 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
15115760Skarels 	if (sendto(s, packet, sizeof (struct rip), 0,
152*46785Sbostic 	  (struct sockaddr *)&router, sizeof(router)) < 0)
1536918Ssam 		perror(host);
1546918Ssam }
1556918Ssam 
1566918Ssam /*
1576918Ssam  * Handle an incoming routing packet.
1586918Ssam  */
1596918Ssam rip_input(from, size)
1606918Ssam 	struct sockaddr_in *from;
1616918Ssam 	int size;
1626918Ssam {
1636918Ssam 	register struct rip *msg = (struct rip *)packet;
16428205Skarels 	register struct netinfo *n;
1656918Ssam 	char *name;
16622547Skarels 	int lna, net, subnet;
1678339Ssam 	struct hostent *hp;
1688339Ssam 	struct netent *np;
1696918Ssam 
1706918Ssam 	if (msg->rip_cmd != RIPCMD_RESPONSE)
1716918Ssam 		return;
17226959Skarels 	printf("%d bytes from ", size);
17326146Skarels 	if (nflag)
17426146Skarels 		printf("%s:\n", inet_ntoa(from->sin_addr));
17526146Skarels 	else {
176*46785Sbostic 		hp = gethostbyaddr((char *)&from->sin_addr,
177*46785Sbostic 		    sizeof (struct in_addr), AF_INET);
17826146Skarels 		name = hp == 0 ? "???" : hp->h_name;
17926146Skarels 		printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
18026146Skarels 	}
1816918Ssam 	size -= sizeof (int);
1826918Ssam 	n = msg->rip_nets;
1836918Ssam 	while (size > 0) {
18428205Skarels 	    if (size < sizeof (struct netinfo))
18528205Skarels 		    break;
18628205Skarels 	    if (msg->rip_vers > 0) {
18728205Skarels 		    n->rip_dst.sa_family =
18828205Skarels 			    ntohs(n->rip_dst.sa_family);
18928205Skarels 		    n->rip_metric = ntohl(n->rip_metric);
19028205Skarels 	    }
19128205Skarels 	    switch (n->rip_dst.sa_family) {
1926918Ssam 
19328205Skarels 	    case AF_INET:
19428205Skarels 		{ register struct sockaddr_in *sin;
19528205Skarels 
1966918Ssam 		sin = (struct sockaddr_in *)&n->rip_dst;
19722547Skarels 		net = inet_netof(sin->sin_addr);
19822547Skarels 		subnet = inet_subnetof(sin->sin_addr);
19922547Skarels 		lna = inet_lnaof(sin->sin_addr);
20022547Skarels 		name = "???";
20126146Skarels 		if (!nflag) {
20228205Skarels 			if (sin->sin_addr.s_addr == 0)
20328205Skarels 				name = "default";
20428205Skarels 			else if (lna == INADDR_ANY) {
20526146Skarels 				np = getnetbyaddr(net, AF_INET);
20626146Skarels 				if (np)
20726146Skarels 					name = np->n_name;
20826146Skarels 				else if (net == 0)
20926146Skarels 					name = "default";
21026959Skarels 			} else if ((lna & 0xff) == 0 &&
21126146Skarels 			    (np = getnetbyaddr(subnet, AF_INET))) {
21226146Skarels 				struct in_addr subnaddr, inet_makeaddr();
21322547Skarels 
21426146Skarels 				subnaddr = inet_makeaddr(subnet, INADDR_ANY);
21526146Skarels 				if (bcmp(&sin->sin_addr, &subnaddr,
21626146Skarels 				    sizeof(subnaddr)) == 0)
21726146Skarels 					name = np->n_name;
21826146Skarels 				else
21926146Skarels 					goto host;
22026146Skarels 			} else {
22126146Skarels 	host:
222*46785Sbostic 				hp = gethostbyaddr((char *)&sin->sin_addr,
22326146Skarels 				    sizeof (struct in_addr), AF_INET);
22426146Skarels 				if (hp)
22526146Skarels 					name = hp->h_name;
22626146Skarels 			}
22734708Skarels 			printf("\t%-17s metric %2d name %s\n",
22834708Skarels 				inet_ntoa(sin->sin_addr), n->rip_metric, name);
22926146Skarels 		} else
23034708Skarels 			printf("\t%-17s metric %2d\n",
23126146Skarels 				inet_ntoa(sin->sin_addr), n->rip_metric);
23228205Skarels 		break;
23328205Skarels 		}
23428205Skarels 
23528205Skarels 	    default:
23628205Skarels 		{ u_short *p = (u_short *)n->rip_dst.sa_data;
23728205Skarels 
23828205Skarels 		printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
23928205Skarels 		    p[0], p[1], p[2], p[3], p[4], p[5], p[6],
24028205Skarels 		    n->rip_dst.sa_family,
24128205Skarels 		    n->rip_metric);
24228205Skarels 		break;
24328205Skarels 		}
24428205Skarels 
24528205Skarels 	    }
24628205Skarels 	    size -= sizeof (struct netinfo), n++;
2476918Ssam 	}
2486918Ssam }
24915760Skarels 
250*46785Sbostic void
25115760Skarels timeout()
25215760Skarels {
25315760Skarels 	timedout = 1;
25415760Skarels }
25522547Skarels 
25622547Skarels /*
25722547Skarels  * Return the possible subnetwork number from an internet address.
25822547Skarels  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
25922547Skarels  * INSIDE OF THE HOST PART.  We can only believe this if we have other
26022547Skarels  * information (e.g., we can find a name for this number).
26122547Skarels  */
26222547Skarels inet_subnetof(in)
26322547Skarels 	struct in_addr in;
26422547Skarels {
26522547Skarels 	register u_long i = ntohl(in.s_addr);
26622547Skarels 
26725382Skarels 	if (IN_CLASSA(i))
26825382Skarels 		return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
26925382Skarels 	else if (IN_CLASSB(i))
27022547Skarels 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
27125382Skarels 	else
27225382Skarels 		return ((i & 0xffffffc0) >> 28);
27322547Skarels }
274