1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 
23 #include "../qcommon/q_shared.h"
24 #include "../qcommon/qcommon.h"
25 
26 #ifdef _WIN32
27 #	include <winsock2.h>
28 #	include <ws2tcpip.h>
29 #	if WINVER < 0x501
30 #		ifdef __MINGW32__
31 			// wspiapi.h isn't available on MinGW, so if it's
32 			// present it's because the end user has added it
33 			// and we should look for it in our tree
34 #			include "wspiapi.h"
35 #		else
36 #			include <wspiapi.h>
37 #		endif
38 #	else
39 #		include <ws2spi.h>
40 #	endif
41 
42 typedef int socklen_t;
43 #	ifdef ADDRESS_FAMILY
44 #		define sa_family_t	ADDRESS_FAMILY
45 #	else
46 typedef unsigned short sa_family_t;
47 #	endif
48 
49 #	define EAGAIN					WSAEWOULDBLOCK
50 #	define EADDRNOTAVAIL	WSAEADDRNOTAVAIL
51 #	define EAFNOSUPPORT		WSAEAFNOSUPPORT
52 #	define ECONNRESET			WSAECONNRESET
53 typedef u_long	ioctlarg_t;
54 #	define socketError		WSAGetLastError( )
55 
56 static WSADATA	winsockdata;
57 static qboolean	winsockInitialized = qfalse;
58 
59 #else
60 
61 #	if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
62 		// needed for socklen_t on OSX 10.2
63 #		define _BSD_SOCKLEN_T_
64 #	endif
65 
66 #	include <sys/socket.h>
67 #	include <errno.h>
68 #	include <netdb.h>
69 #	include <netinet/in.h>
70 #	include <arpa/inet.h>
71 #	include <net/if.h>
72 #	include <sys/ioctl.h>
73 #	include <sys/types.h>
74 #	include <sys/time.h>
75 #	include <unistd.h>
76 #	if !defined(__sun) && !defined(__sgi)
77 #		include <ifaddrs.h>
78 #	endif
79 
80 #	ifdef __sun
81 #		include <sys/filio.h>
82 #	endif
83 
84 typedef int SOCKET;
85 #	define INVALID_SOCKET		-1
86 #	define SOCKET_ERROR			-1
87 #	define closesocket			close
88 #	define ioctlsocket			ioctl
89 typedef int	ioctlarg_t;
90 #	define socketError			errno
91 
92 #endif
93 
94 static qboolean usingSocks = qfalse;
95 static int networkingEnabled = 0;
96 
97 static cvar_t	*net_enabled;
98 
99 static cvar_t	*net_socksEnabled;
100 static cvar_t	*net_socksServer;
101 static cvar_t	*net_socksPort;
102 static cvar_t	*net_socksUsername;
103 static cvar_t	*net_socksPassword;
104 
105 static cvar_t	*net_ip;
106 static cvar_t	*net_ip6;
107 static cvar_t	*net_port;
108 static cvar_t	*net_port6;
109 static cvar_t	*net_mcast6addr;
110 static cvar_t	*net_mcast6iface;
111 
112 static cvar_t	*net_dropsim;
113 
114 static struct sockaddr	socksRelayAddr;
115 
116 static SOCKET	ip_socket = INVALID_SOCKET;
117 static SOCKET	ip6_socket = INVALID_SOCKET;
118 static SOCKET	socks_socket = INVALID_SOCKET;
119 static SOCKET	multicast6_socket = INVALID_SOCKET;
120 
121 // Keep track of currently joined multicast group.
122 static struct ipv6_mreq curgroup;
123 // And the currently bound address.
124 static struct sockaddr_in6 boundto;
125 
126 #ifndef IF_NAMESIZE
127   #define IF_NAMESIZE 16
128 #endif
129 
130 // use an admin local address per default so that network admins can decide on how to handle quake3 traffic.
131 #define NET_MULTICAST_IP6 "ff04::696f:7175:616b:6533"
132 
133 #define	MAX_IPS		32
134 
135 typedef struct
136 {
137 	char ifname[IF_NAMESIZE];
138 
139 	netadrtype_t type;
140 	sa_family_t family;
141 	struct sockaddr_storage addr;
142 	struct sockaddr_storage netmask;
143 } nip_localaddr_t;
144 
145 static nip_localaddr_t localIP[MAX_IPS];
146 static int numIP;
147 
148 
149 //=============================================================================
150 
151 
152 /*
153 ====================
154 NET_ErrorString
155 ====================
156 */
NET_ErrorString(void)157 char *NET_ErrorString( void ) {
158 #ifdef _WIN32
159 	//FIXME: replace with FormatMessage?
160 	switch( socketError ) {
161 		case WSAEINTR: return "WSAEINTR";
162 		case WSAEBADF: return "WSAEBADF";
163 		case WSAEACCES: return "WSAEACCES";
164 		case WSAEDISCON: return "WSAEDISCON";
165 		case WSAEFAULT: return "WSAEFAULT";
166 		case WSAEINVAL: return "WSAEINVAL";
167 		case WSAEMFILE: return "WSAEMFILE";
168 		case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
169 		case WSAEINPROGRESS: return "WSAEINPROGRESS";
170 		case WSAEALREADY: return "WSAEALREADY";
171 		case WSAENOTSOCK: return "WSAENOTSOCK";
172 		case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
173 		case WSAEMSGSIZE: return "WSAEMSGSIZE";
174 		case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
175 		case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
176 		case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
177 		case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
178 		case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
179 		case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
180 		case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
181 		case WSAEADDRINUSE: return "WSAEADDRINUSE";
182 		case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
183 		case WSAENETDOWN: return "WSAENETDOWN";
184 		case WSAENETUNREACH: return "WSAENETUNREACH";
185 		case WSAENETRESET: return "WSAENETRESET";
186 		case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
187 		case WSAECONNRESET: return "WSAECONNRESET";
188 		case WSAENOBUFS: return "WSAENOBUFS";
189 		case WSAEISCONN: return "WSAEISCONN";
190 		case WSAENOTCONN: return "WSAENOTCONN";
191 		case WSAESHUTDOWN: return "WSAESHUTDOWN";
192 		case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
193 		case WSAETIMEDOUT: return "WSAETIMEDOUT";
194 		case WSAECONNREFUSED: return "WSAECONNREFUSED";
195 		case WSAELOOP: return "WSAELOOP";
196 		case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
197 		case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
198 		case WSASYSNOTREADY: return "WSASYSNOTREADY";
199 		case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
200 		case WSANOTINITIALISED: return "WSANOTINITIALISED";
201 		case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
202 		case WSATRY_AGAIN: return "WSATRY_AGAIN";
203 		case WSANO_RECOVERY: return "WSANO_RECOVERY";
204 		case WSANO_DATA: return "WSANO_DATA";
205 		default: return "NO ERROR";
206 	}
207 #else
208 	return strerror(socketError);
209 #endif
210 }
211 
NetadrToSockadr(netadr_t * a,struct sockaddr * s)212 static void NetadrToSockadr( netadr_t *a, struct sockaddr *s ) {
213 	if( a->type == NA_BROADCAST ) {
214 		((struct sockaddr_in *)s)->sin_family = AF_INET;
215 		((struct sockaddr_in *)s)->sin_port = a->port;
216 		((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
217 	}
218 	else if( a->type == NA_IP ) {
219 		((struct sockaddr_in *)s)->sin_family = AF_INET;
220 		((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
221 		((struct sockaddr_in *)s)->sin_port = a->port;
222 	}
223 	else if( a->type == NA_IP6 ) {
224 		((struct sockaddr_in6 *)s)->sin6_family = AF_INET6;
225 		((struct sockaddr_in6 *)s)->sin6_addr = * ((struct in6_addr *) &a->ip6);
226 		((struct sockaddr_in6 *)s)->sin6_port = a->port;
227 		((struct sockaddr_in6 *)s)->sin6_scope_id = a->scope_id;
228 	}
229 	else if(a->type == NA_MULTICAST6)
230 	{
231 		((struct sockaddr_in6 *)s)->sin6_family = AF_INET6;
232 		((struct sockaddr_in6 *)s)->sin6_addr = curgroup.ipv6mr_multiaddr;
233 		((struct sockaddr_in6 *)s)->sin6_port = a->port;
234 	}
235 }
236 
237 
SockadrToNetadr(struct sockaddr * s,netadr_t * a)238 static void SockadrToNetadr( struct sockaddr *s, netadr_t *a ) {
239 	if (s->sa_family == AF_INET) {
240 		a->type = NA_IP;
241 		*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
242 		a->port = ((struct sockaddr_in *)s)->sin_port;
243 	}
244 	else if(s->sa_family == AF_INET6)
245 	{
246 		a->type = NA_IP6;
247 		memcpy(a->ip6, &((struct sockaddr_in6 *)s)->sin6_addr, sizeof(a->ip6));
248 		a->port = ((struct sockaddr_in6 *)s)->sin6_port;
249 		a->scope_id = ((struct sockaddr_in6 *)s)->sin6_scope_id;
250 	}
251 }
252 
253 
SearchAddrInfo(struct addrinfo * hints,sa_family_t family)254 static struct addrinfo *SearchAddrInfo(struct addrinfo *hints, sa_family_t family)
255 {
256 	while(hints)
257 	{
258 		if(hints->ai_family == family)
259 			return hints;
260 
261 		hints = hints->ai_next;
262 	}
263 
264 	return NULL;
265 }
266 
267 /*
268 =============
269 Sys_StringToSockaddr
270 =============
271 */
Sys_StringToSockaddr(const char * s,struct sockaddr * sadr,int sadr_len,sa_family_t family)272 static qboolean Sys_StringToSockaddr(const char *s, struct sockaddr *sadr, int sadr_len, sa_family_t family)
273 {
274 	struct addrinfo hints;
275 	struct addrinfo *res = NULL;
276 	struct addrinfo *search = NULL;
277 	struct addrinfo *hintsp;
278 	int retval;
279 
280 	memset(sadr, '\0', sizeof(*sadr));
281 	memset(&hints, '\0', sizeof(hints));
282 
283 	hintsp = &hints;
284 	hintsp->ai_family = family;
285 	hintsp->ai_socktype = SOCK_DGRAM;
286 
287 	retval = getaddrinfo(s, NULL, hintsp, &res);
288 
289 	if(!retval)
290 	{
291 		if(family == AF_UNSPEC)
292 		{
293 			// Decide here and now which protocol family to use
294 			if(net_enabled->integer & NET_PRIOV6)
295 			{
296 				if(net_enabled->integer & NET_ENABLEV6)
297 					search = SearchAddrInfo(res, AF_INET6);
298 
299 				if(!search && (net_enabled->integer & NET_ENABLEV4))
300 					search = SearchAddrInfo(res, AF_INET);
301 			}
302 			else
303 			{
304 				if(net_enabled->integer & NET_ENABLEV4)
305 					search = SearchAddrInfo(res, AF_INET);
306 
307 				if(!search && (net_enabled->integer & NET_ENABLEV6))
308 					search = SearchAddrInfo(res, AF_INET6);
309 			}
310 		}
311 		else
312 			search = SearchAddrInfo(res, family);
313 
314 		if(search)
315 		{
316 			if(search->ai_addrlen > sadr_len)
317 				search->ai_addrlen = sadr_len;
318 
319 			memcpy(sadr, search->ai_addr, search->ai_addrlen);
320 			freeaddrinfo(res);
321 
322 			return qtrue;
323 		}
324 		else
325 			Com_Printf("Sys_StringToSockaddr: Error resolving %s: No address of required type found.\n", s);
326 	}
327 	else
328 		Com_Printf("Sys_StringToSockaddr: Error resolving %s: %s\n", s, gai_strerror(retval));
329 
330 	if(res)
331 		freeaddrinfo(res);
332 
333 	return qfalse;
334 }
335 
336 /*
337 =============
338 Sys_SockaddrToString
339 =============
340 */
Sys_SockaddrToString(char * dest,int destlen,struct sockaddr * input)341 static void Sys_SockaddrToString(char *dest, int destlen, struct sockaddr *input)
342 {
343 	socklen_t inputlen;
344 
345 	if (input->sa_family == AF_INET6)
346 		inputlen = sizeof(struct sockaddr_in6);
347 	else
348 		inputlen = sizeof(struct sockaddr_in);
349 
350 	if(getnameinfo(input, inputlen, dest, destlen, NULL, 0, NI_NUMERICHOST) && destlen > 0)
351 		*dest = '\0';
352 }
353 
354 /*
355 =============
356 Sys_StringToAdr
357 =============
358 */
Sys_StringToAdr(const char * s,netadr_t * a,netadrtype_t family)359 qboolean Sys_StringToAdr( const char *s, netadr_t *a, netadrtype_t family ) {
360 	struct sockaddr_storage sadr;
361 	sa_family_t fam;
362 
363 	switch(family)
364 	{
365 		case NA_IP:
366 			fam = AF_INET;
367 		break;
368 		case NA_IP6:
369 			fam = AF_INET6;
370 		break;
371 		default:
372 			fam = AF_UNSPEC;
373 		break;
374 	}
375 	if( !Sys_StringToSockaddr(s, (struct sockaddr *) &sadr, sizeof(sadr), fam ) ) {
376 		return qfalse;
377 	}
378 
379 	SockadrToNetadr( (struct sockaddr *) &sadr, a );
380 	return qtrue;
381 }
382 
383 /*
384 ===================
385 NET_CompareBaseAdrMask
386 
387 Compare without port, and up to the bit number given in netmask.
388 ===================
389 */
NET_CompareBaseAdrMask(netadr_t a,netadr_t b,int netmask)390 qboolean NET_CompareBaseAdrMask(netadr_t a, netadr_t b, int netmask)
391 {
392 	byte cmpmask, *addra, *addrb;
393 	int curbyte;
394 
395 	if (a.type != b.type)
396 		return qfalse;
397 
398 	if (a.type == NA_LOOPBACK)
399 		return qtrue;
400 
401 	if(a.type == NA_IP)
402 	{
403 		addra = (byte *) &a.ip;
404 		addrb = (byte *) &b.ip;
405 
406 		if(netmask < 0 || netmask > 32)
407 			netmask = 32;
408 	}
409 	else if(a.type == NA_IP6)
410 	{
411 		addra = (byte *) &a.ip6;
412 		addrb = (byte *) &b.ip6;
413 
414 		if(netmask < 0 || netmask > 128)
415 			netmask = 128;
416 	}
417 	else
418 	{
419 		Com_Printf ("NET_CompareBaseAdr: bad address type\n");
420 		return qfalse;
421 	}
422 
423 	curbyte = netmask >> 3;
424 
425 	if(curbyte && memcmp(addra, addrb, curbyte))
426 			return qfalse;
427 
428 	netmask &= 0x07;
429 	if(netmask)
430 	{
431 		cmpmask = (1 << netmask) - 1;
432 		cmpmask <<= 8 - netmask;
433 
434 		if((addra[curbyte] & cmpmask) == (addrb[curbyte] & cmpmask))
435 			return qtrue;
436 	}
437 	else
438 		return qtrue;
439 
440 	return qfalse;
441 }
442 
443 
444 /*
445 ===================
446 NET_CompareBaseAdr
447 
448 Compares without the port
449 ===================
450 */
NET_CompareBaseAdr(netadr_t a,netadr_t b)451 qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
452 {
453 	return NET_CompareBaseAdrMask(a, b, -1);
454 }
455 
NET_AdrToString(netadr_t a)456 const char	*NET_AdrToString (netadr_t a)
457 {
458 	static	char	s[NET_ADDRSTRMAXLEN];
459 
460 	if (a.type == NA_LOOPBACK)
461 		Com_sprintf (s, sizeof(s), "loopback");
462 	else if (a.type == NA_BOT)
463 		Com_sprintf (s, sizeof(s), "bot");
464 	else if (a.type == NA_IP || a.type == NA_IP6)
465 	{
466 		struct sockaddr_storage sadr;
467 
468 		memset(&sadr, 0, sizeof(sadr));
469 		NetadrToSockadr(&a, (struct sockaddr *) &sadr);
470 		Sys_SockaddrToString(s, sizeof(s), (struct sockaddr *) &sadr);
471 	}
472 
473 	return s;
474 }
475 
NET_AdrToStringwPort(netadr_t a)476 const char	*NET_AdrToStringwPort (netadr_t a)
477 {
478 	static	char	s[NET_ADDRSTRMAXLEN];
479 
480 	if (a.type == NA_LOOPBACK)
481 		Com_sprintf (s, sizeof(s), "loopback");
482 	else if (a.type == NA_BOT)
483 		Com_sprintf (s, sizeof(s), "bot");
484 	else if(a.type == NA_IP)
485 		Com_sprintf(s, sizeof(s), "%s:%hu", NET_AdrToString(a), ntohs(a.port));
486 	else if(a.type == NA_IP6)
487 		Com_sprintf(s, sizeof(s), "[%s]:%hu", NET_AdrToString(a), ntohs(a.port));
488 
489 	return s;
490 }
491 
492 
NET_CompareAdr(netadr_t a,netadr_t b)493 qboolean	NET_CompareAdr (netadr_t a, netadr_t b)
494 {
495 	if(!NET_CompareBaseAdr(a, b))
496 		return qfalse;
497 
498 	if (a.type == NA_IP || a.type == NA_IP6)
499 	{
500 		if (a.port == b.port)
501 			return qtrue;
502 	}
503 	else
504 		return qtrue;
505 
506 	return qfalse;
507 }
508 
509 
NET_IsLocalAddress(netadr_t adr)510 qboolean	NET_IsLocalAddress( netadr_t adr ) {
511 	return adr.type == NA_LOOPBACK;
512 }
513 
514 //=============================================================================
515 
516 /*
517 ==================
518 NET_GetPacket
519 
520 Receive one packet
521 ==================
522 */
NET_GetPacket(netadr_t * net_from,msg_t * net_message,fd_set * fdr)523 qboolean NET_GetPacket(netadr_t *net_from, msg_t *net_message, fd_set *fdr)
524 {
525 	int 	ret;
526 	struct sockaddr_storage from;
527 	socklen_t	fromlen;
528 	int		err;
529 
530 	if(ip_socket != INVALID_SOCKET && FD_ISSET(ip_socket, fdr))
531 	{
532 		fromlen = sizeof(from);
533 		ret = recvfrom( ip_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen );
534 
535 		if (ret == SOCKET_ERROR)
536 		{
537 			err = socketError;
538 
539 			if( err != EAGAIN && err != ECONNRESET )
540 				Com_Printf( "NET_GetPacket: %s\n", NET_ErrorString() );
541 		}
542 		else
543 		{
544 
545 			memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 );
546 
547 			if ( usingSocks && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) {
548 				if ( ret < 10 || net_message->data[0] != 0 || net_message->data[1] != 0 || net_message->data[2] != 0 || net_message->data[3] != 1 ) {
549 					return qfalse;
550 				}
551 				net_from->type = NA_IP;
552 				net_from->ip[0] = net_message->data[4];
553 				net_from->ip[1] = net_message->data[5];
554 				net_from->ip[2] = net_message->data[6];
555 				net_from->ip[3] = net_message->data[7];
556 				net_from->port = *(short *)&net_message->data[8];
557 				net_message->readcount = 10;
558 			}
559 			else {
560 				SockadrToNetadr( (struct sockaddr *) &from, net_from );
561 				net_message->readcount = 0;
562 			}
563 
564 			if( ret >= net_message->maxsize ) {
565 				Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
566 				return qfalse;
567 			}
568 
569 			net_message->cursize = ret;
570 			return qtrue;
571 		}
572 	}
573 
574 	if(ip6_socket != INVALID_SOCKET && FD_ISSET(ip6_socket, fdr))
575 	{
576 		fromlen = sizeof(from);
577 		ret = recvfrom(ip6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen);
578 
579 		if (ret == SOCKET_ERROR)
580 		{
581 			err = socketError;
582 
583 			if( err != EAGAIN && err != ECONNRESET )
584 				Com_Printf( "NET_GetPacket: %s\n", NET_ErrorString() );
585 		}
586 		else
587 		{
588 			SockadrToNetadr((struct sockaddr *) &from, net_from);
589 			net_message->readcount = 0;
590 
591 			if(ret >= net_message->maxsize)
592 			{
593 				Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
594 				return qfalse;
595 			}
596 
597 			net_message->cursize = ret;
598 			return qtrue;
599 		}
600 	}
601 
602 	if(multicast6_socket != INVALID_SOCKET && multicast6_socket != ip6_socket && FD_ISSET(multicast6_socket, fdr))
603 	{
604 		fromlen = sizeof(from);
605 		ret = recvfrom(multicast6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen);
606 
607 		if (ret == SOCKET_ERROR)
608 		{
609 			err = socketError;
610 
611 			if( err != EAGAIN && err != ECONNRESET )
612 				Com_Printf( "NET_GetPacket: %s\n", NET_ErrorString() );
613 		}
614 		else
615 		{
616 			SockadrToNetadr((struct sockaddr *) &from, net_from);
617 			net_message->readcount = 0;
618 
619 			if(ret >= net_message->maxsize)
620 			{
621 				Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
622 				return qfalse;
623 			}
624 
625 			net_message->cursize = ret;
626 			return qtrue;
627 		}
628 	}
629 
630 
631 	return qfalse;
632 }
633 
634 //=============================================================================
635 
636 static char socksBuf[4096];
637 
638 /*
639 ==================
640 Sys_SendPacket
641 ==================
642 */
Sys_SendPacket(int length,const void * data,netadr_t to)643 void Sys_SendPacket( int length, const void *data, netadr_t to ) {
644 	int				ret = SOCKET_ERROR;
645 	struct sockaddr_storage	addr;
646 
647 	if( to.type != NA_BROADCAST && to.type != NA_IP && to.type != NA_IP6 && to.type != NA_MULTICAST6)
648 	{
649 		Com_Error( ERR_FATAL, "Sys_SendPacket: bad address type" );
650 		return;
651 	}
652 
653 	if( (ip_socket == INVALID_SOCKET && to.type == NA_IP) ||
654 		(ip_socket == INVALID_SOCKET && to.type == NA_BROADCAST) ||
655 		(ip6_socket == INVALID_SOCKET && to.type == NA_IP6) ||
656 		(ip6_socket == INVALID_SOCKET && to.type == NA_MULTICAST6) )
657 		return;
658 
659 	if(to.type == NA_MULTICAST6 && (net_enabled->integer & NET_DISABLEMCAST))
660 		return;
661 
662 	memset(&addr, 0, sizeof(addr));
663 	NetadrToSockadr( &to, (struct sockaddr *) &addr );
664 
665 	if( usingSocks && to.type == NA_IP ) {
666 		socksBuf[0] = 0;	// reserved
667 		socksBuf[1] = 0;
668 		socksBuf[2] = 0;	// fragment (not fragmented)
669 		socksBuf[3] = 1;	// address type: IPV4
670 		*(int *)&socksBuf[4] = ((struct sockaddr_in *)&addr)->sin_addr.s_addr;
671 		*(short *)&socksBuf[8] = ((struct sockaddr_in *)&addr)->sin_port;
672 		memcpy( &socksBuf[10], data, length );
673 		ret = sendto( ip_socket, socksBuf, length+10, 0, &socksRelayAddr, sizeof(socksRelayAddr) );
674 	}
675 	else {
676 		if(addr.ss_family == AF_INET)
677 			ret = sendto( ip_socket, data, length, 0, (struct sockaddr *) &addr, sizeof(struct sockaddr_in) );
678 		else if(addr.ss_family == AF_INET6)
679 			ret = sendto( ip6_socket, data, length, 0, (struct sockaddr *) &addr, sizeof(struct sockaddr_in6) );
680 	}
681 	if( ret == SOCKET_ERROR ) {
682 		int err = socketError;
683 
684 		// wouldblock is silent
685 		if( err == EAGAIN ) {
686 			return;
687 		}
688 
689 		// some PPP links do not allow broadcasts and return an error
690 		if( ( err == EADDRNOTAVAIL ) && ( ( to.type == NA_BROADCAST ) ) ) {
691 			return;
692 		}
693 
694 		Com_Printf( "Sys_SendPacket: %s\n", NET_ErrorString() );
695 	}
696 }
697 
698 
699 //=============================================================================
700 
701 /*
702 ==================
703 Sys_IsLANAddress
704 
705 LAN clients will have their rate var ignored
706 ==================
707 */
Sys_IsLANAddress(netadr_t adr)708 qboolean Sys_IsLANAddress( netadr_t adr ) {
709 	int		index, run, addrsize;
710 	qboolean differed;
711 	byte *compareadr, *comparemask, *compareip;
712 
713 	if( adr.type == NA_LOOPBACK ) {
714 		return qtrue;
715 	}
716 
717 	if( adr.type == NA_IP )
718 	{
719 		// RFC1918:
720 		// 10.0.0.0        -   10.255.255.255  (10/8 prefix)
721 		// 172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
722 		// 192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
723 		if(adr.ip[0] == 10)
724 			return qtrue;
725 		if(adr.ip[0] == 172 && (adr.ip[1]&0xf0) == 16)
726 			return qtrue;
727 		if(adr.ip[0] == 192 && adr.ip[1] == 168)
728 			return qtrue;
729 
730 		if(adr.ip[0] == 127)
731 			return qtrue;
732 	}
733 	else if(adr.type == NA_IP6)
734 	{
735 		if(adr.ip6[0] == 0xfe && (adr.ip6[1] & 0xc0) == 0x80)
736 			return qtrue;
737 		if((adr.ip6[0] & 0xfe) == 0xfc)
738 			return qtrue;
739 	}
740 
741 	// Now compare against the networks this computer is member of.
742 	for(index = 0; index < numIP; index++)
743 	{
744 		if(localIP[index].type == adr.type)
745 		{
746 			if(adr.type == NA_IP)
747 			{
748 				compareip = (byte *) &((struct sockaddr_in *) &localIP[index].addr)->sin_addr.s_addr;
749 				comparemask = (byte *) &((struct sockaddr_in *) &localIP[index].netmask)->sin_addr.s_addr;
750 				compareadr = adr.ip;
751 
752 				addrsize = sizeof(adr.ip);
753 			}
754 			else
755 			{
756 				// TODO? should we check the scope_id here?
757 
758 				compareip = (byte *) &((struct sockaddr_in6 *) &localIP[index].addr)->sin6_addr;
759 				comparemask = (byte *) &((struct sockaddr_in6 *) &localIP[index].netmask)->sin6_addr;
760 				compareadr = adr.ip6;
761 
762 				addrsize = sizeof(adr.ip6);
763 			}
764 
765 			differed = qfalse;
766 			for(run = 0; run < addrsize; run++)
767 			{
768 				if((compareip[run] & comparemask[run]) != (compareadr[run] & comparemask[run]))
769 				{
770 					differed = qtrue;
771 					break;
772 				}
773 			}
774 
775 			if(!differed)
776 				return qtrue;
777 
778 		}
779 	}
780 
781 	return qfalse;
782 }
783 
784 /*
785 ==================
786 Sys_ShowIP
787 ==================
788 */
Sys_ShowIP(void)789 void Sys_ShowIP(void) {
790 	int i;
791 	char addrbuf[NET_ADDRSTRMAXLEN];
792 
793 	for(i = 0; i < numIP; i++)
794 	{
795 		Sys_SockaddrToString(addrbuf, sizeof(addrbuf), (struct sockaddr *) &localIP[i].addr);
796 
797 		if(localIP[i].type == NA_IP)
798 			Com_Printf( "IP: %s\n", addrbuf);
799 		else if(localIP[i].type == NA_IP6)
800 			Com_Printf( "IP6: %s\n", addrbuf);
801 	}
802 }
803 
804 
805 //=============================================================================
806 
807 
808 /*
809 ====================
810 NET_IPSocket
811 ====================
812 */
NET_IPSocket(char * net_interface,int port,int * err)813 SOCKET NET_IPSocket( char *net_interface, int port, int *err ) {
814 	SOCKET				newsocket;
815 	struct sockaddr_in	address;
816 	ioctlarg_t			_true = 1;
817 	int					i = 1;
818 
819 	*err = 0;
820 
821 	if( net_interface ) {
822 		Com_Printf( "Opening IP socket: %s:%i\n", net_interface, port );
823 	}
824 	else {
825 		Com_Printf( "Opening IP socket: 0.0.0.0:%i\n", port );
826 	}
827 
828 	if( ( newsocket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
829 		*err = socketError;
830 		Com_Printf( "WARNING: NET_IPSocket: socket: %s\n", NET_ErrorString() );
831 		return newsocket;
832 	}
833 	// make it non-blocking
834 	if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
835 		Com_Printf( "WARNING: NET_IPSocket: ioctl FIONBIO: %s\n", NET_ErrorString() );
836 		*err = socketError;
837 		closesocket(newsocket);
838 		return INVALID_SOCKET;
839 	}
840 
841 	// make it broadcast capable
842 	if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof(i) ) == SOCKET_ERROR ) {
843 		Com_Printf( "WARNING: NET_IPSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
844 	}
845 
846 	if( !net_interface || !net_interface[0]) {
847 		address.sin_family = AF_INET;
848 		address.sin_addr.s_addr = INADDR_ANY;
849 	}
850 	else
851 	{
852 		if(!Sys_StringToSockaddr( net_interface, (struct sockaddr *)&address, sizeof(address), AF_INET))
853 		{
854 			closesocket(newsocket);
855 			return INVALID_SOCKET;
856 		}
857 	}
858 
859 	if( port == PORT_ANY ) {
860 		address.sin_port = 0;
861 	}
862 	else {
863 		address.sin_port = htons( (short)port );
864 	}
865 
866 	if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) {
867 		Com_Printf( "WARNING: NET_IPSocket: bind: %s\n", NET_ErrorString() );
868 		*err = socketError;
869 		closesocket( newsocket );
870 		return INVALID_SOCKET;
871 	}
872 
873 	return newsocket;
874 }
875 
876 /*
877 ====================
878 NET_IP6Socket
879 ====================
880 */
NET_IP6Socket(char * net_interface,int port,struct sockaddr_in6 * bindto,int * err)881 SOCKET NET_IP6Socket( char *net_interface, int port, struct sockaddr_in6 *bindto, int *err ) {
882 	SOCKET				newsocket;
883 	struct sockaddr_in6	address;
884 	ioctlarg_t			_true = 1;
885 
886 	*err = 0;
887 
888 	if( net_interface )
889 	{
890 		// Print the name in brackets if there is a colon:
891 		if(Q_CountChar(net_interface, ':'))
892 			Com_Printf( "Opening IP6 socket: [%s]:%i\n", net_interface, port );
893 		else
894 			Com_Printf( "Opening IP6 socket: %s:%i\n", net_interface, port );
895 	}
896 	else
897 		Com_Printf( "Opening IP6 socket: [::]:%i\n", port );
898 
899 	if( ( newsocket = socket( PF_INET6, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
900 		*err = socketError;
901 		Com_Printf( "WARNING: NET_IP6Socket: socket: %s\n", NET_ErrorString() );
902 		return newsocket;
903 	}
904 
905 	// make it non-blocking
906 	if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
907 		Com_Printf( "WARNING: NET_IP6Socket: ioctl FIONBIO: %s\n", NET_ErrorString() );
908 		*err = socketError;
909 		closesocket(newsocket);
910 		return INVALID_SOCKET;
911 	}
912 
913 #ifdef IPV6_V6ONLY
914 	{
915 		int i = 1;
916 
917 		// ipv4 addresses should not be allowed to connect via this socket.
918 		if(setsockopt(newsocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &i, sizeof(i)) == SOCKET_ERROR)
919 		{
920 			// win32 systems don't seem to support this anyways.
921 			Com_DPrintf("WARNING: NET_IP6Socket: setsockopt IPV6_V6ONLY: %s\n", NET_ErrorString());
922 		}
923 	}
924 #endif
925 
926 	if( !net_interface || !net_interface[0]) {
927 		address.sin6_family = AF_INET6;
928 		address.sin6_addr = in6addr_any;
929 	}
930 	else
931 	{
932 		if(!Sys_StringToSockaddr( net_interface, (struct sockaddr *)&address, sizeof(address), AF_INET6))
933 		{
934 			closesocket(newsocket);
935 			return INVALID_SOCKET;
936 		}
937 	}
938 
939 	if( port == PORT_ANY ) {
940 		address.sin6_port = 0;
941 	}
942 	else {
943 		address.sin6_port = htons( (short)port );
944 	}
945 
946 	if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) {
947 		Com_Printf( "WARNING: NET_IP6Socket: bind: %s\n", NET_ErrorString() );
948 		*err = socketError;
949 		closesocket( newsocket );
950 		return INVALID_SOCKET;
951 	}
952 
953 	if(bindto)
954 		*bindto = address;
955 
956 	return newsocket;
957 }
958 
959 /*
960 ====================
961 NET_SetMulticast
962 Set the current multicast group
963 ====================
964 */
NET_SetMulticast6(void)965 void NET_SetMulticast6(void)
966 {
967 	struct sockaddr_in6 addr;
968 
969 	if(!*net_mcast6addr->string || !Sys_StringToSockaddr(net_mcast6addr->string, (struct sockaddr *) &addr, sizeof(addr), AF_INET6))
970 	{
971 		Com_Printf("WARNING: NET_JoinMulticast6: Incorrect multicast address given, "
972 			   "please set cvar %s to a sane value.\n", net_mcast6addr->name);
973 
974 		Cvar_SetValue(net_enabled->name, net_enabled->integer | NET_DISABLEMCAST);
975 
976 		return;
977 	}
978 
979 	memcpy(&curgroup.ipv6mr_multiaddr, &addr.sin6_addr, sizeof(curgroup.ipv6mr_multiaddr));
980 
981 	if(*net_mcast6iface->string)
982 	{
983 #ifdef _WIN32
984 		curgroup.ipv6mr_interface = net_mcast6iface->integer;
985 #else
986 		curgroup.ipv6mr_interface = if_nametoindex(net_mcast6iface->string);
987 #endif
988 	}
989 	else
990 		curgroup.ipv6mr_interface = 0;
991 }
992 
993 /*
994 ====================
995 NET_JoinMulticast
996 Join an ipv6 multicast group
997 ====================
998 */
NET_JoinMulticast6(void)999 void NET_JoinMulticast6(void)
1000 {
1001 	int err;
1002 
1003 	if(ip6_socket == INVALID_SOCKET || multicast6_socket != INVALID_SOCKET || (net_enabled->integer & NET_DISABLEMCAST))
1004 		return;
1005 
1006 	if(IN6_IS_ADDR_MULTICAST(&boundto.sin6_addr) || IN6_IS_ADDR_UNSPECIFIED(&boundto.sin6_addr))
1007 	{
1008 		// The way the socket was bound does not prohibit receiving multi-cast packets. So we don't need to open a new one.
1009 		multicast6_socket = ip6_socket;
1010 	}
1011 	else
1012 	{
1013 		if((multicast6_socket = NET_IP6Socket(net_mcast6addr->string, ntohs(boundto.sin6_port), NULL, &err)) == INVALID_SOCKET)
1014 		{
1015 			// If the OS does not support binding to multicast addresses, like WinXP, at least try with the normal file descriptor.
1016 			multicast6_socket = ip6_socket;
1017 		}
1018 	}
1019 
1020 	if(curgroup.ipv6mr_interface)
1021 	{
1022 		if (setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1023 					(char *) &curgroup.ipv6mr_interface, sizeof(curgroup.ipv6mr_interface)) < 0)
1024 		{
1025 			Com_Printf("NET_JoinMulticast6: Couldn't set scope on multicast socket: %s\n", NET_ErrorString());
1026 
1027 			if(multicast6_socket != ip6_socket)
1028 			{
1029 				closesocket(multicast6_socket);
1030 				multicast6_socket = INVALID_SOCKET;
1031 				return;
1032 			}
1033 		}
1034 	}
1035 
1036 	if (setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &curgroup, sizeof(curgroup)))
1037 	{
1038 		Com_Printf("NET_JoinMulticast6: Couldn't join multicast group: %s\n", NET_ErrorString());
1039 
1040 		if(multicast6_socket != ip6_socket)
1041 		{
1042 			closesocket(multicast6_socket);
1043 			multicast6_socket = INVALID_SOCKET;
1044 			return;
1045 		}
1046 	}
1047 }
1048 
NET_LeaveMulticast6()1049 void NET_LeaveMulticast6()
1050 {
1051 	if(multicast6_socket != INVALID_SOCKET)
1052 	{
1053 		if(multicast6_socket != ip6_socket)
1054 			closesocket(multicast6_socket);
1055 		else
1056 			setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *) &curgroup, sizeof(curgroup));
1057 
1058 		multicast6_socket = INVALID_SOCKET;
1059 	}
1060 }
1061 
1062 /*
1063 ====================
1064 NET_OpenSocks
1065 ====================
1066 */
NET_OpenSocks(int port)1067 void NET_OpenSocks( int port ) {
1068 	struct sockaddr_in	address;
1069 	struct hostent		*h;
1070 	int					len;
1071 	qboolean			rfc1929;
1072 	unsigned char		buf[64];
1073 
1074 	usingSocks = qfalse;
1075 
1076 	Com_Printf( "Opening connection to SOCKS server.\n" );
1077 
1078 	if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) {
1079 		Com_Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() );
1080 		return;
1081 	}
1082 
1083 	h = gethostbyname( net_socksServer->string );
1084 	if ( h == NULL ) {
1085 		Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() );
1086 		return;
1087 	}
1088 	if ( h->h_addrtype != AF_INET ) {
1089 		Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" );
1090 		return;
1091 	}
1092 	address.sin_family = AF_INET;
1093 	address.sin_addr.s_addr = *(int *)h->h_addr_list[0];
1094 	address.sin_port = htons( (short)net_socksPort->integer );
1095 
1096 	if ( connect( socks_socket, (struct sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) {
1097 		Com_Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() );
1098 		return;
1099 	}
1100 
1101 	// send socks authentication handshake
1102 	if ( *net_socksUsername->string || *net_socksPassword->string ) {
1103 		rfc1929 = qtrue;
1104 	}
1105 	else {
1106 		rfc1929 = qfalse;
1107 	}
1108 
1109 	buf[0] = 5;		// SOCKS version
1110 	// method count
1111 	if ( rfc1929 ) {
1112 		buf[1] = 2;
1113 		len = 4;
1114 	}
1115 	else {
1116 		buf[1] = 1;
1117 		len = 3;
1118 	}
1119 	buf[2] = 0;		// method #1 - method id #00: no authentication
1120 	if ( rfc1929 ) {
1121 		buf[2] = 2;		// method #2 - method id #02: username/password
1122 	}
1123 	if ( send( socks_socket, (void *)buf, len, 0 ) == SOCKET_ERROR ) {
1124 		Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
1125 		return;
1126 	}
1127 
1128 	// get the response
1129 	len = recv( socks_socket, (void *)buf, 64, 0 );
1130 	if ( len == SOCKET_ERROR ) {
1131 		Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
1132 		return;
1133 	}
1134 	if ( len != 2 || buf[0] != 5 ) {
1135 		Com_Printf( "NET_OpenSocks: bad response\n" );
1136 		return;
1137 	}
1138 	switch( buf[1] ) {
1139 	case 0:	// no authentication
1140 		break;
1141 	case 2: // username/password authentication
1142 		break;
1143 	default:
1144 		Com_Printf( "NET_OpenSocks: request denied\n" );
1145 		return;
1146 	}
1147 
1148 	// do username/password authentication if needed
1149 	if ( buf[1] == 2 ) {
1150 		int		ulen;
1151 		int		plen;
1152 
1153 		// build the request
1154 		ulen = strlen( net_socksUsername->string );
1155 		plen = strlen( net_socksPassword->string );
1156 
1157 		buf[0] = 1;		// username/password authentication version
1158 		buf[1] = ulen;
1159 		if ( ulen ) {
1160 			memcpy( &buf[2], net_socksUsername->string, ulen );
1161 		}
1162 		buf[2 + ulen] = plen;
1163 		if ( plen ) {
1164 			memcpy( &buf[3 + ulen], net_socksPassword->string, plen );
1165 		}
1166 
1167 		// send it
1168 		if ( send( socks_socket, (void *)buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) {
1169 			Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
1170 			return;
1171 		}
1172 
1173 		// get the response
1174 		len = recv( socks_socket, (void *)buf, 64, 0 );
1175 		if ( len == SOCKET_ERROR ) {
1176 			Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
1177 			return;
1178 		}
1179 		if ( len != 2 || buf[0] != 1 ) {
1180 			Com_Printf( "NET_OpenSocks: bad response\n" );
1181 			return;
1182 		}
1183 		if ( buf[1] != 0 ) {
1184 			Com_Printf( "NET_OpenSocks: authentication failed\n" );
1185 			return;
1186 		}
1187 	}
1188 
1189 	// send the UDP associate request
1190 	buf[0] = 5;		// SOCKS version
1191 	buf[1] = 3;		// command: UDP associate
1192 	buf[2] = 0;		// reserved
1193 	buf[3] = 1;		// address type: IPV4
1194 	*(int *)&buf[4] = INADDR_ANY;
1195 	*(short *)&buf[8] = htons( (short)port );		// port
1196 	if ( send( socks_socket, (void *)buf, 10, 0 ) == SOCKET_ERROR ) {
1197 		Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
1198 		return;
1199 	}
1200 
1201 	// get the response
1202 	len = recv( socks_socket, (void *)buf, 64, 0 );
1203 	if( len == SOCKET_ERROR ) {
1204 		Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
1205 		return;
1206 	}
1207 	if( len < 2 || buf[0] != 5 ) {
1208 		Com_Printf( "NET_OpenSocks: bad response\n" );
1209 		return;
1210 	}
1211 	// check completion code
1212 	if( buf[1] != 0 ) {
1213 		Com_Printf( "NET_OpenSocks: request denied: %i\n", buf[1] );
1214 		return;
1215 	}
1216 	if( buf[3] != 1 ) {
1217 		Com_Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
1218 		return;
1219 	}
1220 	((struct sockaddr_in *)&socksRelayAddr)->sin_family = AF_INET;
1221 	((struct sockaddr_in *)&socksRelayAddr)->sin_addr.s_addr = *(int *)&buf[4];
1222 	((struct sockaddr_in *)&socksRelayAddr)->sin_port = *(short *)&buf[8];
1223 	memset( ((struct sockaddr_in *)&socksRelayAddr)->sin_zero, 0, 8 );
1224 
1225 	usingSocks = qtrue;
1226 }
1227 
1228 
1229 /*
1230 =====================
1231 NET_AddLocalAddress
1232 =====================
1233 */
NET_AddLocalAddress(char * ifname,struct sockaddr * addr,struct sockaddr * netmask)1234 static void NET_AddLocalAddress(char *ifname, struct sockaddr *addr, struct sockaddr *netmask)
1235 {
1236 	int addrlen;
1237 	sa_family_t family;
1238 
1239 	// only add addresses that have all required info.
1240 	if(!addr || !netmask || !ifname)
1241 		return;
1242 
1243 	family = addr->sa_family;
1244 
1245 	if(numIP < MAX_IPS)
1246 	{
1247 		if(family == AF_INET)
1248 		{
1249 			addrlen = sizeof(struct sockaddr_in);
1250 			localIP[numIP].type = NA_IP;
1251 		}
1252 		else if(family == AF_INET6)
1253 		{
1254 			addrlen = sizeof(struct sockaddr_in6);
1255 			localIP[numIP].type = NA_IP6;
1256 		}
1257 		else
1258 			return;
1259 
1260 		Q_strncpyz(localIP[numIP].ifname, ifname, sizeof(localIP[numIP].ifname));
1261 
1262 		localIP[numIP].family = family;
1263 
1264 		memcpy(&localIP[numIP].addr, addr, addrlen);
1265 		memcpy(&localIP[numIP].netmask, netmask, addrlen);
1266 
1267 		numIP++;
1268 	}
1269 }
1270 
1271 #if defined(__linux__) || defined(MACOSX) || defined(__BSD__)
NET_GetLocalAddress(void)1272 static void NET_GetLocalAddress(void)
1273 {
1274 	struct ifaddrs *ifap, *search;
1275 
1276 	numIP = 0;
1277 
1278 	if(getifaddrs(&ifap))
1279 		Com_Printf("NET_GetLocalAddress: Unable to get list of network interfaces: %s\n", NET_ErrorString());
1280 	else
1281 	{
1282 		for(search = ifap; search; search = search->ifa_next)
1283 		{
1284 			// Only add interfaces that are up.
1285 			if(ifap->ifa_flags & IFF_UP)
1286 				NET_AddLocalAddress(search->ifa_name, search->ifa_addr, search->ifa_netmask);
1287 		}
1288 
1289 		freeifaddrs(ifap);
1290 
1291 		Sys_ShowIP();
1292 	}
1293 }
1294 #else
NET_GetLocalAddress(void)1295 static void NET_GetLocalAddress( void ) {
1296 	char				hostname[256];
1297 	struct addrinfo	hint;
1298 	struct addrinfo	*res = NULL;
1299 
1300 	numIP = 0;
1301 
1302 	if(gethostname( hostname, 256 ) == SOCKET_ERROR)
1303 		return;
1304 
1305 	Com_Printf( "Hostname: %s\n", hostname );
1306 
1307 	memset(&hint, 0, sizeof(hint));
1308 
1309 	hint.ai_family = AF_UNSPEC;
1310 	hint.ai_socktype = SOCK_DGRAM;
1311 
1312 	if(!getaddrinfo(hostname, NULL, &hint, &res))
1313 	{
1314 		struct sockaddr_in mask4;
1315 		struct sockaddr_in6 mask6;
1316 		struct addrinfo *search;
1317 
1318 		/* On operating systems where it's more difficult to find out the configured interfaces, we'll just assume a
1319 		 * netmask with all bits set. */
1320 
1321 		memset(&mask4, 0, sizeof(mask4));
1322 		memset(&mask6, 0, sizeof(mask6));
1323 		mask4.sin_family = AF_INET;
1324 		memset(&mask4.sin_addr.s_addr, 0xFF, sizeof(mask4.sin_addr.s_addr));
1325 		mask6.sin6_family = AF_INET6;
1326 		memset(&mask6.sin6_addr, 0xFF, sizeof(mask6.sin6_addr));
1327 
1328 		// add all IPs from returned list.
1329 		for(search = res; search; search = search->ai_next)
1330 		{
1331 			if(search->ai_family == AF_INET)
1332 				NET_AddLocalAddress("", search->ai_addr, (struct sockaddr *) &mask4);
1333 			else if(search->ai_family == AF_INET6)
1334 				NET_AddLocalAddress("", search->ai_addr, (struct sockaddr *) &mask6);
1335 		}
1336 
1337 		Sys_ShowIP();
1338 	}
1339 
1340 	if(res)
1341 		freeaddrinfo(res);
1342 }
1343 #endif
1344 
1345 /*
1346 ====================
1347 NET_OpenIP
1348 ====================
1349 */
NET_OpenIP(void)1350 void NET_OpenIP( void ) {
1351 	int		i;
1352 	int		err;
1353 	int		port;
1354 	int		port6;
1355 
1356 	port = net_port->integer;
1357 	port6 = net_port6->integer;
1358 
1359 	NET_GetLocalAddress();
1360 
1361 	// automatically scan for a valid port, so multiple
1362 	// dedicated servers can be started without requiring
1363 	// a different net_port for each one
1364 
1365 	if(net_enabled->integer & NET_ENABLEV6)
1366 	{
1367 		for( i = 0 ; i < 10 ; i++ )
1368 		{
1369 			ip6_socket = NET_IP6Socket(net_ip6->string, port6 + i, &boundto, &err);
1370 			if (ip6_socket != INVALID_SOCKET)
1371 			{
1372 				Cvar_SetValue( "net_port6", port6 + i );
1373 				break;
1374 			}
1375 			else
1376 			{
1377 				if(err == EAFNOSUPPORT)
1378 					break;
1379 			}
1380 		}
1381 		if(ip6_socket == INVALID_SOCKET)
1382 			Com_Printf( "WARNING: Couldn't bind to a v6 ip address.\n");
1383 	}
1384 
1385 	if(net_enabled->integer & NET_ENABLEV4)
1386 	{
1387 		for( i = 0 ; i < 10 ; i++ ) {
1388 			ip_socket = NET_IPSocket( net_ip->string, port + i, &err );
1389 			if (ip_socket != INVALID_SOCKET) {
1390 				Cvar_SetValue( "net_port", port + i );
1391 
1392 				if (net_socksEnabled->integer)
1393 					NET_OpenSocks( port + i );
1394 
1395 				break;
1396 			}
1397 			else
1398 			{
1399 				if(err == EAFNOSUPPORT)
1400 					break;
1401 			}
1402 		}
1403 
1404 		if(ip_socket == INVALID_SOCKET)
1405 			Com_Printf( "WARNING: Couldn't bind to a v4 ip address.\n");
1406 	}
1407 }
1408 
1409 
1410 //===================================================================
1411 
1412 
1413 /*
1414 ====================
1415 NET_GetCvars
1416 ====================
1417 */
NET_GetCvars(void)1418 static qboolean NET_GetCvars( void ) {
1419 	int modified;
1420 
1421 #ifdef DEDICATED
1422 	// I want server owners to explicitly turn on ipv6 support.
1423 	net_enabled = Cvar_Get( "net_enabled", "1", CVAR_LATCH | CVAR_ARCHIVE );
1424 #else
1425 	/* End users have it enabled so they can connect to ipv6-only hosts, but ipv4 will be
1426 	 * used if available due to ping */
1427 	net_enabled = Cvar_Get( "net_enabled", "3", CVAR_LATCH | CVAR_ARCHIVE );
1428 #endif
1429 	modified = net_enabled->modified;
1430 	net_enabled->modified = qfalse;
1431 
1432 	net_ip = Cvar_Get( "net_ip", "0.0.0.0", CVAR_LATCH );
1433 	modified += net_ip->modified;
1434 	net_ip->modified = qfalse;
1435 
1436 	net_ip6 = Cvar_Get( "net_ip6", "::", CVAR_LATCH );
1437 	modified += net_ip6->modified;
1438 	net_ip6->modified = qfalse;
1439 
1440 	net_port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH );
1441 	modified += net_port->modified;
1442 	net_port->modified = qfalse;
1443 
1444 	net_port6 = Cvar_Get( "net_port6", va( "%i", PORT_SERVER ), CVAR_LATCH );
1445 	modified += net_port6->modified;
1446 	net_port6->modified = qfalse;
1447 
1448 	// Some cvars for configuring multicast options which facilitates scanning for servers on local subnets.
1449 	net_mcast6addr = Cvar_Get( "net_mcast6addr", NET_MULTICAST_IP6, CVAR_LATCH | CVAR_ARCHIVE );
1450 	modified += net_mcast6addr->modified;
1451 	net_mcast6addr->modified = qfalse;
1452 
1453 #ifdef _WIN32
1454 	net_mcast6iface = Cvar_Get( "net_mcast6iface", "0", CVAR_LATCH | CVAR_ARCHIVE );
1455 #else
1456 	net_mcast6iface = Cvar_Get( "net_mcast6iface", "", CVAR_LATCH | CVAR_ARCHIVE );
1457 #endif
1458 	modified += net_mcast6iface->modified;
1459 	net_mcast6iface->modified = qfalse;
1460 
1461 	net_socksEnabled = Cvar_Get( "net_socksEnabled", "0", CVAR_LATCH | CVAR_ARCHIVE );
1462 	modified += net_socksEnabled->modified;
1463 	net_socksEnabled->modified = qfalse;
1464 
1465 	net_socksServer = Cvar_Get( "net_socksServer", "", CVAR_LATCH | CVAR_ARCHIVE );
1466 	modified += net_socksServer->modified;
1467 	net_socksServer->modified = qfalse;
1468 
1469 	net_socksPort = Cvar_Get( "net_socksPort", "1080", CVAR_LATCH | CVAR_ARCHIVE );
1470 	modified += net_socksPort->modified;
1471 	net_socksPort->modified = qfalse;
1472 
1473 	net_socksUsername = Cvar_Get( "net_socksUsername", "", CVAR_LATCH | CVAR_ARCHIVE );
1474 	modified += net_socksUsername->modified;
1475 	net_socksUsername->modified = qfalse;
1476 
1477 	net_socksPassword = Cvar_Get( "net_socksPassword", "", CVAR_LATCH | CVAR_ARCHIVE );
1478 	modified += net_socksPassword->modified;
1479 	net_socksPassword->modified = qfalse;
1480 
1481 	net_dropsim = Cvar_Get("net_dropsim", "", CVAR_TEMP);
1482 
1483 	return modified ? qtrue : qfalse;
1484 }
1485 
1486 
1487 /*
1488 ====================
1489 NET_Config
1490 ====================
1491 */
NET_Config(qboolean enableNetworking)1492 void NET_Config( qboolean enableNetworking ) {
1493 	qboolean	modified;
1494 	qboolean	stop;
1495 	qboolean	start;
1496 
1497 	// get any latched changes to cvars
1498 	modified = NET_GetCvars();
1499 
1500 	if( !net_enabled->integer ) {
1501 		enableNetworking = 0;
1502 	}
1503 
1504 	// if enable state is the same and no cvars were modified, we have nothing to do
1505 	if( enableNetworking == networkingEnabled && !modified ) {
1506 		return;
1507 	}
1508 
1509 	if( enableNetworking == networkingEnabled ) {
1510 		if( enableNetworking ) {
1511 			stop = qtrue;
1512 			start = qtrue;
1513 		}
1514 		else {
1515 			stop = qfalse;
1516 			start = qfalse;
1517 		}
1518 	}
1519 	else {
1520 		if( enableNetworking ) {
1521 			stop = qfalse;
1522 			start = qtrue;
1523 		}
1524 		else {
1525 			stop = qtrue;
1526 			start = qfalse;
1527 		}
1528 		networkingEnabled = enableNetworking;
1529 	}
1530 
1531 	if( stop ) {
1532 		if ( ip_socket != INVALID_SOCKET ) {
1533 			closesocket( ip_socket );
1534 			ip_socket = INVALID_SOCKET;
1535 		}
1536 
1537 		if(multicast6_socket != INVALID_SOCKET)
1538 		{
1539 			if(multicast6_socket != ip6_socket)
1540 				closesocket(multicast6_socket);
1541 
1542 			multicast6_socket = INVALID_SOCKET;
1543 		}
1544 
1545 		if ( ip6_socket != INVALID_SOCKET ) {
1546 			closesocket( ip6_socket );
1547 			ip6_socket = INVALID_SOCKET;
1548 		}
1549 
1550 		if ( socks_socket != INVALID_SOCKET ) {
1551 			closesocket( socks_socket );
1552 			socks_socket = INVALID_SOCKET;
1553 		}
1554 
1555 	}
1556 
1557 	if( start )
1558 	{
1559 		if (net_enabled->integer)
1560 		{
1561 			NET_OpenIP();
1562 			NET_SetMulticast6();
1563 		}
1564 	}
1565 }
1566 
1567 
1568 /*
1569 ====================
1570 NET_Init
1571 ====================
1572 */
NET_Init(void)1573 void NET_Init( void ) {
1574 #ifdef _WIN32
1575 	int		r;
1576 
1577 	r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata );
1578 	if( r ) {
1579 		Com_Printf( "WARNING: Winsock initialization failed, returned %d\n", r );
1580 		return;
1581 	}
1582 
1583 	winsockInitialized = qtrue;
1584 	Com_Printf( "Winsock Initialized\n" );
1585 #endif
1586 
1587 	NET_Config( qtrue );
1588 
1589 	Cmd_AddCommand ("net_restart", NET_Restart_f);
1590 	Cmd_AddCommand ("net_stop", NET_Shutdown);
1591 }
1592 
1593 
1594 /*
1595 ====================
1596 NET_Shutdown
1597 ====================
1598 */
NET_Shutdown(void)1599 void NET_Shutdown( void ) {
1600 	if ( !networkingEnabled ) {
1601 		return;
1602 	}
1603 
1604 	NET_Config( qfalse );
1605 
1606 #ifdef _WIN32
1607 	WSACleanup();
1608 	winsockInitialized = qfalse;
1609 #endif
1610 }
1611 
1612 /*
1613 ====================
1614 NET_Event
1615 
1616 Called from NET_Sleep which uses select() to determine which sockets have seen action.
1617 ====================
1618 */
1619 
NET_Event(fd_set * fdr)1620 void NET_Event(fd_set *fdr)
1621 {
1622 	byte bufData[MAX_MSGLEN + 1];
1623 	netadr_t from = {0};
1624 	msg_t netmsg;
1625 
1626 	while(1)
1627 	{
1628 		MSG_Init(&netmsg, bufData, sizeof(bufData));
1629 
1630 		if(NET_GetPacket(&from, &netmsg, fdr))
1631 		{
1632 			if(net_dropsim->value > 0.0f && net_dropsim->value <= 100.0f)
1633 			{
1634 				// com_dropsim->value percent of incoming packets get dropped.
1635 				if(rand() < (int) (((double) RAND_MAX) / 100.0 * (double) net_dropsim->value))
1636 					continue;          // drop this packet
1637 			}
1638 
1639 			if(com_sv_running->integer)
1640 				Com_RunAndTimeServerPacket(&from, &netmsg);
1641 			else
1642 				CL_PacketEvent(from, &netmsg);
1643 		}
1644 		else
1645 			break;
1646 	}
1647 }
1648 
1649 /*
1650 ====================
1651 NET_Sleep
1652 
1653 Sleeps msec or until something happens on the network
1654 ====================
1655 */
NET_Sleep(int msec)1656 void NET_Sleep(int msec)
1657 {
1658 	struct timeval timeout;
1659 	fd_set fdr;
1660 	int retval;
1661 	SOCKET highestfd = INVALID_SOCKET;
1662 
1663 	if(msec < 0)
1664 		msec = 0;
1665 
1666 	FD_ZERO(&fdr);
1667 
1668 	if(ip_socket != INVALID_SOCKET)
1669 	{
1670 		FD_SET(ip_socket, &fdr);
1671 
1672 		highestfd = ip_socket;
1673 	}
1674 	if(ip6_socket != INVALID_SOCKET)
1675 	{
1676 		FD_SET(ip6_socket, &fdr);
1677 
1678 		if(highestfd == INVALID_SOCKET || ip6_socket > highestfd)
1679 			highestfd = ip6_socket;
1680 	}
1681 
1682 #ifdef _WIN32
1683 	if(highestfd == INVALID_SOCKET)
1684 	{
1685 		// windows ain't happy when select is called without valid FDs
1686 		SleepEx(msec, 0);
1687 		return;
1688 	}
1689 #endif
1690 
1691 	timeout.tv_sec = msec/1000;
1692 	timeout.tv_usec = (msec%1000)*1000;
1693 
1694 	retval = select(highestfd + 1, &fdr, NULL, NULL, &timeout);
1695 
1696 	if(retval == SOCKET_ERROR)
1697 		Com_Printf("Warning: select() syscall failed: %s\n", NET_ErrorString());
1698 	else if(retval > 0)
1699 		NET_Event(&fdr);
1700 }
1701 
1702 /*
1703 ====================
1704 NET_Restart_f
1705 ====================
1706 */
NET_Restart_f(void)1707 void NET_Restart_f(void)
1708 {
1709 	NET_Config(qtrue);
1710 }
1711