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