]> git.saurik.com Git - apple/network_cmds.git/blob - routed.tproj/query/query.c
97b8b86184500b631a3b628707498a3ad1454b3d
[apple/network_cmds.git] / routed.tproj / query / query.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved
26 *
27 * Copyright (c) 1982, 1986, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * The NEXTSTEP Software License Agreement specifies the terms
31 * and conditions for redistribution.
32 *
33 */
34
35 #ifndef lint
36 static char copyright[] =
37 "@(#) Copyright (c) 1982, 1986, 1993\n\
38 The Regents of the University of California. All rights reserved.\n";
39 #endif /* not lint */
40
41 #ifndef lint
42 static char sccsid[] = "@(#)query.c 8.3 (Berkeley) 4/28/95";
43 #endif /* not lint */
44
45 #include <sys/param.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/time.h>
49 #include <signal.h>
50 #include <netinet/in.h>
51 #include <protocols/routed.h>
52 #include <arpa/inet.h>
53 #include <netdb.h>
54 #include <errno.h>
55 #include <unistd.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59
60 #define WTIME 5 /* Time to wait for all responses */
61 #define STIME 500000 /* usec to wait for another response */
62
63 int s;
64 int timedout;
65 void timeout();
66 char packet[MAXPACKETSIZE];
67 int nflag;
68
69 main(argc, argv)
70 int argc;
71 char *argv[];
72 {
73 extern char *optarg;
74 extern int optind;
75 int ch, cc, count, bits;
76 struct sockaddr from;
77 struct sigaction sigact;
78 int fromlen = sizeof(from), size = 32*1024;
79 struct timeval shorttime;
80
81 while ((ch = getopt(argc, argv, "n")) != EOF)
82 switch (ch) {
83 case 'n':
84 nflag++;
85 break;
86 case '?':
87 default:
88 goto usage;
89 }
90 argv += optind;
91
92 if (!*argv) {
93 usage: printf("usage: query [-n] hosts...\n");
94 exit(1);
95 }
96
97 s = socket(AF_INET, SOCK_DGRAM, 0);
98 if (s < 0) {
99 perror("socket");
100 exit(2);
101 }
102 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
103 perror("setsockopt SO_RCVBUF");
104
105 while (*argv) {
106 query(*argv++);
107 count++;
108 }
109
110 /*
111 * Listen for returning packets;
112 * may be more than one packet per host.
113 */
114 bits = 1 << s;
115 memset(&shorttime, 0, sizeof(shorttime));
116 shorttime.tv_usec = STIME;
117 memset(&sigact, 0, sizeof(sigact));
118 sigact.sa_handler = timeout;
119 /*sigact.sa_flags = 0; /* no restart */
120 if (sigaction(SIGALRM, &sigact, (struct sigaction *)NULL) == -1)
121 perror("sigaction");
122 alarm(WTIME);
123 while ((count > 0 && !timedout) ||
124 select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) {
125 cc = recvfrom(s, packet, sizeof (packet), 0,
126 &from, &fromlen);
127 if (cc <= 0) {
128 if (cc < 0) {
129 if (errno == EINTR)
130 continue;
131 perror("recvfrom");
132 (void) close(s);
133 exit(1);
134 }
135 continue;
136 }
137 rip_input(&from, cc);
138 count--;
139 }
140 exit (count > 0 ? count : 0);
141 }
142
143 query(host)
144 char *host;
145 {
146 struct sockaddr_in router;
147 register struct rip *msg = (struct rip *)packet;
148 struct hostent *hp;
149 struct servent *sp;
150
151 memset(&router, 0, sizeof (router));
152 router.sin_family = AF_INET;
153 router.sin_addr.s_addr = inet_addr(host);
154 if (router.sin_addr.s_addr == -1) {
155 hp = gethostbyname(host);
156 if (hp == NULL) {
157 fprintf(stderr, "query: %s: ", host);
158 herror((char *)NULL);
159 exit(1);
160 }
161 memmove(&router.sin_addr, hp->h_addr, hp->h_length);
162 }
163 sp = getservbyname("router", "udp");
164 if (sp == 0) {
165 printf("udp/router: service unknown\n");
166 exit(1);
167 }
168 router.sin_port = sp->s_port;
169 msg->rip_cmd = RIPCMD_REQUEST;
170 msg->rip_vers = RIPVERSION;
171 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
172 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
173 if (sendto(s, packet, sizeof (struct rip), 0,
174 (struct sockaddr *)&router, sizeof(router)) < 0)
175 perror(host);
176 }
177
178 /*
179 * Handle an incoming routing packet.
180 */
181 rip_input(from, size)
182 struct sockaddr_in *from;
183 int size;
184 {
185 register struct rip *msg = (struct rip *)packet;
186 register struct netinfo *n;
187 char *name;
188 int lna, net, subnet;
189 struct hostent *hp;
190 struct netent *np;
191
192 if (msg->rip_cmd != RIPCMD_RESPONSE)
193 return;
194 printf("%d bytes from ", size);
195 if (nflag)
196 printf("%s:\n", inet_ntoa(from->sin_addr));
197 else {
198 hp = gethostbyaddr((char *)&from->sin_addr,
199 sizeof (struct in_addr), AF_INET);
200 name = hp == 0 ? "???" : hp->h_name;
201 printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
202 }
203 size -= sizeof (int);
204 n = msg->rip_nets;
205 while (size > 0) {
206 if (size < sizeof (struct netinfo))
207 break;
208 if (msg->rip_vers > 0) {
209 n->rip_dst.sa_family =
210 ntohs(n->rip_dst.sa_family);
211 n->rip_metric = ntohl(n->rip_metric);
212 }
213 switch (n->rip_dst.sa_family) {
214
215 case AF_INET:
216 { register struct sockaddr_in *sin;
217
218 sin = (struct sockaddr_in *)&n->rip_dst;
219 net = inet_netof(sin->sin_addr);
220 subnet = inet_subnetof(sin->sin_addr);
221 lna = inet_lnaof(sin->sin_addr);
222 name = "???";
223 if (!nflag) {
224 if (sin->sin_addr.s_addr == 0)
225 name = "default";
226 else if (lna == INADDR_ANY) {
227 np = getnetbyaddr(net, AF_INET);
228 if (np)
229 name = np->n_name;
230 else if (net == 0)
231 name = "default";
232 } else if ((lna & 0xff) == 0 &&
233 (np = getnetbyaddr(subnet, AF_INET))) {
234 struct in_addr subnaddr, inet_makeaddr();
235
236 subnaddr = inet_makeaddr(subnet, INADDR_ANY);
237 if (memcmp(&sin->sin_addr, &subnaddr,
238 sizeof(subnaddr)) == 0)
239 name = np->n_name;
240 else
241 goto host;
242 } else {
243 host:
244 hp = gethostbyaddr((char *)&sin->sin_addr,
245 sizeof (struct in_addr), AF_INET);
246 if (hp)
247 name = hp->h_name;
248 }
249 printf("\t%-17s metric %2d name %s\n",
250 inet_ntoa(sin->sin_addr), n->rip_metric, name);
251 } else
252 printf("\t%-17s metric %2d\n",
253 inet_ntoa(sin->sin_addr), n->rip_metric);
254 break;
255 }
256
257 default:
258 { u_short *p = (u_short *)n->rip_dst.sa_data;
259
260 printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
261 p[0], p[1], p[2], p[3], p[4], p[5], p[6],
262 n->rip_dst.sa_family,
263 n->rip_metric);
264 break;
265 }
266
267 }
268 size -= sizeof (struct netinfo), n++;
269 }
270 }
271
272 void
273 timeout()
274 {
275 timedout = 1;
276 }
277
278 /*
279 * Return the possible subnetwork number from an internet address.
280 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
281 * INSIDE OF THE HOST PART. We can only believe this if we have other
282 * information (e.g., we can find a name for this number).
283 */
284 inet_subnetof(in)
285 struct in_addr in;
286 {
287 register u_long i = ntohl(in.s_addr);
288
289 if (IN_CLASSA(i))
290 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
291 else if (IN_CLASSB(i))
292 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
293 else
294 return ((i & 0xffffffc0) >> 28);
295 }