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