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