1 /*-
2 * Copyright (c) 1982, 1986 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1982, 1986 The Regents of the University of California.\n\
37 All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 static char sccsid[] = "@(#)query.c 5.13 (Berkeley) 4/16/91";
42 #endif /* not lint */
43
44 #include <sys/param.h>
45 #include <sys/protosw.h>
46 #include <sys/socket.h>
47 #include <sys/time.h>
48 #include <signal.h>
49 #include <netinet/in.h>
50 #include <protocols/routed.h>
51 #include <arpa/inet.h>
52 #include <netdb.h>
53 #include <errno.h>
54 #include <unistd.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58
59 #define WTIME 5 /* Time to wait for all responses */
60 #define STIME 500000 /* usec to wait for another response */
61
62 int s;
63 int timedout;
64 void timeout();
65 char packet[MAXPACKETSIZE];
66 int nflag;
67
main(argc,argv)68 main(argc, argv)
69 int argc;
70 char *argv[];
71 {
72 extern char *optarg;
73 extern int optind;
74 int ch, cc, count, bits;
75 struct sockaddr from;
76 int fromlen = sizeof(from), size = 32*1024;
77 struct timeval shorttime;
78
79 while ((ch = getopt(argc, argv, "n")) != EOF)
80 switch((char)ch) {
81 case 'n':
82 nflag++;
83 break;
84 case '?':
85 default:
86 goto usage;
87 }
88 argv += optind;
89
90 if (!*argv) {
91 usage: printf("usage: query [-n] hosts...\n");
92 exit(1);
93 }
94
95 s = socket(AF_INET, SOCK_DGRAM, 0);
96 if (s < 0) {
97 perror("socket");
98 exit(2);
99 }
100 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
101 perror("setsockopt SO_RCVBUF");
102
103 while (*argv) {
104 query(*argv++);
105 count++;
106 }
107
108 /*
109 * Listen for returning packets;
110 * may be more than one packet per host.
111 */
112 bits = 1 << s;
113 bzero(&shorttime, sizeof(shorttime));
114 shorttime.tv_usec = STIME;
115 signal(SIGALRM, timeout);
116 alarm(WTIME);
117 while ((count > 0 && !timedout) ||
118 select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) {
119 cc = recvfrom(s, packet, sizeof (packet), 0,
120 &from, &fromlen);
121 if (cc <= 0) {
122 if (cc < 0) {
123 if (errno == EINTR)
124 continue;
125 perror("recvfrom");
126 (void) close(s);
127 exit(1);
128 }
129 continue;
130 }
131 rip_input(&from, cc);
132 count--;
133 }
134 exit (count > 0 ? count : 0);
135 }
136
query(host)137 query(host)
138 char *host;
139 {
140 struct sockaddr_in router;
141 register struct rip *msg = (struct rip *)packet;
142 struct hostent *hp;
143 struct servent *sp;
144
145 bzero((char *)&router, sizeof (router));
146 router.sin_family = AF_INET;
147 router.sin_addr.s_addr = inet_addr(host);
148 if (router.sin_addr.s_addr == -1) {
149 hp = gethostbyname(host);
150 if (hp == NULL) {
151 fprintf(stderr, "query: %s: ", host);
152 herror((char *)NULL);
153 exit(1);
154 }
155 bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
156 }
157 sp = getservbyname("router", "udp");
158 if (sp == 0) {
159 printf("udp/router: service unknown\n");
160 exit(1);
161 }
162 router.sin_port = sp->s_port;
163 msg->rip_cmd = RIPCMD_REQUEST;
164 msg->rip_vers = RIPVERSION;
165 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
166 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
167 if (sendto(s, packet, sizeof (struct rip), 0,
168 (struct sockaddr *)&router, sizeof(router)) < 0)
169 perror(host);
170 }
171
172 /*
173 * Handle an incoming routing packet.
174 */
175 rip_input(from, size)
176 struct sockaddr_in *from;
177 int size;
178 {
179 register struct rip *msg = (struct rip *)packet;
180 register struct netinfo *n;
181 char *name;
182 int lna, net, subnet;
183 struct hostent *hp;
184 struct netent *np;
185
186 if (msg->rip_cmd != RIPCMD_RESPONSE)
187 return;
188 printf("%d bytes from ", size);
189 if (nflag)
190 printf("%s:\n", inet_ntoa(from->sin_addr));
191 else {
192 hp = gethostbyaddr((char *)&from->sin_addr,
193 sizeof (struct in_addr), AF_INET);
194 name = hp == 0 ? "???" : hp->h_name;
195 printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
196 }
197 size -= sizeof (int);
198 n = msg->rip_nets;
199 while (size > 0) {
200 if (size < sizeof (struct netinfo))
201 break;
202 if (msg->rip_vers > 0) {
203 n->rip_dst.sa_family =
204 ntohs(n->rip_dst.sa_family);
205 n->rip_metric = ntohl(n->rip_metric);
206 }
207 switch (n->rip_dst.sa_family) {
208
209 case AF_INET:
210 { register struct sockaddr_in *sin;
211
212 sin = (struct sockaddr_in *)&n->rip_dst;
213 net = inet_netof(sin->sin_addr);
214 subnet = inet_subnetof(sin->sin_addr);
215 lna = inet_lnaof(sin->sin_addr);
216 name = "???";
217 if (!nflag) {
218 if (sin->sin_addr.s_addr == 0)
219 name = "default";
220 else if (lna == INADDR_ANY) {
221 np = getnetbyaddr(net, AF_INET);
222 if (np)
223 name = np->n_name;
224 else if (net == 0)
225 name = "default";
226 } else if ((lna & 0xff) == 0 &&
227 (np = getnetbyaddr(subnet, AF_INET))) {
228 struct in_addr subnaddr, inet_makeaddr();
229
230 subnaddr = inet_makeaddr(subnet, INADDR_ANY);
231 if (bcmp(&sin->sin_addr, &subnaddr,
232 sizeof(subnaddr)) == 0)
233 name = np->n_name;
234 else
235 goto host;
236 } else {
237 host:
238 hp = gethostbyaddr((char *)&sin->sin_addr,
239 sizeof (struct in_addr), AF_INET);
240 if (hp)
241 name = hp->h_name;
242 }
243 printf("\t%-17s metric %2d name %s\n",
244 inet_ntoa(sin->sin_addr), n->rip_metric, name);
245 } else
246 printf("\t%-17s metric %2d\n",
247 inet_ntoa(sin->sin_addr), n->rip_metric);
248 break;
249 }
250
251 default:
252 { u_short *p = (u_short *)n->rip_dst.sa_data;
253
254 printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
255 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
256 n->rip_dst.sa_family,
257 n->rip_metric);
258 break;
259 }
260
261 }
262 size -= sizeof (struct netinfo), n++;
263 }
264 }
265
266 void
timeout()267 timeout()
268 {
269 timedout = 1;
270 }
271
272 /*
273 * Return the possible subnetwork number from an internet address.
274 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
275 * INSIDE OF THE HOST PART. We can only believe this if we have other
276 * information (e.g., we can find a name for this number).
277 */
278 inet_subnetof(in)
279 struct in_addr in;
280 {
281 register u_long i = ntohl(in.s_addr);
282
283 if (IN_CLASSA(i))
284 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
285 else if (IN_CLASSB(i))
286 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
287 else
288 return ((i & 0xffffffc0) >> 28);
289 }
290