xref: /csrg-svn/sbin/routed/query/query.c (revision 28205)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)query.c	5.7 (Berkeley) 05/15/86";
9 #endif not lint
10 
11 #include <sys/param.h>
12 #include <sys/protosw.h>
13 #include <sys/socket.h>
14 #include <sys/time.h>
15 #include <netinet/in.h>
16 #include <errno.h>
17 #include <stdio.h>
18 #include <netdb.h>
19 #include <protocols/routed.h>
20 
21 #define	WTIME	5		/* Time to wait for all responses */
22 #define	STIME	500000		/* usec to wait for another response */
23 
24 int	s;
25 int	timedout, timeout();
26 char	packet[MAXPACKETSIZE];
27 extern int errno;
28 int	nflag;
29 
30 main(argc, argv)
31 	int argc;
32 	char *argv[];
33 {
34 	int cc, count, bits;
35 	struct sockaddr from;
36 	int fromlen = sizeof(from);
37 	struct timeval shorttime;
38 
39 	if (argc < 2) {
40 usage:
41 		printf("usage: query [ -n ] hosts...\n");
42 		exit(1);
43 	}
44 	s = socket(AF_INET, SOCK_DGRAM, 0);
45 	if (s < 0) {
46 		perror("socket");
47 		exit(2);
48 	}
49 
50 	argv++, argc--;
51 	if (*argv[0] == '-') {
52 		switch (argv[0][1]) {
53 		case 'n':
54 			nflag++;
55 			break;
56 		default:
57 			goto usage;
58 		}
59 		argc--, argv++;
60 	}
61 	while (argc > 0) {
62 		query(*argv);
63 		count++;
64 		argv++, argc--;
65 	}
66 
67 	/*
68 	 * Listen for returning packets;
69 	 * may be more than one packet per host.
70 	 */
71 	bits = 1 << s;
72 	bzero(&shorttime, sizeof(shorttime));
73 	shorttime.tv_usec = STIME;
74 	signal(SIGALRM, timeout);
75 	alarm(WTIME);
76 	while ((count > 0 && !timedout) ||
77 	    select(20, &bits, 0, 0, &shorttime) > 0) {
78 		cc = recvfrom(s, packet, sizeof (packet), 0,
79 		  &from, &fromlen);
80 		if (cc <= 0) {
81 			if (cc < 0) {
82 				if (errno == EINTR)
83 					continue;
84 				perror("recvfrom");
85 				(void) close(s);
86 				exit(1);
87 			}
88 			continue;
89 		}
90 		rip_input(&from, cc);
91 		count--;
92 	}
93 }
94 
95 query(host)
96 	char *host;
97 {
98 	struct sockaddr_in router;
99 	register struct rip *msg = (struct rip *)packet;
100 	struct hostent *hp;
101 	struct servent *sp;
102 
103 	bzero((char *)&router, sizeof (router));
104 	router.sin_family = AF_INET;
105 	router.sin_addr.s_addr = inet_addr(host);
106 	if (router.sin_addr.s_addr == -1) {
107 		hp = gethostbyname(host);
108 		if (hp == 0) {
109 			printf("%s: unknown\n", host);
110 			exit(1);
111 		}
112 		bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
113 	}
114 	sp = getservbyname("router", "udp");
115 	if (sp == 0) {
116 		printf("udp/router: service unknown\n");
117 		exit(1);
118 	}
119 	router.sin_port = sp->s_port;
120 	msg->rip_cmd = RIPCMD_REQUEST;
121 	msg->rip_vers = RIPVERSION;
122 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
123 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
124 	if (sendto(s, packet, sizeof (struct rip), 0,
125 	  &router, sizeof(router)) < 0)
126 		perror(host);
127 }
128 
129 /*
130  * Handle an incoming routing packet.
131  */
132 rip_input(from, size)
133 	struct sockaddr_in *from;
134 	int size;
135 {
136 	register struct rip *msg = (struct rip *)packet;
137 	register struct netinfo *n;
138 	char *name;
139 	int lna, net, subnet;
140 	struct hostent *hp;
141 	struct netent *np;
142 
143 	if (msg->rip_cmd != RIPCMD_RESPONSE)
144 		return;
145 	printf("%d bytes from ", size);
146 	if (nflag)
147 		printf("%s:\n", inet_ntoa(from->sin_addr));
148 	else {
149 		hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr),
150 			AF_INET);
151 		name = hp == 0 ? "???" : hp->h_name;
152 		printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
153 	}
154 	size -= sizeof (int);
155 	n = msg->rip_nets;
156 	while (size > 0) {
157 	    if (size < sizeof (struct netinfo))
158 		    break;
159 	    if (msg->rip_vers > 0) {
160 		    n->rip_dst.sa_family =
161 			    ntohs(n->rip_dst.sa_family);
162 		    n->rip_metric = ntohl(n->rip_metric);
163 	    }
164 	    switch (n->rip_dst.sa_family) {
165 
166 	    case AF_INET:
167 		{ register struct sockaddr_in *sin;
168 
169 		sin = (struct sockaddr_in *)&n->rip_dst;
170 		net = inet_netof(sin->sin_addr);
171 		subnet = inet_subnetof(sin->sin_addr);
172 		lna = inet_lnaof(sin->sin_addr);
173 		name = "???";
174 		if (!nflag) {
175 			if (sin->sin_addr.s_addr == 0)
176 				name = "default";
177 			else if (lna == INADDR_ANY) {
178 				np = getnetbyaddr(net, AF_INET);
179 				if (np)
180 					name = np->n_name;
181 				else if (net == 0)
182 					name = "default";
183 			} else if ((lna & 0xff) == 0 &&
184 			    (np = getnetbyaddr(subnet, AF_INET))) {
185 				struct in_addr subnaddr, inet_makeaddr();
186 
187 				subnaddr = inet_makeaddr(subnet, INADDR_ANY);
188 				if (bcmp(&sin->sin_addr, &subnaddr,
189 				    sizeof(subnaddr)) == 0)
190 					name = np->n_name;
191 				else
192 					goto host;
193 			} else {
194 	host:
195 				hp = gethostbyaddr(&sin->sin_addr,
196 				    sizeof (struct in_addr), AF_INET);
197 				if (hp)
198 					name = hp->h_name;
199 			}
200 			printf("\t%s(%s), metric %d\n", name,
201 				inet_ntoa(sin->sin_addr), n->rip_metric);
202 		} else
203 			printf("\t%s, metric %d\n",
204 				inet_ntoa(sin->sin_addr), n->rip_metric);
205 		break;
206 		}
207 
208 	    default:
209 		{ u_short *p = (u_short *)n->rip_dst.sa_data;
210 
211 		printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
212 		    p[0], p[1], p[2], p[3], p[4], p[5], p[6],
213 		    n->rip_dst.sa_family,
214 		    n->rip_metric);
215 		break;
216 		}
217 
218 	    }
219 	    size -= sizeof (struct netinfo), n++;
220 	}
221 }
222 
223 timeout()
224 {
225 	timedout = 1;
226 }
227 
228 /*
229  * Return the possible subnetwork number from an internet address.
230  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
231  * INSIDE OF THE HOST PART.  We can only believe this if we have other
232  * information (e.g., we can find a name for this number).
233  */
234 inet_subnetof(in)
235 	struct in_addr in;
236 {
237 	register u_long i = ntohl(in.s_addr);
238 
239 	if (IN_CLASSA(i))
240 		return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
241 	else if (IN_CLASSB(i))
242 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
243 	else
244 		return ((i & 0xffffffc0) >> 28);
245 }
246