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