xref: /original-bsd/sbin/XNSrouted/tools/query.c (revision c3e32dec)
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();
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(&notime, sizeof(notime));
71 	signal(SIGALRM, timeout);
72 	alarm(WTIME);
73 	while (!timedout ||
74 	    select(20, &bits, 0, 0, &notime) > 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 
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 
163 timeout()
164 {
165 	timedout = 1;
166 }
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