|
|
@ -22,7 +22,7 @@
|
|
|
|
#include "iob.h"
|
|
|
|
#include "iob.h"
|
|
|
|
#include "byte.h"
|
|
|
|
#include "byte.h"
|
|
|
|
#include "scan.h"
|
|
|
|
#include "scan.h"
|
|
|
|
#include "ip4.h"
|
|
|
|
#include "ip6.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* Opentracker */
|
|
|
|
/* Opentracker */
|
|
|
|
#include "trackerlogic.h"
|
|
|
|
#include "trackerlogic.h"
|
|
|
@ -108,7 +108,7 @@ static ssize_t handle_read( const int64 clientsocket, struct ot_workstruct *ws )
|
|
|
|
struct http_data* h = io_getcookie( clientsocket );
|
|
|
|
struct http_data* h = io_getcookie( clientsocket );
|
|
|
|
ssize_t l;
|
|
|
|
ssize_t l;
|
|
|
|
|
|
|
|
|
|
|
|
if( ( l = io_tryread( clientsocket, ws->inbuf, ws->inbuf_size ) ) <= 0 ) {
|
|
|
|
if( ( l = io_tryread( clientsocket, ws->inbuf, G_INBUF_SIZE ) ) <= 0 ) {
|
|
|
|
handle_dead( clientsocket );
|
|
|
|
handle_dead( clientsocket );
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -152,12 +152,12 @@ static void handle_write( const int64 clientsocket ) {
|
|
|
|
|
|
|
|
|
|
|
|
static void handle_accept( const int64 serversocket ) {
|
|
|
|
static void handle_accept( const int64 serversocket ) {
|
|
|
|
struct http_data *h;
|
|
|
|
struct http_data *h;
|
|
|
|
unsigned char ip[4];
|
|
|
|
ot_ip6 ip;
|
|
|
|
uint16 port;
|
|
|
|
uint16 port;
|
|
|
|
tai6464 t;
|
|
|
|
tai6464 t;
|
|
|
|
int64 i;
|
|
|
|
int64 i;
|
|
|
|
|
|
|
|
|
|
|
|
while( ( i = socket_accept4( serversocket, (char*)ip, &port) ) != -1 ) {
|
|
|
|
while( ( i = socket_accept6( serversocket, ip, &port, NULL ) ) != -1 ) {
|
|
|
|
|
|
|
|
|
|
|
|
/* Put fd into a non-blocking mode */
|
|
|
|
/* Put fd into a non-blocking mode */
|
|
|
|
io_nonblock( i );
|
|
|
|
io_nonblock( i );
|
|
|
@ -171,9 +171,9 @@ static void handle_accept( const int64 serversocket ) {
|
|
|
|
io_wantread( i );
|
|
|
|
io_wantread( i );
|
|
|
|
|
|
|
|
|
|
|
|
memset(h, 0, sizeof( struct http_data ) );
|
|
|
|
memset(h, 0, sizeof( struct http_data ) );
|
|
|
|
WRITE32(h->ip,0,READ32(ip,0));
|
|
|
|
memcpy(h->ip,ip,sizeof(ot_ip6));
|
|
|
|
|
|
|
|
|
|
|
|
stats_issue_event( EVENT_ACCEPT, FLAG_TCP, ntohl(*(uint32_t*)ip));
|
|
|
|
stats_issue_event( EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip);
|
|
|
|
|
|
|
|
|
|
|
|
/* That breaks taia encapsulation. But there is no way to take system
|
|
|
|
/* That breaks taia encapsulation. But there is no way to take system
|
|
|
|
time this often in FreeBSD and libowfat does not allow to set unix time */
|
|
|
|
time this often in FreeBSD and libowfat does not allow to set unix time */
|
|
|
@ -193,20 +193,14 @@ static void server_mainloop( ) {
|
|
|
|
int iovec_entries;
|
|
|
|
int iovec_entries;
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialize our "thread local storage" */
|
|
|
|
/* Initialize our "thread local storage" */
|
|
|
|
ws.inbuf = malloc( THREAD_INBUF_SIZE );
|
|
|
|
ws.inbuf = malloc( G_INBUF_SIZE );
|
|
|
|
ws.outbuf = malloc( THREAD_OUTBUF_SIZE );
|
|
|
|
ws.outbuf = malloc( G_OUTBUF_SIZE );
|
|
|
|
#ifdef _DEBUG_HTTPERROR
|
|
|
|
#ifdef _DEBUG_HTTPERROR
|
|
|
|
ws.debugbuf= malloc( THREAD_INBUF_SIZE );
|
|
|
|
ws.debugbuf= malloc( G_INBUF_SIZE );
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
if( !ws.inbuf || !ws.outbuf )
|
|
|
|
if( !ws.inbuf || !ws.outbuf )
|
|
|
|
panic( "Initializing worker failed" );
|
|
|
|
panic( "Initializing worker failed" );
|
|
|
|
|
|
|
|
|
|
|
|
ws.inbuf_size = THREAD_INBUF_SIZE;
|
|
|
|
|
|
|
|
ws.outbuf_size = THREAD_OUTBUF_SIZE;
|
|
|
|
|
|
|
|
#ifdef _DEBUG_HTTPERROR
|
|
|
|
|
|
|
|
ws.debugbuf_size= THREAD_INBUF_SIZE;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( ; ; ) {
|
|
|
|
for( ; ; ) {
|
|
|
|
int64 i;
|
|
|
|
int64 i;
|
|
|
|
|
|
|
|
|
|
|
@ -217,7 +211,7 @@ static void server_mainloop( ) {
|
|
|
|
if( (intptr_t)cookie == FLAG_TCP )
|
|
|
|
if( (intptr_t)cookie == FLAG_TCP )
|
|
|
|
handle_accept( i );
|
|
|
|
handle_accept( i );
|
|
|
|
else if( (intptr_t)cookie == FLAG_UDP )
|
|
|
|
else if( (intptr_t)cookie == FLAG_UDP )
|
|
|
|
handle_udp4( i, &ws );
|
|
|
|
handle_udp6( i, &ws );
|
|
|
|
else
|
|
|
|
else
|
|
|
|
handle_read( i, &ws );
|
|
|
|
handle_read( i, &ws );
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -241,17 +235,20 @@ static void server_mainloop( ) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int64_t ot_try_bind( char ip[4], uint16_t port, PROTO_FLAG proto ) {
|
|
|
|
static int64_t ot_try_bind( ot_ip6 ip, uint16_t port, PROTO_FLAG proto ) {
|
|
|
|
int64 s = proto == FLAG_TCP ? socket_tcp4( ) : socket_udp4( );
|
|
|
|
int64 s = proto == FLAG_TCP ? socket_tcp6( ) : socket_udp6( );
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#ifdef _DEBUG
|
|
|
|
char *protos[] = {"TCP","UDP","UDP mcast"};
|
|
|
|
char *protos[] = {"TCP","UDP","UDP mcast"};
|
|
|
|
uint8_t *_ip = (uint8_t *)ip;
|
|
|
|
char _debug[512];
|
|
|
|
fprintf( stderr, "Binding socket type %s to address %d.%d.%d.%d:%d...", protos[proto],_ip[0],_ip[1],_ip[2],_ip[3],port);
|
|
|
|
int off = snprintf( _debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto] );
|
|
|
|
|
|
|
|
off += fmt_ip6( _debug+off, ip);
|
|
|
|
|
|
|
|
off += snprintf( _debug + off, sizeof(_debug)-off, "]:%d...", port);
|
|
|
|
|
|
|
|
fputs( _debug, stderr );
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if( socket_bind4_reuse( s, ip, port ) == -1 )
|
|
|
|
if( socket_bind6_reuse( s, ip, port, 0 ) == -1 )
|
|
|
|
panic( "socket_bind4_reuse" );
|
|
|
|
panic( "socket_bind6_reuse" );
|
|
|
|
|
|
|
|
|
|
|
|
if( ( proto == FLAG_TCP ) && ( socket_listen( s, SOMAXCONN) == -1 ) )
|
|
|
|
if( ( proto == FLAG_TCP ) && ( socket_listen( s, SOMAXCONN) == -1 ) )
|
|
|
|
panic( "socket_listen" );
|
|
|
|
panic( "socket_listen" );
|
|
|
@ -279,16 +276,22 @@ char * set_config_option( char **option, char *value ) {
|
|
|
|
return *option = strdup( value );
|
|
|
|
return *option = strdup( value );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int scan_ip4_port( const char *src, char *ip, uint16 *port ) {
|
|
|
|
static int scan_ip6_port( const char *src, ot_ip6 ip, uint16 *port ) {
|
|
|
|
const char *s = src;
|
|
|
|
const char *s = src;
|
|
|
|
int off;
|
|
|
|
int off, bracket = 0;
|
|
|
|
while( isspace(*s) ) ++s;
|
|
|
|
while( isspace(*s) ) ++s;
|
|
|
|
if( !(off = scan_ip4( s, ip ) ) )
|
|
|
|
if( *s == '[' ) ++s, ++bracket; /* for v6 style notation */
|
|
|
|
|
|
|
|
if( !(off = scan_ip6( s, ip ) ) )
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
s += off;
|
|
|
|
s += off;
|
|
|
|
if( *s == 0 || isspace(*s)) return s-src;
|
|
|
|
if( *s == 0 || isspace(*s)) return s-src;
|
|
|
|
if( *(s++) != ':' )
|
|
|
|
if( *s == ']' && bracket ) ++s;
|
|
|
|
return 0;
|
|
|
|
if( !ip6_isv4mapped(ip)){
|
|
|
|
|
|
|
|
if( ( bracket && *(s) != ':' ) || ( *(s) != '.' ) ) return 0;
|
|
|
|
|
|
|
|
s++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if( *(s++) != ':' ) return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
if( !(off = scan_ushort (s, port ) ) )
|
|
|
|
if( !(off = scan_ushort (s, port ) ) )
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
return off+s-src;
|
|
|
|
return off+s-src;
|
|
|
@ -296,7 +299,8 @@ static int scan_ip4_port( const char *src, char *ip, uint16 *port ) {
|
|
|
|
|
|
|
|
|
|
|
|
int parse_configfile( char * config_filename ) {
|
|
|
|
int parse_configfile( char * config_filename ) {
|
|
|
|
FILE * accesslist_filehandle;
|
|
|
|
FILE * accesslist_filehandle;
|
|
|
|
char inbuf[512], tmpip[4];
|
|
|
|
char inbuf[512];
|
|
|
|
|
|
|
|
ot_ip6 tmpip;
|
|
|
|
int bound = 0;
|
|
|
|
int bound = 0;
|
|
|
|
|
|
|
|
|
|
|
|
accesslist_filehandle = fopen( config_filename, "r" );
|
|
|
|
accesslist_filehandle = fopen( config_filename, "r" );
|
|
|
@ -324,17 +328,17 @@ int parse_configfile( char * config_filename ) {
|
|
|
|
set_config_option( &g_serverdir, p+16 );
|
|
|
|
set_config_option( &g_serverdir, p+16 );
|
|
|
|
} else if(!byte_diff(p,14,"listen.tcp_udp" ) && isspace(p[14])) {
|
|
|
|
} else if(!byte_diff(p,14,"listen.tcp_udp" ) && isspace(p[14])) {
|
|
|
|
uint16_t tmpport = 6969;
|
|
|
|
uint16_t tmpport = 6969;
|
|
|
|
if( !scan_ip4_port( p+15, tmpip, &tmpport )) goto parse_error;
|
|
|
|
if( !scan_ip6_port( p+15, tmpip, &tmpport )) goto parse_error;
|
|
|
|
ot_try_bind( tmpip, tmpport, FLAG_TCP ); ++bound;
|
|
|
|
ot_try_bind( tmpip, tmpport, FLAG_TCP ); ++bound;
|
|
|
|
ot_try_bind( tmpip, tmpport, FLAG_UDP ); ++bound;
|
|
|
|
ot_try_bind( tmpip, tmpport, FLAG_UDP ); ++bound;
|
|
|
|
} else if(!byte_diff(p,10,"listen.tcp" ) && isspace(p[10])) {
|
|
|
|
} else if(!byte_diff(p,10,"listen.tcp" ) && isspace(p[10])) {
|
|
|
|
uint16_t tmpport = 6969;
|
|
|
|
uint16_t tmpport = 6969;
|
|
|
|
if( !scan_ip4_port( p+11, tmpip, &tmpport )) goto parse_error;
|
|
|
|
if( !scan_ip6_port( p+11, tmpip, &tmpport )) goto parse_error;
|
|
|
|
ot_try_bind( tmpip, tmpport, FLAG_TCP );
|
|
|
|
ot_try_bind( tmpip, tmpport, FLAG_TCP );
|
|
|
|
++bound;
|
|
|
|
++bound;
|
|
|
|
} else if(!byte_diff(p, 10, "listen.udp" ) && isspace(p[10])) {
|
|
|
|
} else if(!byte_diff(p, 10, "listen.udp" ) && isspace(p[10])) {
|
|
|
|
uint16_t tmpport = 6969;
|
|
|
|
uint16_t tmpport = 6969;
|
|
|
|
if( !scan_ip4_port( p+11, tmpip, &tmpport )) goto parse_error;
|
|
|
|
if( !scan_ip6_port( p+11, tmpip, &tmpport )) goto parse_error;
|
|
|
|
ot_try_bind( tmpip, tmpport, FLAG_UDP );
|
|
|
|
ot_try_bind( tmpip, tmpport, FLAG_UDP );
|
|
|
|
++bound;
|
|
|
|
++bound;
|
|
|
|
#ifdef WANT_ACCESSLIST_WHITE
|
|
|
|
#ifdef WANT_ACCESSLIST_WHITE
|
|
|
@ -346,18 +350,18 @@ int parse_configfile( char * config_filename ) {
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef WANT_RESTRICT_STATS
|
|
|
|
#ifdef WANT_RESTRICT_STATS
|
|
|
|
} else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) {
|
|
|
|
} else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) {
|
|
|
|
if( !scan_ip4( p+13, tmpip )) goto parse_error;
|
|
|
|
if( !scan_ip6( p+13, tmpip )) goto parse_error;
|
|
|
|
accesslist_blessip( tmpip, OT_PERMISSION_MAY_STAT );
|
|
|
|
accesslist_blessip( tmpip, OT_PERMISSION_MAY_STAT );
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
} else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) {
|
|
|
|
} else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) {
|
|
|
|
set_config_option( &g_redirecturl, p+21 );
|
|
|
|
set_config_option( &g_redirecturl, p+21 );
|
|
|
|
#ifdef WANT_SYNC_LIVE
|
|
|
|
#ifdef WANT_SYNC_LIVE
|
|
|
|
} else if(!byte_diff(p, 24, "livesync.cluster.node_ip" ) && isspace(p[24])) {
|
|
|
|
} else if(!byte_diff(p, 24, "livesync.cluster.node_ip" ) && isspace(p[24])) {
|
|
|
|
if( !scan_ip4( p+25, tmpip )) goto parse_error;
|
|
|
|
if( !scan_ip6( p+25, tmpip )) goto parse_error;
|
|
|
|
accesslist_blessip( tmpip, OT_PERMISSION_MAY_LIVESYNC );
|
|
|
|
accesslist_blessip( tmpip, OT_PERMISSION_MAY_LIVESYNC );
|
|
|
|
} else if(!byte_diff(p, 23, "livesync.cluster.listen" ) && isspace(p[23])) {
|
|
|
|
} else if(!byte_diff(p, 23, "livesync.cluster.listen" ) && isspace(p[23])) {
|
|
|
|
uint16_t tmpport = LIVESYNC_PORT;
|
|
|
|
uint16_t tmpport = LIVESYNC_PORT;
|
|
|
|
if( !scan_ip4_port( p+24, tmpip, &tmpport )) goto parse_error;
|
|
|
|
if( !scan_ip6_port( p+24, tmpip, &tmpport )) goto parse_error;
|
|
|
|
livesync_bind_mcast( tmpip, tmpport );
|
|
|
|
livesync_bind_mcast( tmpip, tmpport );
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
} else
|
|
|
|
} else
|
|
|
@ -411,10 +415,12 @@ int drop_privileges (const char * const serverdir) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main( int argc, char **argv ) {
|
|
|
|
int main( int argc, char **argv ) {
|
|
|
|
char serverip[4] = {0,0,0,0}, tmpip[4];
|
|
|
|
ot_ip6 serverip, tmpip;
|
|
|
|
int bound = 0, scanon = 1;
|
|
|
|
int bound = 0, scanon = 1;
|
|
|
|
uint16_t tmpport;
|
|
|
|
uint16_t tmpport;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset( serverip, 0, sizeof(ot_ip6) );
|
|
|
|
|
|
|
|
|
|
|
|
while( scanon ) {
|
|
|
|
while( scanon ) {
|
|
|
|
switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:v"
|
|
|
|
switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:v"
|
|
|
|
#ifdef WANT_ACCESSLIST_BLACK
|
|
|
|
#ifdef WANT_ACCESSLIST_BLACK
|
|
|
@ -425,7 +431,7 @@ while( scanon ) {
|
|
|
|
"h" ) ) {
|
|
|
|
"h" ) ) {
|
|
|
|
case -1 : scanon = 0; break;
|
|
|
|
case -1 : scanon = 0; break;
|
|
|
|
case 'i':
|
|
|
|
case 'i':
|
|
|
|
if( !scan_ip4( optarg, serverip )) { usage( argv[0] ); exit( 1 ); }
|
|
|
|
if( !scan_ip6( optarg, serverip )) { usage( argv[0] ); exit( 1 ); }
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
#ifdef WANT_ACCESSLIST_BLACK
|
|
|
|
#ifdef WANT_ACCESSLIST_BLACK
|
|
|
|
case 'b': set_config_option( &g_accesslist_filename, optarg); break;
|
|
|
|
case 'b': set_config_option( &g_accesslist_filename, optarg); break;
|
|
|
@ -446,7 +452,7 @@ while( scanon ) {
|
|
|
|
case 'd': set_config_option( &g_serverdir, optarg ); break;
|
|
|
|
case 'd': set_config_option( &g_serverdir, optarg ); break;
|
|
|
|
case 'r': set_config_option( &g_redirecturl, optarg ); break;
|
|
|
|
case 'r': set_config_option( &g_redirecturl, optarg ); break;
|
|
|
|
case 'A':
|
|
|
|
case 'A':
|
|
|
|
if( !scan_ip4( optarg, tmpip )) { usage( argv[0] ); exit( 1 ); }
|
|
|
|
if( !scan_ip6( optarg, tmpip )) { usage( argv[0] ); exit( 1 ); }
|
|
|
|
accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */
|
|
|
|
accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case 'f': bound += parse_configfile( optarg ); break;
|
|
|
|
case 'f': bound += parse_configfile( optarg ); break;
|
|
|
|