xref: /csrg-svn/sbin/routed/query/query.c (revision 22547)
1 #ifndef lint
2 static char sccsid[] = "@(#)query.c	4.7 06/06/85";
3 #endif
4 
5 #include <sys/param.h>
6 #include <sys/protosw.h>
7 #include <sys/socket.h>
8 #include <sys/time.h>
9 #include <netinet/in.h>
10 #include <errno.h>
11 #include <stdio.h>
12 #include <netdb.h>
13 #include "../protocol.h"
14 
15 #define	WTIME	5		/* Time to wait for responses */
16 
17 int	s;
18 int	timedout, timeout();
19 char	packet[MAXPACKETSIZE];
20 extern int errno;
21 
22 main(argc, argv)
23 	int argc;
24 	char *argv[];
25 {
26 	int cc, count, bits;
27 	struct sockaddr from;
28 	int fromlen = sizeof(from);
29 	struct timeval notime;
30 
31 	if (argc < 2) {
32 		printf("usage: query hosts...\n");
33 		exit(1);
34 	}
35 	s = socket(AF_INET, SOCK_DGRAM, 0);
36 	if (s < 0) {
37 		perror("socket");
38 		exit(2);
39 	}
40 
41 	argv++, argc--;
42 	count = argc;
43 	while (argc > 0) {
44 		query(*argv);
45 		argv++, argc--;
46 	}
47 
48 	/*
49 	 * Listen for returning packets;
50 	 * may be more than one packet per host.
51 	 */
52 	bits = 1 << s;
53 	bzero(&notime, sizeof(notime));
54 	signal(SIGALRM, timeout);
55 	alarm(WTIME);
56 	while ((count > 0 && !timedout) ||
57 	    select(20, &bits, 0, 0, &notime) > 0) {
58 		cc = recvfrom(s, packet, sizeof (packet), 0,
59 		  &from, &fromlen);
60 		if (cc <= 0) {
61 			if (cc < 0) {
62 				if (errno == EINTR)
63 					continue;
64 				perror("recvfrom");
65 				(void) close(s);
66 				exit(1);
67 			}
68 			continue;
69 		}
70 		rip_input(&from, cc);
71 		count--;
72 	}
73 }
74 
75 query(host)
76 	char *host;
77 {
78 	struct sockaddr_in router;
79 	register struct rip *msg = (struct rip *)packet;
80 	struct hostent *hp;
81 	struct servent *sp;
82 
83 	bzero((char *)&router, sizeof (router));
84 	hp = gethostbyname(host);
85 	if (hp == 0) {
86 		printf("%s: unknown\n", host);
87 		exit(1);
88 	}
89 	bcopy(hp->h_addr, &router.sin_addr, hp->h_length);
90 	router.sin_family = AF_INET;
91 	sp = getservbyname("router", "udp");
92 	if (sp == 0) {
93 		printf("udp/router: service unknown\n");
94 		exit(1);
95 	}
96 	router.sin_port = sp->s_port;
97 	msg->rip_cmd = RIPCMD_REQUEST;
98 	msg->rip_vers = RIPVERSION;
99 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
100 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
101 	if (sendto(s, packet, sizeof (struct rip), 0,
102 	  &router, sizeof(router)) < 0)
103 		perror(host);
104 }
105 
106 /*
107  * Handle an incoming routing packet.
108  */
109 rip_input(from, size)
110 	struct sockaddr_in *from;
111 	int size;
112 {
113 	register struct rip *msg = (struct rip *)packet;
114 	struct netinfo *n;
115 	char *name;
116 	int lna, net, subnet;
117 	struct hostent *hp;
118 	struct netent *np;
119 
120 	if (msg->rip_cmd != RIPCMD_RESPONSE)
121 		return;
122 	hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), AF_INET);
123 	name = hp == 0 ? "???" : hp->h_name;
124 	printf("from %s(%s):\n", name, inet_ntoa(from->sin_addr));
125 	size -= sizeof (int);
126 	n = msg->rip_nets;
127 	while (size > 0) {
128 		register struct sockaddr_in *sin;
129 
130 		if (size < sizeof (struct netinfo))
131 			break;
132 		if (msg->rip_vers > 0) {
133 			n->rip_dst.sa_family =
134 				ntohs(n->rip_dst.sa_family);
135 			n->rip_metric = ntohl(n->rip_metric);
136 		}
137 		sin = (struct sockaddr_in *)&n->rip_dst;
138 		net = inet_netof(sin->sin_addr);
139 		subnet = inet_subnetof(sin->sin_addr);
140 		lna = inet_lnaof(sin->sin_addr);
141 		name = "???";
142 		if (lna == INADDR_ANY) {
143 			np = getnetbyaddr(net, AF_INET);
144 			if (np)
145 				name = np->n_name;
146 			else if (net == 0)
147 				name = "default";
148 		} else if ((subnet != net) && ((lna & 0xff) == 0) &&
149 		    (np = getnetbyaddr(subnet, AF_INET))) {
150 			struct in_addr subnaddr, inet_makeaddr();
151 
152 			subnaddr = inet_makeaddr(subnet, INADDR_ANY);
153 			if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0)
154 				name = np->n_name;
155 			else
156 				goto host;
157 		} else {
158 host:
159 			hp = gethostbyaddr(&sin->sin_addr,
160 			    sizeof (struct in_addr), AF_INET);
161 			if (hp)
162 				name = hp->h_name;
163 		}
164 		printf("\t%s(%s), metric %d\n", name,
165 			inet_ntoa(sin->sin_addr), n->rip_metric);
166 		size -= sizeof (struct netinfo), n++;
167 	}
168 }
169 
170 timeout()
171 {
172 	timedout = 1;
173 }
174 
175 /*
176  * Return the possible subnetwork number from an internet address.
177  * If the address is of the form of a subnet address (most significant
178  * bit of the host part is set), believe the subnet exists.
179  * Otherwise, return the network number.
180  * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
181  * INSIDE OF THE HOST PART.  We can only believe this if we have other
182  * information (e.g., we can find a name for this number).
183  */
184 inet_subnetof(in)
185 	struct in_addr in;
186 {
187 	register u_long i = ntohl(in.s_addr);
188 
189 	if (IN_CLASSA(i)) {
190 		if (IN_SUBNETA(i))
191 			return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT);
192 		else
193 			return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
194 	} else if (IN_CLASSB(i)) {
195 		if (IN_SUBNETB(i))
196 			return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT);
197 		else
198 			return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
199 	} else
200 		return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
201 }
202