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