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