Commit | Line | Data |
---|---|---|
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 |
8 | static 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 | 23 | int s; |
5befa0ff | 24 | int timedout, timeout(); |
9629a51d | 25 | char packet[MAXPACKETSIZE]; |
5befa0ff | 26 | extern int errno; |
9629a51d SL |
27 | |
28 | main(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(¬ime, sizeof(notime)); | |
5befa0ff MK |
60 | signal(SIGALRM, timeout); |
61 | alarm(WTIME); | |
62 | while ((count > 0 && !timedout) || | |
63 | select(20, &bits, 0, 0, ¬ime) > 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 | ||
81 | query(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 | */ | |
115 | rip_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 | 164 | host: |
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 | |
176 | timeout() | |
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 | */ | |
190 | inet_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 | } |