xref: /original-bsd/sbin/XNSrouted/tools/query.c (revision 62cd422e)
1 /*
2  * Copyright (c) 1983, 1986 The Regents of the University of California.
3  * All rights reserved.
4  *
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.
19  */
20 
21 #ifndef lint
22 char copyright[] =
23 "@(#) Copyright (c) 1983, 1986 The Regents of the University of California.\n\
24  All rights reserved.\n";
25 #endif /* not lint */
26 
27 #ifndef lint
28 static char sccsid[] = "@(#)query.c	5.7 (Berkeley) 11/29/90";
29 #endif /* not lint */
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
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;
50 struct sockaddr_ns	myaddr = {sizeof(myaddr), AF_NS};
51 char *ns_ntoa();
52 struct ns_addr ns_addr();
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--;
73 	query(argv,argc);
74 
75 	/*
76 	 * Listen for returning packets;
77 	 * may be more than one packet per host.
78 	 */
79 	bits = 1 << s;
80 	bzero(&notime, sizeof(notime));
81 	signal(SIGALRM, timeout);
82 	alarm(WTIME);
83 	while (!timedout ||
84 	    select(20, &bits, 0, 0, &notime) > 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 }
105 static struct sockaddr_ns router = {sizeof(myaddr), AF_NS};
106 static struct ns_addr zero_addr;
107 static short allones[] = {-1, -1, -1};
108 
109 query(argv,argc)
110 char **argv;
111 {
112 	register struct rip *msg = (struct rip *)packet;
113 	char *host = *argv;
114 	int flags = 0;
115 	struct ns_addr specific;
116 
117 	if (bcmp(*argv, "-r", 3) == 0) {
118 		flags = MSG_DONTROUTE; argv++; argc--;
119 	}
120 	host = *argv;
121 	router.sns_addr = ns_addr(host);
122 	router.sns_addr.x_port = htons(IDPPORT_RIF);
123 	if (ns_hosteq(zero_addr, router.sns_addr)) {
124 		router.sns_addr.x_host = *(union ns_host *) allones;
125 	}
126 	msg->rip_cmd = htons(RIPCMD_REQUEST);
127 	msg->rip_nets[0].rip_dst = *(union ns_net *) allones;
128 	msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY);
129 	if (argc > 0) {
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));
135 	}
136 	if (sendto(s, packet, sizeof (struct rip), flags,
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;
154 	static struct ns_addr work;
155 
156 	if (htons(msg->rip_cmd) != RIPCMD_RESPONSE)
157 		return;
158 	printf("from %s\n", ns_ntoa(from->sns_addr));
159 	size -= sizeof (struct idp);
160 	size -= sizeof (short);
161 	n = msg->rip_nets;
162 	while (size > 0) {
163 		union ns_net_u net;
164 		if (size < sizeof (struct netinfo))
165 			break;
166 		net.net_e = n->rip_dst;
167 		printf("\t%d, metric %d\n", ntohl(net.long_e),
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 }
217