|
|
@ -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,28 +152,28 @@ 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 ); |
|
|
|
|
|
|
|
|
|
|
|
if( !io_fd( i ) || |
|
|
|
if( !io_fd( i ) || |
|
|
|
!( h = (struct http_data*)malloc( sizeof( struct http_data ) ) ) ) { |
|
|
|
!( h = (struct http_data*)malloc( sizeof(struct http_data) ) ) ) { |
|
|
|
io_close( i ); |
|
|
|
io_close( i ); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
io_setcookie( i, h ); |
|
|
|
io_setcookie( i, h ); |
|
|
|
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; |
|
|
|