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