win_net.c (25227B)
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 Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 // net_wins.c 23 24 #include "../game/q_shared.h" 25 #include "../qcommon/qcommon.h" 26 #include "win_local.h" 27 28 static WSADATA winsockdata; 29 static qboolean winsockInitialized = qfalse; 30 static qboolean usingSocks = qfalse; 31 static qboolean networkingEnabled = qfalse; 32 33 static cvar_t *net_noudp; 34 static cvar_t *net_noipx; 35 36 static cvar_t *net_socksEnabled; 37 static cvar_t *net_socksServer; 38 static cvar_t *net_socksPort; 39 static cvar_t *net_socksUsername; 40 static cvar_t *net_socksPassword; 41 static struct sockaddr socksRelayAddr; 42 43 static SOCKET ip_socket; 44 static SOCKET socks_socket; 45 static SOCKET ipx_socket; 46 47 #define MAX_IPS 16 48 static int numIP; 49 static byte localIP[MAX_IPS][4]; 50 51 //============================================================================= 52 53 54 /* 55 ==================== 56 NET_ErrorString 57 ==================== 58 */ 59 char *NET_ErrorString( void ) { 60 int code; 61 62 code = WSAGetLastError(); 63 switch( code ) { 64 case WSAEINTR: return "WSAEINTR"; 65 case WSAEBADF: return "WSAEBADF"; 66 case WSAEACCES: return "WSAEACCES"; 67 case WSAEDISCON: return "WSAEDISCON"; 68 case WSAEFAULT: return "WSAEFAULT"; 69 case WSAEINVAL: return "WSAEINVAL"; 70 case WSAEMFILE: return "WSAEMFILE"; 71 case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK"; 72 case WSAEINPROGRESS: return "WSAEINPROGRESS"; 73 case WSAEALREADY: return "WSAEALREADY"; 74 case WSAENOTSOCK: return "WSAENOTSOCK"; 75 case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ"; 76 case WSAEMSGSIZE: return "WSAEMSGSIZE"; 77 case WSAEPROTOTYPE: return "WSAEPROTOTYPE"; 78 case WSAENOPROTOOPT: return "WSAENOPROTOOPT"; 79 case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT"; 80 case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT"; 81 case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP"; 82 case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT"; 83 case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT"; 84 case WSAEADDRINUSE: return "WSAEADDRINUSE"; 85 case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL"; 86 case WSAENETDOWN: return "WSAENETDOWN"; 87 case WSAENETUNREACH: return "WSAENETUNREACH"; 88 case WSAENETRESET: return "WSAENETRESET"; 89 case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR"; 90 case WSAECONNRESET: return "WSAECONNRESET"; 91 case WSAENOBUFS: return "WSAENOBUFS"; 92 case WSAEISCONN: return "WSAEISCONN"; 93 case WSAENOTCONN: return "WSAENOTCONN"; 94 case WSAESHUTDOWN: return "WSAESHUTDOWN"; 95 case WSAETOOMANYREFS: return "WSAETOOMANYREFS"; 96 case WSAETIMEDOUT: return "WSAETIMEDOUT"; 97 case WSAECONNREFUSED: return "WSAECONNREFUSED"; 98 case WSAELOOP: return "WSAELOOP"; 99 case WSAENAMETOOLONG: return "WSAENAMETOOLONG"; 100 case WSAEHOSTDOWN: return "WSAEHOSTDOWN"; 101 case WSASYSNOTREADY: return "WSASYSNOTREADY"; 102 case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED"; 103 case WSANOTINITIALISED: return "WSANOTINITIALISED"; 104 case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND"; 105 case WSATRY_AGAIN: return "WSATRY_AGAIN"; 106 case WSANO_RECOVERY: return "WSANO_RECOVERY"; 107 case WSANO_DATA: return "WSANO_DATA"; 108 default: return "NO ERROR"; 109 } 110 } 111 112 void NetadrToSockadr( netadr_t *a, struct sockaddr *s ) { 113 memset( s, 0, sizeof(*s) ); 114 115 if( a->type == NA_BROADCAST ) { 116 ((struct sockaddr_in *)s)->sin_family = AF_INET; 117 ((struct sockaddr_in *)s)->sin_port = a->port; 118 ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; 119 } 120 else if( a->type == NA_IP ) { 121 ((struct sockaddr_in *)s)->sin_family = AF_INET; 122 ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip; 123 ((struct sockaddr_in *)s)->sin_port = a->port; 124 } 125 else if( a->type == NA_IPX ) { 126 ((struct sockaddr_ipx *)s)->sa_family = AF_IPX; 127 memcpy( ((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4 ); 128 memcpy( ((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6 ); 129 ((struct sockaddr_ipx *)s)->sa_socket = a->port; 130 } 131 else if( a->type == NA_BROADCAST_IPX ) { 132 ((struct sockaddr_ipx *)s)->sa_family = AF_IPX; 133 memset( ((struct sockaddr_ipx *)s)->sa_netnum, 0, 4 ); 134 memset( ((struct sockaddr_ipx *)s)->sa_nodenum, 0xff, 6 ); 135 ((struct sockaddr_ipx *)s)->sa_socket = a->port; 136 } 137 } 138 139 140 void SockadrToNetadr( struct sockaddr *s, netadr_t *a ) { 141 if (s->sa_family == AF_INET) { 142 a->type = NA_IP; 143 *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; 144 a->port = ((struct sockaddr_in *)s)->sin_port; 145 } 146 else if( s->sa_family == AF_IPX ) { 147 a->type = NA_IPX; 148 memcpy( &a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4 ); 149 memcpy( &a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6 ); 150 a->port = ((struct sockaddr_ipx *)s)->sa_socket; 151 } 152 } 153 154 155 /* 156 ============= 157 Sys_StringToAdr 158 159 idnewt 160 192.246.40.70 161 12121212.121212121212 162 ============= 163 */ 164 #define DO(src,dest) \ 165 copy[0] = s[src]; \ 166 copy[1] = s[src + 1]; \ 167 sscanf (copy, "%x", &val); \ 168 ((struct sockaddr_ipx *)sadr)->dest = val 169 170 qboolean Sys_StringToSockaddr( const char *s, struct sockaddr *sadr ) { 171 struct hostent *h; 172 int val; 173 char copy[MAX_STRING_CHARS]; 174 175 memset( sadr, 0, sizeof( *sadr ) ); 176 177 // check for an IPX address 178 if( ( strlen( s ) == 21 ) && ( s[8] == '.' ) ) { 179 ((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX; 180 ((struct sockaddr_ipx *)sadr)->sa_socket = 0; 181 copy[2] = 0; 182 DO(0, sa_netnum[0]); 183 DO(2, sa_netnum[1]); 184 DO(4, sa_netnum[2]); 185 DO(6, sa_netnum[3]); 186 DO(9, sa_nodenum[0]); 187 DO(11, sa_nodenum[1]); 188 DO(13, sa_nodenum[2]); 189 DO(15, sa_nodenum[3]); 190 DO(17, sa_nodenum[4]); 191 DO(19, sa_nodenum[5]); 192 } 193 else { 194 ((struct sockaddr_in *)sadr)->sin_family = AF_INET; 195 ((struct sockaddr_in *)sadr)->sin_port = 0; 196 197 if( s[0] >= '0' && s[0] <= '9' ) { 198 *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s); 199 } else { 200 if( ( h = gethostbyname( s ) ) == 0 ) { 201 return 0; 202 } 203 *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0]; 204 } 205 } 206 207 return qtrue; 208 } 209 210 #undef DO 211 212 /* 213 ============= 214 Sys_StringToAdr 215 216 idnewt 217 192.246.40.70 218 ============= 219 */ 220 qboolean Sys_StringToAdr( const char *s, netadr_t *a ) { 221 struct sockaddr sadr; 222 223 if ( !Sys_StringToSockaddr( s, &sadr ) ) { 224 return qfalse; 225 } 226 227 SockadrToNetadr( &sadr, a ); 228 return qtrue; 229 } 230 231 //============================================================================= 232 233 /* 234 ================== 235 Sys_GetPacket 236 237 Never called by the game logic, just the system event queing 238 ================== 239 */ 240 int recvfromCount; 241 242 qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) { 243 int ret; 244 struct sockaddr from; 245 int fromlen; 246 int net_socket; 247 int protocol; 248 int err; 249 250 for( protocol = 0 ; protocol < 2 ; protocol++ ) { 251 if( protocol == 0 ) { 252 net_socket = ip_socket; 253 } 254 else { 255 net_socket = ipx_socket; 256 } 257 258 if( !net_socket ) { 259 continue; 260 } 261 262 fromlen = sizeof(from); 263 recvfromCount++; // performance check 264 ret = recvfrom( net_socket, net_message->data, net_message->maxsize, 0, (struct sockaddr *)&from, &fromlen ); 265 if (ret == SOCKET_ERROR) 266 { 267 err = WSAGetLastError(); 268 269 if( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) { 270 continue; 271 } 272 Com_Printf( "NET_GetPacket: %s\n", NET_ErrorString() ); 273 continue; 274 } 275 276 if ( net_socket == ip_socket ) { 277 memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 ); 278 } 279 280 if ( usingSocks && net_socket == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) { 281 if ( ret < 10 || net_message->data[0] != 0 || net_message->data[1] != 0 || net_message->data[2] != 0 || net_message->data[3] != 1 ) { 282 continue; 283 } 284 net_from->type = NA_IP; 285 net_from->ip[0] = net_message->data[4]; 286 net_from->ip[1] = net_message->data[5]; 287 net_from->ip[2] = net_message->data[6]; 288 net_from->ip[3] = net_message->data[7]; 289 net_from->port = *(short *)&net_message->data[8]; 290 net_message->readcount = 10; 291 } 292 else { 293 SockadrToNetadr( &from, net_from ); 294 net_message->readcount = 0; 295 } 296 297 if( ret == net_message->maxsize ) { 298 Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) ); 299 continue; 300 } 301 302 net_message->cursize = ret; 303 return qtrue; 304 } 305 306 return qfalse; 307 } 308 309 //============================================================================= 310 311 static char socksBuf[4096]; 312 313 /* 314 ================== 315 Sys_SendPacket 316 ================== 317 */ 318 void Sys_SendPacket( int length, const void *data, netadr_t to ) { 319 int ret; 320 struct sockaddr addr; 321 SOCKET net_socket; 322 323 if( to.type == NA_BROADCAST ) { 324 net_socket = ip_socket; 325 } 326 else if( to.type == NA_IP ) { 327 net_socket = ip_socket; 328 } 329 else if( to.type == NA_IPX ) { 330 net_socket = ipx_socket; 331 } 332 else if( to.type == NA_BROADCAST_IPX ) { 333 net_socket = ipx_socket; 334 } 335 else { 336 Com_Error( ERR_FATAL, "Sys_SendPacket: bad address type" ); 337 return; 338 } 339 340 if( !net_socket ) { 341 return; 342 } 343 344 NetadrToSockadr( &to, &addr ); 345 346 if( usingSocks && to.type == NA_IP ) { 347 socksBuf[0] = 0; // reserved 348 socksBuf[1] = 0; 349 socksBuf[2] = 0; // fragment (not fragmented) 350 socksBuf[3] = 1; // address type: IPV4 351 *(int *)&socksBuf[4] = ((struct sockaddr_in *)&addr)->sin_addr.s_addr; 352 *(short *)&socksBuf[8] = ((struct sockaddr_in *)&addr)->sin_port; 353 memcpy( &socksBuf[10], data, length ); 354 ret = sendto( net_socket, socksBuf, length+10, 0, &socksRelayAddr, sizeof(socksRelayAddr) ); 355 } 356 else { 357 ret = sendto( net_socket, data, length, 0, &addr, sizeof(addr) ); 358 } 359 if( ret == SOCKET_ERROR ) { 360 int err = WSAGetLastError(); 361 362 // wouldblock is silent 363 if( err == WSAEWOULDBLOCK ) { 364 return; 365 } 366 367 // some PPP links do not allow broadcasts and return an error 368 if( ( err == WSAEADDRNOTAVAIL ) && ( ( to.type == NA_BROADCAST ) || ( to.type == NA_BROADCAST_IPX ) ) ) { 369 return; 370 } 371 372 Com_Printf( "NET_SendPacket: %s\n", NET_ErrorString() ); 373 } 374 } 375 376 377 //============================================================================= 378 379 /* 380 ================== 381 Sys_IsLANAddress 382 383 LAN clients will have their rate var ignored 384 ================== 385 */ 386 qboolean Sys_IsLANAddress( netadr_t adr ) { 387 int i; 388 389 if( adr.type == NA_LOOPBACK ) { 390 return qtrue; 391 } 392 393 if( adr.type == NA_IPX ) { 394 return qtrue; 395 } 396 397 if( adr.type != NA_IP ) { 398 return qfalse; 399 } 400 401 // choose which comparison to use based on the class of the address being tested 402 // any local adresses of a different class than the address being tested will fail based on the first byte 403 404 if( adr.ip[0] == 127 && adr.ip[1] == 0 && adr.ip[2] == 0 && adr.ip[3] == 1 ) { 405 return qtrue; 406 } 407 408 // Class A 409 if( (adr.ip[0] & 0x80) == 0x00 ) { 410 for ( i = 0 ; i < numIP ; i++ ) { 411 if( adr.ip[0] == localIP[i][0] ) { 412 return qtrue; 413 } 414 } 415 // the RFC1918 class a block will pass the above test 416 return qfalse; 417 } 418 419 // Class B 420 if( (adr.ip[0] & 0xc0) == 0x80 ) { 421 for ( i = 0 ; i < numIP ; i++ ) { 422 if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] ) { 423 return qtrue; 424 } 425 // also check against the RFC1918 class b blocks 426 if( adr.ip[0] == 172 && localIP[i][0] == 172 && (adr.ip[1] & 0xf0) == 16 && (localIP[i][1] & 0xf0) == 16 ) { 427 return qtrue; 428 } 429 } 430 return qfalse; 431 } 432 433 // Class C 434 for ( i = 0 ; i < numIP ; i++ ) { 435 if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) { 436 return qtrue; 437 } 438 // also check against the RFC1918 class c blocks 439 if( adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 && localIP[i][1] == 168 ) { 440 return qtrue; 441 } 442 } 443 return qfalse; 444 } 445 446 /* 447 ================== 448 Sys_ShowIP 449 ================== 450 */ 451 void Sys_ShowIP(void) { 452 int i; 453 454 for (i = 0; i < numIP; i++) { 455 Com_Printf( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] ); 456 } 457 } 458 459 460 //============================================================================= 461 462 463 /* 464 ==================== 465 NET_IPSocket 466 ==================== 467 */ 468 int NET_IPSocket( char *net_interface, int port ) { 469 SOCKET newsocket; 470 struct sockaddr_in address; 471 qboolean _true = qtrue; 472 int i = 1; 473 int err; 474 475 if( net_interface ) { 476 Com_Printf( "Opening IP socket: %s:%i\n", net_interface, port ); 477 } 478 else { 479 Com_Printf( "Opening IP socket: localhost:%i\n", port ); 480 } 481 482 if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) { 483 err = WSAGetLastError(); 484 if( err != WSAEAFNOSUPPORT ) { 485 Com_Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() ); 486 } 487 return 0; 488 } 489 490 // make it non-blocking 491 if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { 492 Com_Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() ); 493 return 0; 494 } 495 496 // make it broadcast capable 497 if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) { 498 Com_Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() ); 499 return 0; 500 } 501 502 if( !net_interface || !net_interface[0] || !Q_stricmp(net_interface, "localhost") ) { 503 address.sin_addr.s_addr = INADDR_ANY; 504 } 505 else { 506 Sys_StringToSockaddr( net_interface, (struct sockaddr *)&address ); 507 } 508 509 if( port == PORT_ANY ) { 510 address.sin_port = 0; 511 } 512 else { 513 address.sin_port = htons( (short)port ); 514 } 515 516 address.sin_family = AF_INET; 517 518 if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) { 519 Com_Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() ); 520 closesocket( newsocket ); 521 return 0; 522 } 523 524 return newsocket; 525 } 526 527 528 /* 529 ==================== 530 NET_OpenSocks 531 ==================== 532 */ 533 void NET_OpenSocks( int port ) { 534 struct sockaddr_in address; 535 int err; 536 struct hostent *h; 537 int len; 538 qboolean rfc1929; 539 unsigned char buf[64]; 540 541 usingSocks = qfalse; 542 543 Com_Printf( "Opening connection to SOCKS server.\n" ); 544 545 if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) { 546 err = WSAGetLastError(); 547 Com_Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() ); 548 return; 549 } 550 551 h = gethostbyname( net_socksServer->string ); 552 if ( h == NULL ) { 553 err = WSAGetLastError(); 554 Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() ); 555 return; 556 } 557 if ( h->h_addrtype != AF_INET ) { 558 Com_Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" ); 559 return; 560 } 561 address.sin_family = AF_INET; 562 address.sin_addr.s_addr = *(int *)h->h_addr_list[0]; 563 address.sin_port = htons( (short)net_socksPort->integer ); 564 565 if ( connect( socks_socket, (struct sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) { 566 err = WSAGetLastError(); 567 Com_Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() ); 568 return; 569 } 570 571 // send socks authentication handshake 572 if ( *net_socksUsername->string || *net_socksPassword->string ) { 573 rfc1929 = qtrue; 574 } 575 else { 576 rfc1929 = qfalse; 577 } 578 579 buf[0] = 5; // SOCKS version 580 // method count 581 if ( rfc1929 ) { 582 buf[1] = 2; 583 len = 4; 584 } 585 else { 586 buf[1] = 1; 587 len = 3; 588 } 589 buf[2] = 0; // method #1 - method id #00: no authentication 590 if ( rfc1929 ) { 591 buf[2] = 2; // method #2 - method id #02: username/password 592 } 593 if ( send( socks_socket, buf, len, 0 ) == SOCKET_ERROR ) { 594 err = WSAGetLastError(); 595 Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); 596 return; 597 } 598 599 // get the response 600 len = recv( socks_socket, buf, 64, 0 ); 601 if ( len == SOCKET_ERROR ) { 602 err = WSAGetLastError(); 603 Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); 604 return; 605 } 606 if ( len != 2 || buf[0] != 5 ) { 607 Com_Printf( "NET_OpenSocks: bad response\n" ); 608 return; 609 } 610 switch( buf[1] ) { 611 case 0: // no authentication 612 break; 613 case 2: // username/password authentication 614 break; 615 default: 616 Com_Printf( "NET_OpenSocks: request denied\n" ); 617 return; 618 } 619 620 // do username/password authentication if needed 621 if ( buf[1] == 2 ) { 622 int ulen; 623 int plen; 624 625 // build the request 626 ulen = strlen( net_socksUsername->string ); 627 plen = strlen( net_socksPassword->string ); 628 629 buf[0] = 1; // username/password authentication version 630 buf[1] = ulen; 631 if ( ulen ) { 632 memcpy( &buf[2], net_socksUsername->string, ulen ); 633 } 634 buf[2 + ulen] = plen; 635 if ( plen ) { 636 memcpy( &buf[3 + ulen], net_socksPassword->string, plen ); 637 } 638 639 // send it 640 if ( send( socks_socket, buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) { 641 err = WSAGetLastError(); 642 Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); 643 return; 644 } 645 646 // get the response 647 len = recv( socks_socket, buf, 64, 0 ); 648 if ( len == SOCKET_ERROR ) { 649 err = WSAGetLastError(); 650 Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); 651 return; 652 } 653 if ( len != 2 || buf[0] != 1 ) { 654 Com_Printf( "NET_OpenSocks: bad response\n" ); 655 return; 656 } 657 if ( buf[1] != 0 ) { 658 Com_Printf( "NET_OpenSocks: authentication failed\n" ); 659 return; 660 } 661 } 662 663 // send the UDP associate request 664 buf[0] = 5; // SOCKS version 665 buf[1] = 3; // command: UDP associate 666 buf[2] = 0; // reserved 667 buf[3] = 1; // address type: IPV4 668 *(int *)&buf[4] = INADDR_ANY; 669 *(short *)&buf[8] = htons( (short)port ); // port 670 if ( send( socks_socket, buf, 10, 0 ) == SOCKET_ERROR ) { 671 err = WSAGetLastError(); 672 Com_Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() ); 673 return; 674 } 675 676 // get the response 677 len = recv( socks_socket, buf, 64, 0 ); 678 if( len == SOCKET_ERROR ) { 679 err = WSAGetLastError(); 680 Com_Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() ); 681 return; 682 } 683 if( len < 2 || buf[0] != 5 ) { 684 Com_Printf( "NET_OpenSocks: bad response\n" ); 685 return; 686 } 687 // check completion code 688 if( buf[1] != 0 ) { 689 Com_Printf( "NET_OpenSocks: request denied: %i\n", buf[1] ); 690 return; 691 } 692 if( buf[3] != 1 ) { 693 Com_Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] ); 694 return; 695 } 696 ((struct sockaddr_in *)&socksRelayAddr)->sin_family = AF_INET; 697 ((struct sockaddr_in *)&socksRelayAddr)->sin_addr.s_addr = *(int *)&buf[4]; 698 ((struct sockaddr_in *)&socksRelayAddr)->sin_port = *(short *)&buf[8]; 699 memset( ((struct sockaddr_in *)&socksRelayAddr)->sin_zero, 0, 8 ); 700 701 usingSocks = qtrue; 702 } 703 704 705 /* 706 ===================== 707 NET_GetLocalAddress 708 ===================== 709 */ 710 void NET_GetLocalAddress( void ) { 711 char hostname[256]; 712 struct hostent *hostInfo; 713 int error; 714 char *p; 715 int ip; 716 int n; 717 718 if( gethostname( hostname, 256 ) == SOCKET_ERROR ) { 719 error = WSAGetLastError(); 720 return; 721 } 722 723 hostInfo = gethostbyname( hostname ); 724 if( !hostInfo ) { 725 error = WSAGetLastError(); 726 return; 727 } 728 729 Com_Printf( "Hostname: %s\n", hostInfo->h_name ); 730 n = 0; 731 while( ( p = hostInfo->h_aliases[n++] ) != NULL ) { 732 Com_Printf( "Alias: %s\n", p ); 733 } 734 735 if ( hostInfo->h_addrtype != AF_INET ) { 736 return; 737 } 738 739 numIP = 0; 740 while( ( p = hostInfo->h_addr_list[numIP] ) != NULL && numIP < MAX_IPS ) { 741 ip = ntohl( *(int *)p ); 742 localIP[ numIP ][0] = p[0]; 743 localIP[ numIP ][1] = p[1]; 744 localIP[ numIP ][2] = p[2]; 745 localIP[ numIP ][3] = p[3]; 746 Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff ); 747 numIP++; 748 } 749 } 750 751 /* 752 ==================== 753 NET_OpenIP 754 ==================== 755 */ 756 void NET_OpenIP( void ) { 757 cvar_t *ip; 758 int port; 759 int i; 760 761 ip = Cvar_Get( "net_ip", "localhost", CVAR_LATCH ); 762 port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH )->integer; 763 764 // automatically scan for a valid port, so multiple 765 // dedicated servers can be started without requiring 766 // a different net_port for each one 767 for( i = 0 ; i < 10 ; i++ ) { 768 ip_socket = NET_IPSocket( ip->string, port + i ); 769 if ( ip_socket ) { 770 Cvar_SetValue( "net_port", port + i ); 771 if ( net_socksEnabled->integer ) { 772 NET_OpenSocks( port + i ); 773 } 774 NET_GetLocalAddress(); 775 return; 776 } 777 } 778 Com_Printf( "WARNING: Couldn't allocate IP port\n"); 779 } 780 781 782 /* 783 ==================== 784 NET_IPXSocket 785 ==================== 786 */ 787 int NET_IPXSocket( int port ) { 788 SOCKET newsocket; 789 struct sockaddr_ipx address; 790 int _true = 1; 791 int err; 792 793 if( ( newsocket = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX ) ) == INVALID_SOCKET ) { 794 err = WSAGetLastError(); 795 if (err != WSAEAFNOSUPPORT) { 796 Com_Printf( "WARNING: IPX_Socket: socket: %s\n", NET_ErrorString() ); 797 } 798 return 0; 799 } 800 801 // make it non-blocking 802 if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) { 803 Com_Printf( "WARNING: IPX_Socket: ioctl FIONBIO: %s\n", NET_ErrorString() ); 804 return 0; 805 } 806 807 // make it broadcast capable 808 if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof( _true ) ) == SOCKET_ERROR ) { 809 Com_Printf( "WARNING: IPX_Socket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() ); 810 return 0; 811 } 812 813 address.sa_family = AF_IPX; 814 memset( address.sa_netnum, 0, 4 ); 815 memset( address.sa_nodenum, 0, 6 ); 816 if( port == PORT_ANY ) { 817 address.sa_socket = 0; 818 } 819 else { 820 address.sa_socket = htons( (short)port ); 821 } 822 823 if( bind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR ) { 824 Com_Printf( "WARNING: IPX_Socket: bind: %s\n", NET_ErrorString() ); 825 closesocket( newsocket ); 826 return 0; 827 } 828 829 return newsocket; 830 } 831 832 833 /* 834 ==================== 835 NET_OpenIPX 836 ==================== 837 */ 838 void NET_OpenIPX( void ) { 839 int port; 840 841 port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH )->integer; 842 ipx_socket = NET_IPXSocket( port ); 843 } 844 845 846 847 //=================================================================== 848 849 850 /* 851 ==================== 852 NET_GetCvars 853 ==================== 854 */ 855 static qboolean NET_GetCvars( void ) { 856 qboolean modified; 857 858 modified = qfalse; 859 860 if( net_noudp && net_noudp->modified ) { 861 modified = qtrue; 862 } 863 net_noudp = Cvar_Get( "net_noudp", "0", CVAR_LATCH | CVAR_ARCHIVE ); 864 865 if( net_noipx && net_noipx->modified ) { 866 modified = qtrue; 867 } 868 net_noipx = Cvar_Get( "net_noipx", "0", CVAR_LATCH | CVAR_ARCHIVE ); 869 870 871 if( net_socksEnabled && net_socksEnabled->modified ) { 872 modified = qtrue; 873 } 874 net_socksEnabled = Cvar_Get( "net_socksEnabled", "0", CVAR_LATCH | CVAR_ARCHIVE ); 875 876 if( net_socksServer && net_socksServer->modified ) { 877 modified = qtrue; 878 } 879 net_socksServer = Cvar_Get( "net_socksServer", "", CVAR_LATCH | CVAR_ARCHIVE ); 880 881 if( net_socksPort && net_socksPort->modified ) { 882 modified = qtrue; 883 } 884 net_socksPort = Cvar_Get( "net_socksPort", "1080", CVAR_LATCH | CVAR_ARCHIVE ); 885 886 if( net_socksUsername && net_socksUsername->modified ) { 887 modified = qtrue; 888 } 889 net_socksUsername = Cvar_Get( "net_socksUsername", "", CVAR_LATCH | CVAR_ARCHIVE ); 890 891 if( net_socksPassword && net_socksPassword->modified ) { 892 modified = qtrue; 893 } 894 net_socksPassword = Cvar_Get( "net_socksPassword", "", CVAR_LATCH | CVAR_ARCHIVE ); 895 896 897 return modified; 898 } 899 900 901 /* 902 ==================== 903 NET_Config 904 ==================== 905 */ 906 void NET_Config( qboolean enableNetworking ) { 907 qboolean modified; 908 qboolean stop; 909 qboolean start; 910 911 // get any latched changes to cvars 912 modified = NET_GetCvars(); 913 914 if( net_noudp->integer && net_noipx->integer ) { 915 enableNetworking = qfalse; 916 } 917 918 // if enable state is the same and no cvars were modified, we have nothing to do 919 if( enableNetworking == networkingEnabled && !modified ) { 920 return; 921 } 922 923 if( enableNetworking == networkingEnabled ) { 924 if( enableNetworking ) { 925 stop = qtrue; 926 start = qtrue; 927 } 928 else { 929 stop = qfalse; 930 start = qfalse; 931 } 932 } 933 else { 934 if( enableNetworking ) { 935 stop = qfalse; 936 start = qtrue; 937 } 938 else { 939 stop = qtrue; 940 start = qfalse; 941 } 942 networkingEnabled = enableNetworking; 943 } 944 945 if( stop ) { 946 if ( ip_socket && ip_socket != INVALID_SOCKET ) { 947 closesocket( ip_socket ); 948 ip_socket = 0; 949 } 950 951 if ( socks_socket && socks_socket != INVALID_SOCKET ) { 952 closesocket( socks_socket ); 953 socks_socket = 0; 954 } 955 956 if ( ipx_socket && ipx_socket != INVALID_SOCKET ) { 957 closesocket( ipx_socket ); 958 ipx_socket = 0; 959 } 960 } 961 962 if( start ) { 963 if (! net_noudp->integer ) { 964 NET_OpenIP(); 965 } 966 if (! net_noipx->integer ) { 967 NET_OpenIPX(); 968 } 969 } 970 } 971 972 973 /* 974 ==================== 975 NET_Init 976 ==================== 977 */ 978 void NET_Init( void ) { 979 int r; 980 981 r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata ); 982 if( r ) { 983 Com_Printf( "WARNING: Winsock initialization failed, returned %d\n", r ); 984 return; 985 } 986 987 winsockInitialized = qtrue; 988 Com_Printf( "Winsock Initialized\n" ); 989 990 // this is really just to get the cvars registered 991 NET_GetCvars(); 992 993 //FIXME testing! 994 NET_Config( qtrue ); 995 } 996 997 998 /* 999 ==================== 1000 NET_Shutdown 1001 ==================== 1002 */ 1003 void NET_Shutdown( void ) { 1004 if ( !winsockInitialized ) { 1005 return; 1006 } 1007 NET_Config( qfalse ); 1008 WSACleanup(); 1009 winsockInitialized = qfalse; 1010 } 1011 1012 1013 /* 1014 ==================== 1015 NET_Sleep 1016 1017 sleeps msec or until net socket is ready 1018 ==================== 1019 */ 1020 void NET_Sleep( int msec ) { 1021 } 1022 1023 1024 /* 1025 ==================== 1026 NET_Restart_f 1027 ==================== 1028 */ 1029 void NET_Restart( void ) { 1030 NET_Config( networkingEnabled ); 1031 }