Commit | Line | Data |
---|---|---|
efe4f2b0 | 1 | /* |
5932a057 KB |
2 | * Copyright (c) 1983, 1986 The Regents of the University of California. |
3 | * All rights reserved. | |
ad09eb30 | 4 | * |
5932a057 KB |
5 | * This file includes significant work done at Cornell University by |
6 | * Bill Nesheim. That work included by permission. | |
7 | * | |
8 | * Redistribution and use in source and binary forms are permitted | |
9 | * provided that the above copyright notice and this paragraph are | |
10 | * duplicated in all such forms and that any documentation, | |
11 | * advertising materials, and other materials related to such | |
12 | * distribution and use acknowledge that the software was developed | |
13 | * by the University of California, Berkeley. The name of the | |
14 | * University may not be used to endorse or promote products derived | |
15 | * from this software without specific prior written permission. | |
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
17 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
18 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
efe4f2b0 KS |
19 | */ |
20 | ||
21 | #ifndef lint | |
791c4f9a | 22 | char copyright[] = |
5932a057 | 23 | "@(#) Copyright (c) 1983, 1986 The Regents of the University of California.\n\ |
791c4f9a | 24 | All rights reserved.\n"; |
5932a057 | 25 | #endif /* not lint */ |
791c4f9a KS |
26 | |
27 | #ifndef lint | |
d0808c1f | 28 | static char sccsid[] = "@(#)query.c 5.7 (Berkeley) %G%"; |
5932a057 | 29 | #endif /* not lint */ |
efe4f2b0 KS |
30 | |
31 | #include <sys/param.h> | |
32 | #include <sys/protosw.h> | |
33 | #include <sys/socket.h> | |
34 | #include <sys/time.h> | |
35 | #include <netinet/in.h> | |
36 | #include <netns/ns.h> | |
37 | #include <netns/idp.h> | |
38 | #include <errno.h> | |
39 | #include <stdio.h> | |
40 | #include <netdb.h> | |
41 | #include "../protocol.h" | |
42 | #define IDPPORT_RIF 1 | |
efe4f2b0 KS |
43 | |
44 | #define WTIME 5 /* Time to wait for responses */ | |
45 | ||
46 | int s; | |
47 | int timedout, timeout(); | |
48 | char packet[MAXPACKETSIZE]; | |
49 | extern int errno; | |
d0808c1f | 50 | struct sockaddr_ns myaddr = {sizeof(myaddr), AF_NS}; |
d0fa19d4 | 51 | char *ns_ntoa(); |
be68ff62 | 52 | struct ns_addr ns_addr(); |
efe4f2b0 KS |
53 | main(argc, argv) |
54 | int argc; | |
55 | char *argv[]; | |
56 | { | |
57 | int cc, count, bits; | |
58 | struct sockaddr from; | |
59 | int fromlen = sizeof(from); | |
60 | struct timeval notime; | |
61 | ||
62 | if (argc < 2) { | |
63 | printf("usage: query hosts...\n"); | |
64 | exit(1); | |
65 | } | |
66 | s = getsocket(SOCK_DGRAM, 0); | |
67 | if (s < 0) { | |
68 | perror("socket"); | |
69 | exit(2); | |
70 | } | |
71 | ||
72 | argv++, argc--; | |
791c4f9a | 73 | query(argv,argc); |
efe4f2b0 KS |
74 | |
75 | /* | |
76 | * Listen for returning packets; | |
77 | * may be more than one packet per host. | |
78 | */ | |
79 | bits = 1 << s; | |
80 | bzero(¬ime, sizeof(notime)); | |
81 | signal(SIGALRM, timeout); | |
82 | alarm(WTIME); | |
791c4f9a | 83 | while (!timedout || |
efe4f2b0 KS |
84 | select(20, &bits, 0, 0, ¬ime) > 0) { |
85 | struct nspacket { | |
86 | struct idp hdr; | |
87 | char data[512]; | |
88 | } response; | |
89 | cc = recvfrom(s, &response, sizeof (response), 0, | |
90 | &from, &fromlen); | |
91 | if (cc <= 0) { | |
92 | if (cc < 0) { | |
93 | if (errno == EINTR) | |
94 | continue; | |
95 | perror("recvfrom"); | |
96 | (void) close(s); | |
97 | exit(1); | |
98 | } | |
99 | continue; | |
100 | } | |
101 | rip_input(&from, response.data, cc); | |
102 | count--; | |
103 | } | |
104 | } | |
d0808c1f | 105 | static struct sockaddr_ns router = {sizeof(myaddr), AF_NS}; |
be68ff62 KS |
106 | static struct ns_addr zero_addr; |
107 | static short allones[] = {-1, -1, -1}; | |
efe4f2b0 | 108 | |
791c4f9a KS |
109 | query(argv,argc) |
110 | char **argv; | |
efe4f2b0 | 111 | { |
efe4f2b0 | 112 | register struct rip *msg = (struct rip *)packet; |
791c4f9a | 113 | char *host = *argv; |
d0808c1f | 114 | int flags = 0; |
be68ff62 | 115 | struct ns_addr specific; |
efe4f2b0 | 116 | |
d0808c1f KS |
117 | if (bcmp(*argv, "-r", 3) == 0) { |
118 | flags = MSG_DONTROUTE; argv++; argc--; | |
119 | } | |
120 | host = *argv; | |
be68ff62 | 121 | router.sns_addr = ns_addr(host); |
efe4f2b0 | 122 | router.sns_addr.x_port = htons(IDPPORT_RIF); |
be68ff62 KS |
123 | if (ns_hosteq(zero_addr, router.sns_addr)) { |
124 | router.sns_addr.x_host = *(union ns_host *) allones; | |
125 | } | |
efe4f2b0 | 126 | msg->rip_cmd = htons(RIPCMD_REQUEST); |
be68ff62 | 127 | msg->rip_nets[0].rip_dst = *(union ns_net *) allones; |
efe4f2b0 | 128 | msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); |
791c4f9a | 129 | if (argc > 0) { |
be68ff62 KS |
130 | specific = ns_addr(*argv); |
131 | msg->rip_nets[0].rip_dst = specific.x_net; | |
132 | specific.x_host = zero_addr.x_host; | |
133 | specific.x_port = zero_addr.x_port; | |
134 | printf("Net asked for was %s\n", ns_ntoa(specific)); | |
791c4f9a | 135 | } |
d0808c1f | 136 | if (sendto(s, packet, sizeof (struct rip), flags, |
efe4f2b0 KS |
137 | &router, sizeof(router)) < 0) |
138 | perror(host); | |
139 | } | |
140 | ||
141 | /* | |
142 | * Handle an incoming routing packet. | |
143 | */ | |
144 | rip_input(from, msg, size) | |
145 | struct sockaddr_ns *from; | |
146 | register struct rip *msg; | |
147 | int size; | |
148 | { | |
149 | struct netinfo *n; | |
150 | char *name; | |
151 | int lna, net, subnet; | |
152 | struct hostent *hp; | |
153 | struct netent *np; | |
be68ff62 | 154 | static struct ns_addr work; |
efe4f2b0 KS |
155 | |
156 | if (htons(msg->rip_cmd) != RIPCMD_RESPONSE) | |
157 | return; | |
be68ff62 | 158 | printf("from %s\n", ns_ntoa(from->sns_addr)); |
efe4f2b0 KS |
159 | size -= sizeof (struct idp); |
160 | size -= sizeof (short); | |
161 | n = msg->rip_nets; | |
162 | while (size > 0) { | |
be68ff62 | 163 | union ns_net_u net; |
efe4f2b0 KS |
164 | if (size < sizeof (struct netinfo)) |
165 | break; | |
be68ff62 KS |
166 | net.net_e = n->rip_dst; |
167 | printf("\t%d, metric %d\n", ntohl(net.long_e), | |
efe4f2b0 KS |
168 | ntohs(n->rip_metric)); |
169 | size -= sizeof (struct netinfo), n++; | |
170 | } | |
171 | } | |
172 | ||
173 | timeout() | |
174 | { | |
175 | timedout = 1; | |
176 | } | |
177 | getsocket(type, proto) | |
178 | int type, proto; | |
179 | { | |
180 | struct sockaddr_ns *sns = &myaddr; | |
181 | int domain = sns->sns_family; | |
182 | int retry, s, on = 1; | |
183 | ||
184 | retry = 1; | |
185 | while ((s = socket(domain, type, proto)) < 0 && retry) { | |
186 | perror("socket"); | |
187 | sleep(5 * retry); | |
188 | retry <<= 1; | |
189 | } | |
190 | if (retry == 0) | |
191 | return (-1); | |
192 | while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) { | |
193 | perror("bind"); | |
194 | sleep(5 * retry); | |
195 | retry <<= 1; | |
196 | } | |
197 | if (retry == 0) | |
198 | return (-1); | |
199 | if (domain==AF_NS) { | |
200 | struct idp idp; | |
201 | if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { | |
202 | perror("setsockopt SEE HEADERS"); | |
203 | exit(1); | |
204 | } | |
205 | idp.idp_pt = NSPROTO_RI; | |
206 | if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) { | |
207 | perror("setsockopt SET HEADERS"); | |
208 | exit(1); | |
209 | } | |
210 | } | |
211 | if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { | |
212 | perror("setsockopt SO_BROADCAST"); | |
213 | exit(1); | |
214 | } | |
215 | return (s); | |
216 | } |