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