2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
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.
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.
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
===========================================================================
24
#include "../qcommon/q_shared.h"
25
#include "../qcommon/qcommon.h"
28
#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
29
// needed for socket_t on OSX 10.2
30
#define _BSD_SOCKLEN_T_
32
#include <sys/socket.h>
34
#include <netinet/in.h>
36
#include <arpa/inet.h> // bk001204
38
#include <sys/param.h>
39
#include <sys/ioctl.h>
44
#import <sys/sockio.h>
46
#import <net/if_types.h>
48
#import <arpa/inet.h> // for inet_ntoa()
49
#import <net/if_dl.h> // for 'struct sockaddr_dl'
53
#include <sys/filio.h>
58
netadr_t net_local_adr;
65
static byte localIP[MAX_IPS][4];
67
int NET_Socket (char *net_interface, int port);
68
char *NET_ErrorString (void);
70
//=============================================================================
72
void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
74
memset (s, 0, sizeof(*s));
76
if (a->type == NA_BROADCAST)
78
s->sin_family = AF_INET;
80
s->sin_port = a->port;
81
*(int *)&s->sin_addr = -1;
83
else if (a->type == NA_IP)
85
s->sin_family = AF_INET;
87
*(int *)&s->sin_addr = *(int *)&a->ip;
88
s->sin_port = a->port;
92
void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
94
*(int *)&a->ip = *(int *)&s->sin_addr;
95
a->port = s->sin_port;
99
char *NET_BaseAdrToString (netadr_t a)
103
Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
116
qboolean Sys_StringToSockaddr (const char *s, struct sockaddr *sadr)
119
//char *colon; // bk001204 - unused
121
memset (sadr, 0, sizeof(*sadr));
122
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
124
((struct sockaddr_in *)sadr)->sin_port = 0;
126
if ( s[0] >= '0' && s[0] <= '9')
128
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s);
132
if (! (h = gethostbyname(s)) )
134
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
151
qboolean Sys_StringToAdr (const char *s, netadr_t *a)
153
struct sockaddr_in sadr;
155
if (!Sys_StringToSockaddr (s, (struct sockaddr *)&sadr))
158
SockadrToNetadr (&sadr, a);
164
//=============================================================================
166
qboolean Sys_GetPacket (netadr_t *net_from, msg_t *net_message)
169
struct sockaddr_in from;
175
for (protocol = 0 ; protocol < 2 ; protocol++)
178
net_socket = ip_socket;
180
net_socket = ipx_socket;
185
fromlen = sizeof(from);
186
ret = recvfrom (net_socket, net_message->data, net_message->maxsize
187
, 0, (struct sockaddr *)&from, &fromlen);
189
SockadrToNetadr (&from, net_from);
190
// bk000305: was missing
191
net_message->readcount = 0;
197
if (err == EWOULDBLOCK || err == ECONNREFUSED)
199
Com_Printf ("NET_GetPacket: %s from %s\n", NET_ErrorString(),
200
NET_AdrToString(*net_from));
204
if (ret == net_message->maxsize)
206
Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from));
210
net_message->cursize = ret;
217
//=============================================================================
219
void Sys_SendPacket( int length, const void *data, netadr_t to )
222
struct sockaddr_in addr;
225
if (to.type == NA_BROADCAST)
227
net_socket = ip_socket;
229
else if (to.type == NA_IP)
231
net_socket = ip_socket;
233
else if (to.type == NA_IPX)
235
net_socket = ipx_socket;
237
else if (to.type == NA_BROADCAST_IPX)
239
net_socket = ipx_socket;
242
Com_Error (ERR_FATAL, "NET_SendPacket: bad address type");
249
NetadrToSockadr (&to, &addr);
251
ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
254
Com_Printf ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(),
255
NET_AdrToString (to));
260
//=============================================================================
266
LAN clients will have their rate var ignored
269
qboolean Sys_IsLANAddress (netadr_t adr) {
272
if( adr.type == NA_LOOPBACK ) {
276
if( adr.type == NA_IPX ) {
280
if( adr.type != NA_IP ) {
285
// 10.0.0.0 - 10.255.255.255 (10/8 prefix)
286
// 172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
287
// 192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
290
if(adr.ip[0] == 172 && (adr.ip[1]&0xf0) == 16)
292
if(adr.ip[0] == 192 && adr.ip[1] == 168)
295
// the checks below are bogus, aren't they? -- ln
297
// choose which comparison to use based on the class of the address being tested
298
// any local adresses of a different class than the address being tested will fail based on the first byte
301
if( (adr.ip[0] & 0x80) == 0x00 ) {
302
for ( i = 0 ; i < numIP ; i++ ) {
303
if( adr.ip[0] == localIP[i][0] ) {
307
// the RFC1918 class a block will pass the above test
312
if( (adr.ip[0] & 0xc0) == 0x80 ) {
313
for ( i = 0 ; i < numIP ; i++ ) {
314
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] ) {
317
// also check against the RFC1918 class b blocks
318
if( adr.ip[0] == 172 && localIP[i][0] == 172 && (adr.ip[1] & 0xf0) == 16 && (localIP[i][1] & 0xf0) == 16 ) {
326
for ( i = 0 ; i < numIP ; i++ ) {
327
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) {
330
// also check against the RFC1918 class c blocks
331
if( adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 && localIP[i][1] == 168 ) {
343
void Sys_ShowIP(void) {
346
for (i = 0; i < numIP; i++) {
347
Com_Printf( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] );
352
=====================
354
=====================
357
// Don't do a forward mapping from the hostname of the machine to the IP.
358
// The reason is that we might have obtained an IP address from DHCP and
359
// there might not be any name registered for the machine. On Mac OS X,
360
// the machine name defaults to 'localhost' and NetInfo has 127.0.0.1
361
// listed for this name. Instead, we want to get a list of all the IP
362
// network interfaces on the machine. This code adapted from
366
#ifdef _SIZEOF_ADDR_IFREQ
367
// tjw: OSX 10.4 does not have sa_len
368
#define IFR_NEXT(ifr) \
369
((struct ifreq *) ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr)))
371
// tjw: assume that once upon a time some version did have sa_len
372
#define IFR_NEXT(ifr) \
373
((struct ifreq *) ((char *) (ifr) + sizeof(*(ifr)) + \
374
MAX(0, (int) (ifr)->ifr_addr.sa_len - (int) sizeof((ifr)->ifr_addr))))
377
void NET_GetLocalAddress( void ) {
378
struct ifreq requestBuffer[MAX_IPS], *linkInterface, *inetInterface;
381
struct sockaddr_dl *sdl;
385
Com_Printf("NET_GetLocalAddress: Querying for network interfaces\n");
387
// Set this early so we can just return if there is an error
390
ifc.ifc_len = sizeof(requestBuffer);
391
ifc.ifc_buf = (caddr_t)requestBuffer;
393
// Since we get at this info via an ioctl, we need a temporary little socket.
394
// This will only get AF_INET interfaces, but we probably don't care about
395
// anything else. If we do end up caring later, we should add a
396
// ONAddressFamily and at a -interfaces method to it.
398
if ((interfaceSocket = socket(family, SOCK_DGRAM, 0)) < 0) {
399
Com_Printf("NET_GetLocalAddress: Unable to create temporary socket, errno = %d\n", errno);
403
if (ioctl(interfaceSocket, SIOCGIFCONF, &ifc) != 0) {
404
Com_Printf("NET_GetLocalAddress: Unable to get list of network interfaces, errno = %d\n", errno);
409
linkInterface = (struct ifreq *) ifc.ifc_buf;
410
while ((char *) linkInterface < &ifc.ifc_buf[ifc.ifc_len]) {
411
unsigned int nameLength;
413
// The ioctl returns both the entries having the address (AF_INET)
414
// and the link layer entries (AF_LINK). The AF_LINK entry has the
415
// link layer address which contains the interface type. This is the
416
// only way I can see to get this information. We cannot assume that
417
// we will get bot an AF_LINK and AF_INET entry since the interface
418
// may not be configured. For example, if you have a 10Mb port on
419
// the motherboard and a 100Mb card, you may not configure the
422
// For each AF_LINK entry...
423
if (linkInterface->ifr_addr.sa_family == AF_LINK) {
424
// if there is a matching AF_INET entry
425
inetInterface = (struct ifreq *) ifc.ifc_buf;
426
while ((char *) inetInterface < &ifc.ifc_buf[ifc.ifc_len]) {
427
if (inetInterface->ifr_addr.sa_family == AF_INET &&
428
!strncmp(inetInterface->ifr_name, linkInterface->ifr_name,
429
sizeof(linkInterface->ifr_name))) {
431
for (nameLength = 0; nameLength < IFNAMSIZ; nameLength++)
432
if (!linkInterface->ifr_name[nameLength])
435
sdl = (struct sockaddr_dl *)&linkInterface->ifr_addr;
436
// Skip loopback interfaces
437
if (sdl->sdl_type != IFT_LOOP) {
438
// Get the local interface address
439
strncpy(ifr.ifr_name, inetInterface->ifr_name, sizeof(ifr.ifr_name));
440
if (ioctl(interfaceSocket, OSIOCGIFADDR, (caddr_t)&ifr) < 0) {
441
Com_Printf("NET_GetLocalAddress: Unable to get local address "
442
"for interface '%s', errno = %d\n", inetInterface->ifr_name, errno);
444
struct sockaddr_in *sin;
447
sin = (struct sockaddr_in *)&ifr.ifr_addr;
449
ip = ntohl(sin->sin_addr.s_addr);
450
localIP[ numIP ][0] = (ip >> 24) & 0xff;
451
localIP[ numIP ][1] = (ip >> 16) & 0xff;
452
localIP[ numIP ][2] = (ip >> 8) & 0xff;
453
localIP[ numIP ][3] = (ip >> 0) & 0xff;
454
Com_Printf( "IP: %i.%i.%i.%i (%s)\n",
455
localIP[ numIP ][0], localIP[ numIP ][1],
456
localIP[ numIP ][2], localIP[ numIP ][3],
457
inetInterface->ifr_name);
462
// We will assume that there is only one AF_INET entry per AF_LINK entry.
463
// What happens when we have an interface that has multiple IP addresses, or
464
// can that even happen?
467
inetInterface = IFR_NEXT(inetInterface);
470
linkInterface = IFR_NEXT(linkInterface);
472
Com_Printf("NET_GetLocalAddress: DONE querying for network interfaces\n");
474
close(interfaceSocket);
478
void NET_GetLocalAddress( void ) {
480
struct hostent *hostInfo;
481
// int error; // bk001204 - unused
486
if ( gethostname( hostname, 256 ) == -1 ) {
490
hostInfo = gethostbyname( hostname );
495
Com_Printf( "Hostname: %s\n", hostInfo->h_name );
497
while( ( p = hostInfo->h_aliases[n++] ) != NULL ) {
498
Com_Printf( "Alias: %s\n", p );
501
if ( hostInfo->h_addrtype != AF_INET ) {
506
while( ( p = hostInfo->h_addr_list[numIP++] ) != NULL && numIP < MAX_IPS ) {
507
ip = ntohl( *(int *)p );
508
localIP[ numIP ][0] = p[0];
509
localIP[ numIP ][1] = p[1];
510
localIP[ numIP ][2] = p[2];
511
localIP[ numIP ][3] = p[3];
512
Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff );
522
// bk001204 - prototype needed
523
int NET_IPSocket (char *net_interface, int port);
524
void NET_OpenIP (void)
530
ip = Cvar_Get ("net_ip", "localhost", 0);
532
port = Cvar_Get("net_port", va("%i", PORT_SERVER), 0)->value;
534
for ( i = 0 ; i < 10 ; i++ ) {
535
ip_socket = NET_IPSocket (ip->string, port + i);
537
Cvar_SetValue( "net_port", port + i );
538
NET_GetLocalAddress();
542
Com_Error (ERR_FATAL, "Couldn't allocate IP port");
553
noudp = Cvar_Get ("net_noudp", "0", 0);
555
if (! noudp->value) {
566
int NET_IPSocket (char *net_interface, int port)
569
struct sockaddr_in address;
570
qboolean _qtrue = qtrue;
573
if ( net_interface ) {
574
Com_Printf("Opening IP socket: %s:%i\n", net_interface, port );
576
Com_Printf("Opening IP socket: localhost:%i\n", port );
579
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
581
Com_Printf ("ERROR: UDP_OpenSocket: socket: %s", NET_ErrorString());
585
// make it non-blocking
586
if (ioctl (newsocket, FIONBIO, &_qtrue) == -1)
588
Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString());
592
// make it broadcast capable
593
if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
595
Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString());
599
if (!net_interface || !net_interface[0] || !Q_stricmp(net_interface, "localhost"))
600
address.sin_addr.s_addr = INADDR_ANY;
602
Sys_StringToSockaddr (net_interface, (struct sockaddr *)&address);
604
if (port == PORT_ANY)
605
address.sin_port = 0;
607
address.sin_port = htons((short)port);
609
address.sin_family = AF_INET;
611
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
613
Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString());
626
void NET_Shutdown (void)
640
char *NET_ErrorString (void)
645
return strerror (code);
648
// sleeps msec or until net socket is ready
649
void NET_Sleep(int msec)
651
struct timeval timeout;
653
extern qboolean stdin_active;
656
if (!com_dedicated->integer)
657
return; // we're not a server, just run full speed
662
FD_SET(0, &fdset); // stdin is processed too
667
FD_SET(ip_socket, &fdset); // network socket
668
if(ip_socket >= highestfd)
669
highestfd = ip_socket + 1;
676
timeout.tv_sec = msec/1000;
677
timeout.tv_usec = (msec%1000)*1000;
678
select(highestfd, &fdset, NULL, NULL, &timeout);
682
// Block indefinitely
683
select(highestfd, &fdset, NULL, NULL, NULL);