1 /* $Id: query.c,v 5.4 2001/12/27 15:28:18 bertg Exp $
2 *
3 * XPilot, a multiplayer gravity war game. Copyright (C) 1991-2001 by
4 *
5 * Bj�rn Stabell <bjoern@xpilot.org>
6 * Ken Ronny Schouten <ken@xpilot.org>
7 * Bert Gijsbers <bert@xpilot.org>
8 * Dick Balaska <dick@xpilot.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <time.h>
30 #include <sys/types.h>
31
32 #if !defined(_WINDOWS)
33 # include <unistd.h>
34 # include <sys/param.h>
35 # include <sys/socket.h>
36 # include <sys/ioctl.h>
37 # include <netinet/in.h>
38 # include <arpa/inet.h>
39 # include <netdb.h>
40 # if defined(SVR4) || defined(__svr4__)
41 # include <sys/sockio.h>
42 # endif
43 # ifndef __hpux
44 # include <sys/time.h>
45 # endif
46 # include <net/if.h>
47 #endif
48
49 #ifdef _WINDOWS
50 # include "NT/winClient.h"
51 # include "NT/winNet.h"
52 #endif
53
54 #include "version.h"
55 #include "config.h"
56 #include "error.h"
57 #include "socklib.h"
58 #include "protoclient.h"
59
60 char query_version[] = VERSION;
61
62
63 #if defined(_WINDOWS)
64 # ifndef QUERY_FUDGED
65 # define QUERY_FUDGED
66 # endif
67 #endif
68 #ifdef _IBMESA
69 # define _SOCKADDR_LEN
70 #endif
71
72 #ifndef MAX_INTERFACE
73 #define MAX_INTERFACE 16 /* Max. number of network interfaces. */
74 #endif
75 #ifdef DEBUGBROADCAST
76 #undef D
77 #define D(x) x
78 #endif
79
80 /*
81 * Query all hosts on a subnet one after another.
82 * This should be avoided as much as possible.
83 * It may cause network congestion and therefore fail,
84 * because UDP is unreliable.
85 * We only allow this horrible kludge for subnets with 8 or less
86 * bits in the host part of the subnet mask.
87 * Subnets with irregular subnet bits are properly handled (I hope).
88 */
Query_subnet(sock_t * sock,struct sockaddr_in * host_addr,struct sockaddr_in * mask_addr,char * msg,int msglen)89 static int Query_subnet(sock_t *sock,
90 struct sockaddr_in *host_addr,
91 struct sockaddr_in *mask_addr,
92 char *msg,
93 int msglen)
94 {
95 int i, nbits, max;
96 unsigned long bit, mask, dest, host, hostmask, hostbits[256];
97 struct sockaddr_in addr;
98
99 addr = *host_addr;
100 host = ntohl(host_addr->sin_addr.s_addr);
101 mask = ntohl(mask_addr->sin_addr.s_addr);
102 memset ((void *)hostbits, 0, sizeof hostbits);
103 nbits = 0;
104 hostmask = 0;
105
106 /*
107 * Only the lower 32 bits of an unsigned long are used.
108 */
109 for (bit = 1; (bit & 0xffffffff) != 0; bit <<= 1) {
110 if ((mask & bit) != 0) {
111 continue;
112 }
113 if (nbits >= 8) {
114 /* break; ? */
115 error("too many host bits in subnet mask");
116 return (-1);
117 }
118 hostmask |= bit;
119 for (i = (1 << nbits); i < 256; i++) {
120 if ((i & (1 << nbits)) != 0) {
121 hostbits[i] |= bit;
122 }
123 }
124 nbits++;
125 }
126 if (nbits < 2) {
127 error("malformed subnet mask");
128 return (-1);
129 }
130
131 /*
132 * The first and the last address are reserved for the subnet.
133 * So, for an 8 bit host part only 254 hosts are tried, not 256.
134 */
135 max = (1 << nbits) - 2;
136 for (i=1; i <= max; i++) {
137 dest = (host & ~hostmask) | hostbits[i];
138 addr.sin_addr.s_addr = htonl(dest);
139 sock_get_error(sock);
140 sendto(sock->fd, msg, msglen, 0,
141 (struct sockaddr *)&addr, sizeof(addr));
142 D( printf("sendto %s/%d\n",
143 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); );
144 /*
145 * Imagine a server responding to our query while we
146 * are still transmitting packets for non-existing servers
147 * and the server packet colliding with one of our packets.
148 */
149 micro_delay((unsigned)10000);
150 }
151
152 return 0;
153 }
154
155
Query_fudged(sock_t * sock,int port,char * msg,int msglen)156 static int Query_fudged(sock_t *sock, int port, char *msg, int msglen)
157 {
158 int i, count = 0;
159 unsigned char *p;
160 struct sockaddr_in addr, subnet;
161 struct hostent *h;
162 unsigned long addrmask, netmask;
163 char hostname[64];
164
165 gethostname(hostname, sizeof(hostname));
166 if ((h = gethostbyname(hostname)) == NULL) {
167 error("gethostbyname");
168 return -1;
169 }
170 if (h->h_addrtype != AF_INET || h->h_length != 4) {
171 errno = 0;
172 error("Dunno about addresses with address type %d and length %d\n",
173 h->h_addrtype, h->h_length);
174 return -1;
175 }
176 for (i = 0; h->h_addr_list[i]; i++) {
177 memset(&addr, 0, sizeof(addr));
178 addr.sin_family = AF_INET;
179 addr.sin_port = (unsigned short)htons((unsigned short)port);
180 p = (unsigned char *) h->h_addr_list[i];
181 addrmask = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
182 addr.sin_addr.s_addr = htonl(addrmask);
183 subnet = addr;
184 if (addrmask == 0x7F000001) {
185 sock_get_error(sock);
186 if (sendto(sock->fd, msg, msglen, 0,
187 (struct sockaddr *)&addr, sizeof(addr)) != -1) {
188 count++;
189 }
190 } else {
191 netmask = 0xFFFFFF00;
192 subnet.sin_addr.s_addr = htonl(netmask);
193 if (Query_subnet(sock, &addr, &subnet, msg, msglen) != -1) {
194 count++;
195 }
196 }
197 }
198 if (count == 0) {
199 errno = 0;
200 count = -1;
201 }
202 return count;
203 }
204
205
206 /*
207 * Send a datagram on all network interfaces of the local host. Return the
208 * number of packets succesfully transmitted.
209 * We only use the loopback interface if we didn't do a broadcast
210 * on one of the other interfaces in order to reduce the chance that
211 * we get multiple responses from the same server.
212 */
213
Query_all(sock_t * sock,int port,char * msg,int msglen)214 int Query_all(sock_t *sock, int port, char *msg, int msglen)
215 {
216 #ifdef QUERY_FUDGED
217 return Query_fudged(sock, port, msg, msglen);
218 #else
219
220 int fd, len, ifflags, count = 0;
221 /* int broadcasts = 0; */
222 int haslb = 0;
223 struct sockaddr_in addr, mask, loopback;
224 struct ifconf ifconf;
225 struct ifreq *ifreqp, ifreq, ifbuf[MAX_INTERFACE];
226
227 /*
228 * Broadcasting on a socket must be explicitly enabled.
229 */
230 if (sock_set_broadcast(sock, 1) == -1) {
231 error("set broadcast");
232 return (-1);
233 }
234
235 /*
236 * Create an unbound datagram socket. Only used for ioctls.
237 */
238 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
239 error("socket");
240 return (-1);
241 }
242
243 /*
244 * Get names and addresses of all local network interfaces.
245 */
246 ifconf.ifc_len = sizeof(ifbuf);
247 ifconf.ifc_buf = (caddr_t)ifbuf;
248 memset((void *)ifbuf, 0, sizeof(ifbuf));
249 if (ioctl(fd, SIOCGIFCONF, (char *)&ifconf) == -1) {
250 error("ioctl SIOCGIFCONF");
251 close(fd);
252 return Query_fudged(sock, port, msg, msglen);
253 }
254 for (len = 0; len + sizeof(struct ifreq) <= ifconf.ifc_len;) {
255 ifreqp = (struct ifreq *)&ifconf.ifc_buf[len];
256
257 D( printf("interface name %s\n", ifreqp->ifr_name); );
258 D( printf("\taddress family %d\n", ifreqp->ifr_addr.sa_family); );
259
260 len += sizeof(struct ifreq);
261 #if BSD >= 199006 || HAVE_SA_LEN || defined(_SOCKADDR_LEN) || defined(_AIX)
262 /*
263 * Recent TCP/IP implementations have a sa_len member in the socket
264 * address structure in order to support protocol families that have
265 * bigger addresses.
266 */
267 if (ifreqp->ifr_addr.sa_len > sizeof(ifreqp->ifr_addr)) {
268 len += ifreqp->ifr_addr.sa_len - sizeof(ifreqp->ifr_addr);
269 D( printf("\textra address length %d\n",
270 ifreqp->ifr_addr.sa_len - sizeof(ifreqp->ifr_addr)); );
271 }
272 #endif
273 if (ifreqp->ifr_addr.sa_family != AF_INET) {
274 /*
275 * Not supported.
276 */
277 continue;
278 }
279
280 addr = *(struct sockaddr_in *)&ifreqp->ifr_addr;
281 D( printf("\taddress %s\n", inet_ntoa(addr.sin_addr)); );
282
283 /*
284 * Get interface flags.
285 */
286 ifreq = *ifreqp;
287 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifreq) == -1) {
288 error("ioctl SIOCGIFFLAGS");
289 continue;
290 }
291 ifflags = ifreq.ifr_flags;
292
293 if ((ifflags & IFF_UP) == 0) {
294 D( printf("\tinterface is down\n"); );
295 continue;
296 }
297 D( printf("\tinterface %s running\n",
298 (ifflags & IFF_RUNNING) ? "is" : "not"); );
299
300 if ((ifflags & IFF_LOOPBACK) != 0) {
301 D( printf("\tloopback interface\n"); );
302 /*
303 * Only send on the loopback if we don't broadcast.
304 */
305 if (haslb == 0) {
306 loopback = *(struct sockaddr_in *)&ifreq.ifr_addr;
307 haslb = 1;
308 }
309 continue;
310 } else if ((ifflags & IFF_POINTOPOINT) != 0) {
311 D( printf("\tpoint-to-point interface\n"); );
312 ifreq = *ifreqp;
313 if (ioctl(fd, SIOCGIFDSTADDR, (char *)&ifreq) == -1) {
314 error("ioctl SIOCGIFDSTADDR");
315 continue;
316 }
317 addr = *(struct sockaddr_in *)&ifreq.ifr_addr;
318 D(printf("\tdestination address %s\n", inet_ntoa(addr.sin_addr)););
319 } else if ((ifflags & IFF_BROADCAST) != 0) {
320 D( printf("\tbroadcast interface\n"); );
321 ifreq = *ifreqp;
322 if (ioctl(fd, SIOCGIFBRDADDR, (char *)&ifreq) == -1) {
323 error("ioctl SIOCGIFBRDADDR");
324 continue;
325 }
326 addr = *(struct sockaddr_in *)&ifreq.ifr_addr;
327 D( printf("\tbroadcast address %s\n", inet_ntoa(addr.sin_addr)); );
328 } else {
329 /*
330 * Huh? It's not a loopback and not a point-to-point
331 * and it doesn't have a broadcast address???
332 * Something must be rotten here...
333 */
334 }
335
336 if ((ifflags & (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST)) != 0) {
337 /*
338 * Well, we have an address (at last).
339 */
340 addr.sin_port = htons(port);
341 if (sendto(sock->fd, msg, msglen, 0,
342 (struct sockaddr *)&addr, sizeof addr) == msglen) {
343 D(printf("\tsendto %s/%d\n", inet_ntoa(addr.sin_addr), port););
344 /*
345 * Success!
346 */
347 count++;
348 /* if ((ifflags & (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST))
349 == IFF_BROADCAST) {
350 broadcasts++;
351 } */
352 continue;
353 }
354
355 /*
356 * Failure.
357 */
358 error("sendto %s/%d failed", inet_ntoa(addr.sin_addr), port);
359
360 if ((ifflags & (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST))
361 != IFF_BROADCAST) {
362 /*
363 * It wasn't the broadcasting that failed.
364 */
365 continue;
366 }
367
368 /*
369 * Broadcasting failed.
370 * Try it in a different (kludgy) manner.
371 */
372 }
373
374 /*
375 * Get the netmask for this interface.
376 */
377 ifreq = *ifreqp;
378 if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifreq) == -1) {
379 error("ioctl SIOCGIFNETMASK");
380 continue;
381 }
382 mask = *(struct sockaddr_in *)&ifreq.ifr_addr;
383 D( printf("\tmask %s\n", inet_ntoa(mask.sin_addr)); );
384
385 addr.sin_port = htons(port);
386 if (Query_subnet(sock, &addr, &mask, msg, msglen) != -1) {
387 count++;
388 /* broadcasts++; */
389 }
390 }
391
392 /*
393 * Normally we wouldn't send a query over the loopback interface
394 * if we successfully have sent one or more broadcast queries,
395 * but it happens that some Linux machines which have firewalling
396 * packet filters installed don't copy outgoing broadcast packets
397 * to their local sockets. Therefore we now always also send
398 * one query to the loopback address just to be sure we reach
399 * our own server. That we now may receive two or more replies
400 * from the same server is not as serious as not receiving any
401 * reply would be.
402 */
403 if (haslb /* && broadcasts == 0 */) {
404 /*
405 * We may not have reached the localhost yet.
406 */
407 memset(&addr, 0, sizeof(addr));
408 addr.sin_addr = loopback.sin_addr;
409 addr.sin_port = htons(port);
410 if (sendto(sock->fd, msg, msglen, 0,
411 (struct sockaddr *)&addr, sizeof addr) == msglen) {
412 D(printf("\tsendto %s/%d\n", inet_ntoa(addr.sin_addr), port););
413 count++;
414 } else {
415 error("sendto %s/%d failed", inet_ntoa(addr.sin_addr), port);
416 }
417 }
418
419 close(fd);
420
421 if (count == 0) {
422 errno = 0;
423 count = -1;
424 }
425
426 return count;
427
428 #endif /* QUERY_FUDGED */
429 }
430
431