win_net.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../../idlib/precompiled.h"
  22. /*
  23. ================================================================================================
  24. Contains the NetworkSystem implementation specific to Win32.
  25. ================================================================================================
  26. */
  27. #include <iptypes.h>
  28. #include <iphlpapi.h>
  29. static WSADATA winsockdata;
  30. static bool winsockInitialized = false;
  31. static bool usingSocks = false;
  32. //lint -e569 ioctl macros trigger this
  33. // force these libs to be included, so users of idLib don't need to add them to every project
  34. #pragma comment(lib, "iphlpapi.lib" )
  35. #pragma comment(lib, "wsock32.lib" )
  36. /*
  37. ================================================================================================
  38. Network CVars
  39. ================================================================================================
  40. */
  41. idCVar net_socksServer( "net_socksServer", "", CVAR_ARCHIVE, "" );
  42. idCVar net_socksPort( "net_socksPort", "1080", CVAR_ARCHIVE | CVAR_INTEGER, "" );
  43. idCVar net_socksUsername( "net_socksUsername", "", CVAR_ARCHIVE, "" );
  44. idCVar net_socksPassword( "net_socksPassword", "", CVAR_ARCHIVE, "" );
  45. idCVar net_ip( "net_ip", "localhost", 0, "local IP address" );
  46. static struct sockaddr_in socksRelayAddr;
  47. static SOCKET ip_socket;
  48. static SOCKET socks_socket;
  49. static char socksBuf[4096];
  50. typedef struct {
  51. unsigned long ip;
  52. unsigned long mask;
  53. char addr[16];
  54. } net_interface;
  55. #define MAX_INTERFACES 32
  56. int num_interfaces = 0;
  57. net_interface netint[MAX_INTERFACES];
  58. /*
  59. ================================================================================================
  60. Free Functions
  61. ================================================================================================
  62. */
  63. /*
  64. ========================
  65. NET_ErrorString
  66. ========================
  67. */
  68. char *NET_ErrorString() {
  69. int code;
  70. code = WSAGetLastError();
  71. switch( code ) {
  72. case WSAEINTR: return "WSAEINTR";
  73. case WSAEBADF: return "WSAEBADF";
  74. case WSAEACCES: return "WSAEACCES";
  75. case WSAEDISCON: return "WSAEDISCON";
  76. case WSAEFAULT: return "WSAEFAULT";
  77. case WSAEINVAL: return "WSAEINVAL";
  78. case WSAEMFILE: return "WSAEMFILE";
  79. case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
  80. case WSAEINPROGRESS: return "WSAEINPROGRESS";
  81. case WSAEALREADY: return "WSAEALREADY";
  82. case WSAENOTSOCK: return "WSAENOTSOCK";
  83. case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
  84. case WSAEMSGSIZE: return "WSAEMSGSIZE";
  85. case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
  86. case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
  87. case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
  88. case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
  89. case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
  90. case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
  91. case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
  92. case WSAEADDRINUSE: return "WSAEADDRINUSE";
  93. case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
  94. case WSAENETDOWN: return "WSAENETDOWN";
  95. case WSAENETUNREACH: return "WSAENETUNREACH";
  96. case WSAENETRESET: return "WSAENETRESET";
  97. case WSAECONNABORTED: return "WSAECONNABORTED";
  98. case WSAECONNRESET: return "WSAECONNRESET";
  99. case WSAENOBUFS: return "WSAENOBUFS";
  100. case WSAEISCONN: return "WSAEISCONN";
  101. case WSAENOTCONN: return "WSAENOTCONN";
  102. case WSAESHUTDOWN: return "WSAESHUTDOWN";
  103. case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
  104. case WSAETIMEDOUT: return "WSAETIMEDOUT";
  105. case WSAECONNREFUSED: return "WSAECONNREFUSED";
  106. case WSAELOOP: return "WSAELOOP";
  107. case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
  108. case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
  109. case WSASYSNOTREADY: return "WSASYSNOTREADY";
  110. case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
  111. case WSANOTINITIALISED: return "WSANOTINITIALISED";
  112. case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
  113. case WSATRY_AGAIN: return "WSATRY_AGAIN";
  114. case WSANO_RECOVERY: return "WSANO_RECOVERY";
  115. case WSANO_DATA: return "WSANO_DATA";
  116. default: return "NO ERROR";
  117. }
  118. }
  119. /*
  120. ========================
  121. Net_NetadrToSockadr
  122. ========================
  123. */
  124. void Net_NetadrToSockadr( const netadr_t *a, sockaddr_in *s ) {
  125. memset( s, 0, sizeof(*s) );
  126. if ( a->type == NA_BROADCAST ) {
  127. s->sin_family = AF_INET;
  128. s->sin_addr.s_addr = INADDR_BROADCAST;
  129. } else if ( a->type == NA_IP || a->type == NA_LOOPBACK ) {
  130. s->sin_family = AF_INET;
  131. s->sin_addr.s_addr = *(int *)a->ip;
  132. }
  133. s->sin_port = htons( (short)a->port );
  134. }
  135. /*
  136. ========================
  137. Net_SockadrToNetadr
  138. ========================
  139. */
  140. void Net_SockadrToNetadr( sockaddr_in *s, netadr_t *a ) {
  141. unsigned int ip;
  142. if ( s->sin_family == AF_INET ) {
  143. ip = s->sin_addr.s_addr;
  144. *(unsigned int *)a->ip = ip;
  145. a->port = htons( s->sin_port );
  146. // we store in network order, that loopback test is host order..
  147. ip = ntohl( ip );
  148. if ( ip == INADDR_LOOPBACK ) {
  149. a->type = NA_LOOPBACK;
  150. } else {
  151. a->type = NA_IP;
  152. }
  153. }
  154. }
  155. /*
  156. ========================
  157. Net_ExtractPort
  158. ========================
  159. */
  160. static bool Net_ExtractPort( const char *src, char *buf, int bufsize, int *port ) {
  161. char *p;
  162. strncpy( buf, src, bufsize );
  163. p = buf; p += Min( bufsize - 1, idStr::Length( src ) ); *p = '\0';
  164. p = strchr( buf, ':' );
  165. if ( !p ) {
  166. return false;
  167. }
  168. *p = '\0';
  169. *port = strtol( p+1, NULL, 10 );
  170. if ( errno == ERANGE ) {
  171. return false;
  172. }
  173. return true;
  174. }
  175. /*
  176. ========================
  177. Net_StringToSockaddr
  178. ========================
  179. */
  180. static bool Net_StringToSockaddr( const char *s, sockaddr_in *sadr, bool doDNSResolve ) {
  181. struct hostent *h;
  182. char buf[256];
  183. int port;
  184. memset( sadr, 0, sizeof( *sadr ) );
  185. sadr->sin_family = AF_INET;
  186. sadr->sin_port = 0;
  187. if( s[0] >= '0' && s[0] <= '9' ) {
  188. unsigned long ret = inet_addr(s);
  189. if ( ret != INADDR_NONE ) {
  190. *(int *)&sadr->sin_addr = ret;
  191. } else {
  192. // check for port
  193. if ( !Net_ExtractPort( s, buf, sizeof( buf ), &port ) ) {
  194. return false;
  195. }
  196. ret = inet_addr( buf );
  197. if ( ret == INADDR_NONE ) {
  198. return false;
  199. }
  200. *(int *)&sadr->sin_addr = ret;
  201. sadr->sin_port = htons( port );
  202. }
  203. } else if ( doDNSResolve ) {
  204. // try to remove the port first, otherwise the DNS gets confused into multiple timeouts
  205. // failed or not failed, buf is expected to contain the appropriate host to resolve
  206. if ( Net_ExtractPort( s, buf, sizeof( buf ), &port ) ) {
  207. sadr->sin_port = htons( port );
  208. }
  209. h = gethostbyname( buf );
  210. if ( h == 0 ) {
  211. return false;
  212. }
  213. *(int *)&sadr->sin_addr = *(int *)h->h_addr_list[0];
  214. }
  215. return true;
  216. }
  217. /*
  218. ========================
  219. NET_IPSocket
  220. ========================
  221. */
  222. int NET_IPSocket( const char *net_interface, int port, netadr_t *bound_to ) {
  223. SOCKET newsocket;
  224. sockaddr_in address;
  225. unsigned long _true = 1;
  226. int i = 1;
  227. int err;
  228. if ( port != PORT_ANY ) {
  229. if( net_interface ) {
  230. idLib::Printf( "Opening IP socket: %s:%i\n", net_interface, port );
  231. } else {
  232. idLib::Printf( "Opening IP socket: localhost:%i\n", port );
  233. }
  234. }
  235. if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
  236. err = WSAGetLastError();
  237. if( err != WSAEAFNOSUPPORT ) {
  238. idLib::Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() );
  239. }
  240. return 0;
  241. }
  242. // make it non-blocking
  243. if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
  244. idLib::Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() );
  245. closesocket( newsocket );
  246. return 0;
  247. }
  248. // make it broadcast capable
  249. if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) {
  250. idLib::Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
  251. closesocket( newsocket );
  252. return 0;
  253. }
  254. if( !net_interface || !net_interface[0] || !idStr::Icmp( net_interface, "localhost" ) ) {
  255. address.sin_addr.s_addr = INADDR_ANY;
  256. }
  257. else {
  258. Net_StringToSockaddr( net_interface, &address, true );
  259. }
  260. if( port == PORT_ANY ) {
  261. address.sin_port = 0;
  262. }
  263. else {
  264. address.sin_port = htons( (short)port );
  265. }
  266. address.sin_family = AF_INET;
  267. if( bind( newsocket, (const sockaddr *)&address, sizeof(address) ) == SOCKET_ERROR ) {
  268. idLib::Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() );
  269. closesocket( newsocket );
  270. return 0;
  271. }
  272. // if the port was PORT_ANY, we need to query again to know the real port we got bound to
  273. // ( this used to be in idUDP::InitForPort )
  274. if ( bound_to ) {
  275. int len = sizeof( address );
  276. getsockname( newsocket, (sockaddr *)&address, &len );
  277. Net_SockadrToNetadr( &address, bound_to );
  278. }
  279. return newsocket;
  280. }
  281. /*
  282. ========================
  283. NET_OpenSocks
  284. ========================
  285. */
  286. void NET_OpenSocks( int port ) {
  287. sockaddr_in address;
  288. struct hostent *h;
  289. int len;
  290. bool rfc1929;
  291. unsigned char buf[64];
  292. usingSocks = false;
  293. idLib::Printf( "Opening connection to SOCKS server.\n" );
  294. if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) {
  295. idLib::Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() );
  296. return;
  297. }
  298. h = gethostbyname( net_socksServer.GetString() );
  299. if ( h == NULL ) {
  300. idLib::Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() );
  301. return;
  302. }
  303. if ( h->h_addrtype != AF_INET ) {
  304. idLib::Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" );
  305. return;
  306. }
  307. address.sin_family = AF_INET;
  308. address.sin_addr.s_addr = *(int *)h->h_addr_list[0];
  309. address.sin_port = htons( (short)net_socksPort.GetInteger() );
  310. if ( connect( socks_socket, (sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) {
  311. idLib::Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() );
  312. return;
  313. }
  314. // send socks authentication handshake
  315. if ( *net_socksUsername.GetString() || *net_socksPassword.GetString() ) {
  316. rfc1929 = true;
  317. }
  318. else {
  319. rfc1929 = false;
  320. }
  321. buf[0] = 5; // SOCKS version
  322. // method count
  323. if ( rfc1929 ) {
  324. buf[1] = 2;
  325. len = 4;
  326. }
  327. else {
  328. buf[1] = 1;
  329. len = 3;
  330. }
  331. buf[2] = 0; // method #1 - method id #00: no authentication
  332. if ( rfc1929 ) {
  333. buf[2] = 2; // method #2 - method id #02: username/password
  334. }
  335. if ( send( socks_socket, (const char *)buf, len, 0 ) == SOCKET_ERROR ) {
  336. idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
  337. return;
  338. }
  339. // get the response
  340. len = recv( socks_socket, (char *)buf, 64, 0 );
  341. if ( len == SOCKET_ERROR ) {
  342. idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
  343. return;
  344. }
  345. if ( len != 2 || buf[0] != 5 ) {
  346. idLib::Printf( "NET_OpenSocks: bad response\n" );
  347. return;
  348. }
  349. switch( buf[1] ) {
  350. case 0: // no authentication
  351. break;
  352. case 2: // username/password authentication
  353. break;
  354. default:
  355. idLib::Printf( "NET_OpenSocks: request denied\n" );
  356. return;
  357. }
  358. // do username/password authentication if needed
  359. if ( buf[1] == 2 ) {
  360. int ulen;
  361. int plen;
  362. // build the request
  363. ulen = idStr::Length( net_socksUsername.GetString() );
  364. plen = idStr::Length( net_socksPassword.GetString() );
  365. buf[0] = 1; // username/password authentication version
  366. buf[1] = ulen;
  367. if ( ulen ) {
  368. memcpy( &buf[2], net_socksUsername.GetString(), ulen );
  369. }
  370. buf[2 + ulen] = plen;
  371. if ( plen ) {
  372. memcpy( &buf[3 + ulen], net_socksPassword.GetString(), plen );
  373. }
  374. // send it
  375. if ( send( socks_socket, (const char *)buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) {
  376. idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
  377. return;
  378. }
  379. // get the response
  380. len = recv( socks_socket, (char *)buf, 64, 0 );
  381. if ( len == SOCKET_ERROR ) {
  382. idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
  383. return;
  384. }
  385. if ( len != 2 || buf[0] != 1 ) {
  386. idLib::Printf( "NET_OpenSocks: bad response\n" );
  387. return;
  388. }
  389. if ( buf[1] != 0 ) {
  390. idLib::Printf( "NET_OpenSocks: authentication failed\n" );
  391. return;
  392. }
  393. }
  394. // send the UDP associate request
  395. buf[0] = 5; // SOCKS version
  396. buf[1] = 3; // command: UDP associate
  397. buf[2] = 0; // reserved
  398. buf[3] = 1; // address type: IPV4
  399. *(int *)&buf[4] = INADDR_ANY;
  400. *(short *)&buf[8] = htons( (short)port ); // port
  401. if ( send( socks_socket, (const char *)buf, 10, 0 ) == SOCKET_ERROR ) {
  402. idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
  403. return;
  404. }
  405. // get the response
  406. len = recv( socks_socket, (char *)buf, 64, 0 );
  407. if( len == SOCKET_ERROR ) {
  408. idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
  409. return;
  410. }
  411. if( len < 2 || buf[0] != 5 ) {
  412. idLib::Printf( "NET_OpenSocks: bad response\n" );
  413. return;
  414. }
  415. // check completion code
  416. if( buf[1] != 0 ) {
  417. idLib::Printf( "NET_OpenSocks: request denied: %i\n", buf[1] );
  418. return;
  419. }
  420. if( buf[3] != 1 ) {
  421. idLib::Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
  422. return;
  423. }
  424. socksRelayAddr.sin_family = AF_INET;
  425. socksRelayAddr.sin_addr.s_addr = *(int *)&buf[4];
  426. socksRelayAddr.sin_port = *(short *)&buf[8];
  427. memset( socksRelayAddr.sin_zero, 0, sizeof( socksRelayAddr.sin_zero ) );
  428. usingSocks = true;
  429. }
  430. /*
  431. ========================
  432. Net_WaitForData
  433. ========================
  434. */
  435. bool Net_WaitForData( int netSocket, int timeout ) {
  436. int ret;
  437. fd_set set;
  438. struct timeval tv;
  439. if ( !netSocket ) {
  440. return false;
  441. }
  442. if ( timeout < 0 ) {
  443. return true;
  444. }
  445. FD_ZERO( &set );
  446. FD_SET( static_cast<unsigned int>( netSocket ), &set );
  447. tv.tv_sec = 0;
  448. tv.tv_usec = timeout * 1000;
  449. ret = select( netSocket + 1, &set, NULL, NULL, &tv );
  450. if ( ret == -1 ) {
  451. idLib::Printf( "Net_WaitForData select(): %s\n", strerror( errno ) );
  452. return false;
  453. }
  454. // timeout with no data
  455. if ( ret == 0 ) {
  456. return false;
  457. }
  458. return true;
  459. }
  460. /*
  461. ========================
  462. Net_GetUDPPacket
  463. ========================
  464. */
  465. bool Net_GetUDPPacket( int netSocket, netadr_t &net_from, char *data, int &size, int maxSize ) {
  466. int ret;
  467. sockaddr_in from;
  468. int fromlen;
  469. int err;
  470. if ( !netSocket ) {
  471. return false;
  472. }
  473. fromlen = sizeof(from);
  474. ret = recvfrom( netSocket, data, maxSize, 0, (sockaddr *)&from, &fromlen );
  475. if ( ret == SOCKET_ERROR ) {
  476. err = WSAGetLastError();
  477. if ( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) {
  478. return false;
  479. }
  480. char buf[1024];
  481. sprintf( buf, "Net_GetUDPPacket: %s\n", NET_ErrorString() );
  482. idLib::Printf( buf );
  483. return false;
  484. }
  485. if ( static_cast<unsigned int>( netSocket ) == ip_socket ) {
  486. memset( from.sin_zero, 0, sizeof( from.sin_zero ) );
  487. }
  488. if ( usingSocks && static_cast<unsigned int>( netSocket ) == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) {
  489. if ( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) {
  490. return false;
  491. }
  492. net_from.type = NA_IP;
  493. net_from.ip[0] = data[4];
  494. net_from.ip[1] = data[5];
  495. net_from.ip[2] = data[6];
  496. net_from.ip[3] = data[7];
  497. net_from.port = *(short *)&data[8];
  498. memmove( data, &data[10], ret - 10 );
  499. } else {
  500. Net_SockadrToNetadr( &from, &net_from );
  501. }
  502. if ( ret > maxSize ) {
  503. char buf[1024];
  504. sprintf( buf, "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) );
  505. idLib::Printf( buf );
  506. return false;
  507. }
  508. size = ret;
  509. return true;
  510. }
  511. /*
  512. ========================
  513. Net_SendUDPPacket
  514. ========================
  515. */
  516. void Net_SendUDPPacket( int netSocket, int length, const void *data, const netadr_t to ) {
  517. int ret;
  518. sockaddr_in addr;
  519. if ( !netSocket ) {
  520. return;
  521. }
  522. Net_NetadrToSockadr( &to, &addr );
  523. if ( usingSocks && to.type == NA_IP ) {
  524. socksBuf[0] = 0; // reserved
  525. socksBuf[1] = 0;
  526. socksBuf[2] = 0; // fragment (not fragmented)
  527. socksBuf[3] = 1; // address type: IPV4
  528. *(int *)&socksBuf[4] = addr.sin_addr.s_addr;
  529. *(short *)&socksBuf[8] = addr.sin_port;
  530. memcpy( &socksBuf[10], data, length );
  531. ret = sendto( netSocket, socksBuf, length+10, 0, (sockaddr *)&socksRelayAddr, sizeof(socksRelayAddr) );
  532. } else {
  533. ret = sendto( netSocket, (const char *)data, length, 0, (sockaddr *)&addr, sizeof(addr) );
  534. }
  535. if ( ret == SOCKET_ERROR ) {
  536. int err = WSAGetLastError();
  537. // some PPP links do not allow broadcasts and return an error
  538. if ( ( err == WSAEADDRNOTAVAIL ) && ( to.type == NA_BROADCAST ) ) {
  539. return;
  540. }
  541. // NOTE: WSAEWOULDBLOCK used to be silently ignored,
  542. // but that means the packet will be dropped so I don't feel it's a good thing to ignore
  543. idLib::Printf( "UDP sendto error - packet dropped: %s\n", NET_ErrorString() );
  544. }
  545. }
  546. /*
  547. ========================
  548. Sys_InitNetworking
  549. ========================
  550. */
  551. void Sys_InitNetworking() {
  552. int r;
  553. if ( winsockInitialized ) {
  554. return;
  555. }
  556. r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata );
  557. if( r ) {
  558. idLib::Printf( "WARNING: Winsock initialization failed, returned %d\n", r );
  559. return;
  560. }
  561. winsockInitialized = true;
  562. idLib::Printf( "Winsock Initialized\n" );
  563. PIP_ADAPTER_INFO pAdapterInfo;
  564. PIP_ADAPTER_INFO pAdapter = NULL;
  565. DWORD dwRetVal = 0;
  566. PIP_ADDR_STRING pIPAddrString;
  567. ULONG ulOutBufLen;
  568. bool foundloopback;
  569. num_interfaces = 0;
  570. foundloopback = false;
  571. pAdapterInfo = (IP_ADAPTER_INFO *)malloc( sizeof( IP_ADAPTER_INFO ) );
  572. if( !pAdapterInfo ) {
  573. idLib::FatalError( "Sys_InitNetworking: Couldn't malloc( %d )", sizeof( IP_ADAPTER_INFO ) );
  574. }
  575. ulOutBufLen = sizeof( IP_ADAPTER_INFO );
  576. // Make an initial call to GetAdaptersInfo to get
  577. // the necessary size into the ulOutBufLen variable
  578. if( GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ) == ERROR_BUFFER_OVERFLOW ) {
  579. free( pAdapterInfo );
  580. pAdapterInfo = (IP_ADAPTER_INFO *)malloc( ulOutBufLen );
  581. if( !pAdapterInfo ) {
  582. idLib::FatalError( "Sys_InitNetworking: Couldn't malloc( %ld )", ulOutBufLen );
  583. }
  584. }
  585. if( ( dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) ) != NO_ERROR ) {
  586. // happens if you have no network connection
  587. idLib::Printf( "Sys_InitNetworking: GetAdaptersInfo failed (%ld).\n", dwRetVal );
  588. } else {
  589. pAdapter = pAdapterInfo;
  590. while( pAdapter ) {
  591. idLib::Printf( "Found interface: %s %s - ", pAdapter->AdapterName, pAdapter->Description );
  592. pIPAddrString = &pAdapter->IpAddressList;
  593. while( pIPAddrString ) {
  594. unsigned long ip_a, ip_m;
  595. if( !idStr::Icmp( "127.0.0.1", pIPAddrString->IpAddress.String ) ) {
  596. foundloopback = true;
  597. }
  598. ip_a = ntohl( inet_addr( pIPAddrString->IpAddress.String ) );
  599. ip_m = ntohl( inet_addr( pIPAddrString->IpMask.String ) );
  600. //skip null netmasks
  601. if( !ip_m ) {
  602. idLib::Printf( "%s NULL netmask - skipped\n", pIPAddrString->IpAddress.String );
  603. pIPAddrString = pIPAddrString->Next;
  604. continue;
  605. }
  606. idLib::Printf( "%s/%s\n", pIPAddrString->IpAddress.String, pIPAddrString->IpMask.String );
  607. netint[num_interfaces].ip = ip_a;
  608. netint[num_interfaces].mask = ip_m;
  609. idStr::Copynz( netint[num_interfaces].addr, pIPAddrString->IpAddress.String, sizeof( netint[num_interfaces].addr ) );
  610. num_interfaces++;
  611. if( num_interfaces >= MAX_INTERFACES ) {
  612. idLib::Printf( "Sys_InitNetworking: MAX_INTERFACES(%d) hit.\n", MAX_INTERFACES );
  613. free( pAdapterInfo );
  614. return;
  615. }
  616. pIPAddrString = pIPAddrString->Next;
  617. }
  618. pAdapter = pAdapter->Next;
  619. }
  620. }
  621. // for some retarded reason, win32 doesn't count loopback as an adapter...
  622. if( !foundloopback && num_interfaces < MAX_INTERFACES ) {
  623. idLib::Printf( "Sys_InitNetworking: adding loopback interface\n" );
  624. netint[num_interfaces].ip = ntohl( inet_addr( "127.0.0.1" ) );
  625. netint[num_interfaces].mask = ntohl( inet_addr( "255.0.0.0" ) );
  626. num_interfaces++;
  627. }
  628. free( pAdapterInfo );
  629. }
  630. /*
  631. ========================
  632. Sys_ShutdownNetworking
  633. ========================
  634. */
  635. void Sys_ShutdownNetworking() {
  636. if ( !winsockInitialized ) {
  637. return;
  638. }
  639. WSACleanup();
  640. winsockInitialized = false;
  641. }
  642. /*
  643. ========================
  644. Sys_StringToNetAdr
  645. ========================
  646. */
  647. bool Sys_StringToNetAdr( const char *s, netadr_t *a, bool doDNSResolve ) {
  648. sockaddr_in sadr;
  649. if ( !Net_StringToSockaddr( s, &sadr, doDNSResolve ) ) {
  650. return false;
  651. }
  652. Net_SockadrToNetadr( &sadr, a );
  653. return true;
  654. }
  655. /*
  656. ========================
  657. Sys_NetAdrToString
  658. ========================
  659. */
  660. const char *Sys_NetAdrToString( const netadr_t a ) {
  661. static int index = 0;
  662. static char buf[ 4 ][ 64 ]; // flip/flop
  663. char *s;
  664. s = buf[index];
  665. index = (index + 1) & 3;
  666. if ( a.type == NA_LOOPBACK ) {
  667. if ( a.port ) {
  668. idStr::snPrintf( s, 64, "localhost:%i", a.port );
  669. } else {
  670. idStr::snPrintf( s, 64, "localhost" );
  671. }
  672. } else if ( a.type == NA_IP ) {
  673. idStr::snPrintf( s, 64, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], a.port );
  674. }
  675. return s;
  676. }
  677. /*
  678. ========================
  679. Sys_IsLANAddress
  680. ========================
  681. */
  682. bool Sys_IsLANAddress( const netadr_t adr ) {
  683. if ( adr.type == NA_LOOPBACK ) {
  684. return true;
  685. }
  686. if ( adr.type != NA_IP ) {
  687. return false;
  688. }
  689. if ( num_interfaces ) {
  690. int i;
  691. unsigned long *p_ip;
  692. unsigned long ip;
  693. p_ip = (unsigned long *)&adr.ip[0];
  694. ip = ntohl( *p_ip );
  695. for( i = 0; i < num_interfaces; i++ ) {
  696. if( ( netint[i].ip & netint[i].mask ) == ( ip & netint[i].mask ) ) {
  697. return true;
  698. }
  699. }
  700. }
  701. return false;
  702. }
  703. /*
  704. ========================
  705. Sys_CompareNetAdrBase
  706. Compares without the port.
  707. ========================
  708. */
  709. bool Sys_CompareNetAdrBase( const netadr_t a, const netadr_t b ) {
  710. if ( a.type != b.type ) {
  711. return false;
  712. }
  713. if ( a.type == NA_LOOPBACK ) {
  714. if ( a.port == b.port ) {
  715. return true;
  716. }
  717. return false;
  718. }
  719. if ( a.type == NA_IP ) {
  720. if ( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] ) {
  721. return true;
  722. }
  723. return false;
  724. }
  725. idLib::Printf( "Sys_CompareNetAdrBase: bad address type\n" );
  726. return false;
  727. }
  728. /*
  729. ========================
  730. Sys_GetLocalIPCount
  731. ========================
  732. */
  733. int Sys_GetLocalIPCount() {
  734. return num_interfaces;
  735. }
  736. /*
  737. ========================
  738. Sys_GetLocalIP
  739. ========================
  740. */
  741. const char * Sys_GetLocalIP( int i ) {
  742. if ( ( i < 0 ) || ( i >= num_interfaces ) ) {
  743. return NULL;
  744. }
  745. return netint[i].addr;
  746. }
  747. /*
  748. ================================================================================================
  749. idUDP
  750. ================================================================================================
  751. */
  752. /*
  753. ========================
  754. idUDP::idUDP
  755. ========================
  756. */
  757. idUDP::idUDP() {
  758. netSocket = 0;
  759. memset( &bound_to, 0, sizeof( bound_to ) );
  760. silent = false;
  761. packetsRead = 0;
  762. bytesRead = 0;
  763. packetsWritten = 0;
  764. bytesWritten = 0;
  765. }
  766. /*
  767. ========================
  768. idUDP::~idUDP
  769. ========================
  770. */
  771. idUDP::~idUDP() {
  772. Close();
  773. }
  774. /*
  775. ========================
  776. idUDP::InitForPort
  777. ========================
  778. */
  779. bool idUDP::InitForPort( int portNumber ) {
  780. netSocket = NET_IPSocket( net_ip.GetString(), portNumber, &bound_to );
  781. if ( netSocket <= 0 ) {
  782. netSocket = 0;
  783. memset( &bound_to, 0, sizeof( bound_to ) );
  784. return false;
  785. }
  786. return true;
  787. }
  788. /*
  789. ========================
  790. idUDP::Close
  791. ========================
  792. */
  793. void idUDP::Close() {
  794. if ( netSocket ) {
  795. closesocket( netSocket );
  796. netSocket = 0;
  797. memset( &bound_to, 0, sizeof( bound_to ) );
  798. }
  799. }
  800. /*
  801. ========================
  802. idUDP::GetPacket
  803. ========================
  804. */
  805. bool idUDP::GetPacket( netadr_t &from, void *data, int &size, int maxSize ) {
  806. bool ret;
  807. while ( 1 ) {
  808. ret = Net_GetUDPPacket( netSocket, from, (char *)data, size, maxSize );
  809. if ( !ret ) {
  810. break;
  811. }
  812. packetsRead++;
  813. bytesRead += size;
  814. break;
  815. }
  816. return ret;
  817. }
  818. /*
  819. ========================
  820. idUDP::GetPacketBlocking
  821. ========================
  822. */
  823. bool idUDP::GetPacketBlocking( netadr_t &from, void *data, int &size, int maxSize, int timeout ) {
  824. if ( !Net_WaitForData( netSocket, timeout ) ) {
  825. return false;
  826. }
  827. if ( GetPacket( from, data, size, maxSize ) ) {
  828. return true;
  829. }
  830. return false;
  831. }
  832. /*
  833. ========================
  834. idUDP::SendPacket
  835. ========================
  836. */
  837. void idUDP::SendPacket( const netadr_t to, const void *data, int size ) {
  838. if ( to.type == NA_BAD ) {
  839. idLib::Warning( "idUDP::SendPacket: bad address type NA_BAD - ignored" );
  840. return;
  841. }
  842. packetsWritten++;
  843. bytesWritten += size;
  844. if ( silent ) {
  845. return;
  846. }
  847. Net_SendUDPPacket( netSocket, size, data, to );
  848. }