Commit | Line | Data |
---|---|---|
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 | 9 | char 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 | 15 | static 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 | 36 | int s; |
49dac2b7 KB |
37 | int timedout; |
38 | void timeout(); | |
9629a51d | 39 | char packet[MAXPACKETSIZE]; |
fdd611b4 | 40 | int nflag; |
9629a51d SL |
41 | |
42 | main(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) { | |
65 | usage: 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 | ||
111 | query(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 | */ | |
149 | rip_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 | 240 | void |
603811e3 MK |
241 | timeout() |
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 | */ | |
252 | inet_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 | } |