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