summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c179
1 files changed, 139 insertions, 40 deletions
diff --git a/opentracker.c b/opentracker.c
index fda914a..b7431d4 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -8,12 +8,14 @@
8#include <string.h> 8#include <string.h>
9#include <sys/types.h> 9#include <sys/types.h>
10#include <sys/socket.h> 10#include <sys/socket.h>
11#include <arpa/inet.h>
11#include <unistd.h> 12#include <unistd.h>
12#include <stdlib.h> 13#include <stdlib.h>
13#include <errno.h> 14#include <errno.h>
14#include <signal.h> 15#include <signal.h>
15#include <stdio.h> 16#include <stdio.h>
16#include <pwd.h> 17#include <pwd.h>
18#include <ctype.h>
17#include <arpa/inet.h> 19#include <arpa/inet.h>
18 20
19/* Libowfat */ 21/* Libowfat */
@@ -21,6 +23,7 @@
21#include "io.h" 23#include "io.h"
22#include "iob.h" 24#include "iob.h"
23#include "array.h" 25#include "array.h"
26#include "byte.h"
24#include "fmt.h" 27#include "fmt.h"
25#include "scan.h" 28#include "scan.h"
26#include "ip4.h" 29#include "ip4.h"
@@ -34,17 +37,18 @@
34#include "ot_clean.h" 37#include "ot_clean.h"
35#include "ot_accesslist.h" 38#include "ot_accesslist.h"
36#include "ot_stats.h" 39#include "ot_stats.h"
40#include "ot_livesync.h"
37 41
38/* Globals */ 42/* Globals */
39time_t g_now; 43time_t g_now;
40char * g_redirecturl = NULL; 44char * g_redirecturl = NULL;
45uint32_t g_tracker_id;
46
47static char * g_serverdir = NULL;
41 48
42/* To always have space for error messages ;) */ 49/* To always have space for error messages ;) */
43static char static_inbuf[8192]; 50static char static_inbuf[8192];
44 51
45static char *FLAG_TCP = "T";
46static char *FLAG_UDP = "U";
47
48static void panic( const char *routine ) { 52static void panic( const char *routine ) {
49 fprintf( stderr, "%s: %s\n", routine, strerror(errno) ); 53 fprintf( stderr, "%s: %s\n", routine, strerror(errno) );
50 exit( 111 ); 54 exit( 111 );
@@ -63,10 +67,10 @@ static void signal_handler( int s ) {
63} 67}
64 68
65static void usage( char *name ) { 69static void usage( char *name ) {
66 fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-A ip]" 70 fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-A ip] [-f config] [-s livesyncport]"
67#ifdef WANT_BLACKLISTING 71#ifdef WANT_ACCESSLIST_BLACK
68 " [-b blacklistfile]" 72 " [-b blacklistfile]"
69#elif defined ( WANT_CLOSED_TRACKER ) 73#elif defined ( WANT_ACCESSLIST_WHITE )
70 " [-w whitelistfile]" 74 " [-w whitelistfile]"
71#endif 75#endif
72 "\n", name ); 76 "\n", name );
@@ -82,9 +86,9 @@ static void help( char *name ) {
82 HELPLINE("-r redirecturl","specify url where / should be redirected to (default none)"); 86 HELPLINE("-r redirecturl","specify url where / should be redirected to (default none)");
83 HELPLINE("-d dir","specify directory to try to chroot to (default: \".\")"); 87 HELPLINE("-d dir","specify directory to try to chroot to (default: \".\")");
84 HELPLINE("-A ip","bless an ip address as admin address (e.g. to allow syncs from this address)"); 88 HELPLINE("-A ip","bless an ip address as admin address (e.g. to allow syncs from this address)");
85#ifdef WANT_BLACKLISTING 89#ifdef WANT_ACCESSLIST_BLACK
86 HELPLINE("-b file","specify blacklist file."); 90 HELPLINE("-b file","specify blacklist file.");
87#elif defined( WANT_CLOSED_TRACKER ) 91#elif defined( WANT_ACCESSLIST_WHITE )
88 HELPLINE("-w file","specify whitelist file."); 92 HELPLINE("-w file","specify whitelist file.");
89#endif 93#endif
90 94
@@ -168,7 +172,7 @@ static void handle_accept( const int64 serversocket ) {
168 memset( h, 0, sizeof( struct http_data ) ); 172 memset( h, 0, sizeof( struct http_data ) );
169 memmove( h->ip, ip, sizeof( ip ) ); 173 memmove( h->ip, ip, sizeof( ip ) );
170 174
171 stats_issue_event( EVENT_ACCEPT, 1, ntohl(*(uint32_t*)ip)); 175 stats_issue_event( EVENT_ACCEPT, FLAG_TCP, ntohl(*(uint32_t*)ip));
172 176
173 /* That breaks taia encapsulation. But there is no way to take system 177 /* That breaks taia encapsulation. But there is no way to take system
174 time this often in FreeBSD and libowfat does not allow to set unix time */ 178 time this often in FreeBSD and libowfat does not allow to set unix time */
@@ -194,10 +198,12 @@ static void server_mainloop( ) {
194 198
195 while( ( i = io_canread( ) ) != -1 ) { 199 while( ( i = io_canread( ) ) != -1 ) {
196 const void *cookie = io_getcookie( i ); 200 const void *cookie = io_getcookie( i );
197 if( cookie == FLAG_TCP ) 201 if( (int)cookie == FLAG_TCP )
198 handle_accept( i ); 202 handle_accept( i );
199 else if( cookie == FLAG_UDP ) 203 else if( (int)cookie == FLAG_UDP )
200 handle_udp4( i ); 204 handle_udp4( i );
205 else if( (int)cookie == FLAG_MCA )
206 handle_livesync(i);
201 else 207 else
202 handle_read( i ); 208 handle_read( i );
203 } 209 }
@@ -214,6 +220,8 @@ static void server_mainloop( ) {
214 next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL; 220 next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
215 } 221 }
216 222
223 livesync_ticker();
224
217 /* See if we need to move our pools */ 225 /* See if we need to move our pools */
218 if( NOW != ot_last_clean_time ) { 226 if( NOW != ot_last_clean_time ) {
219 ot_last_clean_time = NOW; 227 ot_last_clean_time = NOW;
@@ -225,55 +233,148 @@ static void server_mainloop( ) {
225 } 233 }
226} 234}
227 235
228static void ot_try_bind( char ip[4], uint16 port, int is_tcp ) { 236int64_t ot_try_bind( char ip[4], uint16_t port, PROTO_FLAG proto ) {
229 int64 s = is_tcp ? socket_tcp4( ) : socket_udp4(); 237 int64 s = proto == FLAG_TCP ? socket_tcp4( ) : socket_udp4();
230 238
231 if( socket_bind4_reuse( s, ip, port ) == -1 ) 239 if( socket_bind4_reuse( s, ip, port ) == -1 )
232 panic( "socket_bind4_reuse" ); 240 panic( "socket_bind4_reuse" );
233 241
234 if( is_tcp && ( socket_listen( s, SOMAXCONN) == -1 ) ) 242 if( ( proto == FLAG_TCP ) && ( socket_listen( s, SOMAXCONN) == -1 ) )
235 panic( "socket_listen" ); 243 panic( "socket_listen" );
236 244
237 if( !io_fd( s ) ) 245 if( !io_fd( s ) )
238 panic( "io_fd" ); 246 panic( "io_fd" );
239 247
240 io_setcookie( s, is_tcp ? FLAG_TCP : FLAG_UDP ); 248 io_setcookie( s, (void*)proto );
241 249
242 io_wantread( s ); 250 io_wantread( s );
251
252 return s;
253}
254
255char * set_config_option( char **option, char *value ) {
256 while( isspace(*value) ) ++value;
257 if( *option ) free( *option );
258 return *option = strdup( value );
259}
260
261/* WARNING! Does not behave like scan_ip4 regarding return values */
262static int scan_ip4_port( const char *src, char *ip, uint16 *port ) {
263 int off;
264 while( isspace(*src) ) ++src;
265 if( !(off = scan_ip4( src, ip ) ) )
266 return -1;
267 src += off;
268 if( *src == 0 ) return 0;
269 if( *src != ':' )
270 return -1;
271 *port = atol(src+1);
272 return 0;
273}
274
275int parse_configfile( char * config_filename ) {
276 FILE * accesslist_filehandle;
277 char inbuf[512], tmpip[4];
278 int bound = 0;
279
280 accesslist_filehandle = fopen( config_filename, "r" );
281
282 if( accesslist_filehandle == NULL ) {
283 fprintf( stderr, "Warning: Can't open config file: %s.", config_filename );
284 return 0;
285 }
286
287 while( fgets( inbuf, sizeof(inbuf), accesslist_filehandle ) ) {
288 char *newl;
289 char *p = inbuf;
290
291 /* Skip white spaces */
292 while(isspace(*p)) ++p;
293
294 /* Ignore comments and empty lines */
295 if((*p=='#')||(*p=='\n')||(*p==0)) continue;
296
297 /* chomp */
298 if(( newl = strchr(p, '\n' ))) *newl = 0;
299
300 /* Scan for commands */
301 if(!byte_diff(p,15,"tracker.rootdir" ) && isspace(p[15])) {
302 set_config_option( &g_serverdir, p+16 );
303 } else if(!byte_diff(p,10,"listen.tcp" ) && isspace(p[10])) {
304 uint16_t tmpport = 6969;
305 if( scan_ip4_port( p+11, tmpip, &tmpport )) goto parse_error;
306 ot_try_bind( tmpip, tmpport, FLAG_TCP );
307 ++bound;
308 } else if(!byte_diff(p, 10, "listen.udp" ) && isspace(p[10])) {
309 uint16_t tmpport = 6969;
310 if( scan_ip4_port( p+11, tmpip, &tmpport )) goto parse_error;
311 ot_try_bind( tmpip, tmpport, FLAG_UDP );
312 ++bound;
313#ifdef WANT_ACCESSLIST_BLACK
314 } else if(!byte_diff(p, 16, "access.whitelist" ) && isspace(p[16])) {
315 set_config_option( &g_accesslist_filename, p+17 );
316#elif defined( WANT_ACCESSLIST_WHITE )
317 } else if(!byte_diff(p, 16, "access.blacklist" ) && isspace(p[16])) {
318 set_config_option( &g_accesslist_filename, p+17 );
319#endif
320 } else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) {
321 set_config_option( &g_redirecturl, p+21 );
322#ifdef WANT_SYNC_BATCH
323 } else if(!byte_diff(p, 26, "batchsync.cluster.admin_ip" ) && isspace(p[26])) {
324 if(!scan_ip4( p+27, tmpip )) goto parse_error;
325 accesslist_blessip( tmpip, OT_PERMISSION_MAY_SYNC );
326#endif
327#ifdef WANT_SYNC_LIVE
328 } else if(!byte_diff(p, 24, "livesync.cluster.node_ip" ) && isspace(p[24])) {
329 if( !scan_ip4( p+25, tmpip )) goto parse_error;
330 accesslist_blessip( tmpip, OT_PERMISSION_MAY_LIVESYNC );
331 } else if(!byte_diff(p, 23, "livesync.cluster.listen" ) && isspace(p[23])) {
332 uint16_t tmpport = LIVESYNC_PORT;
333 if( scan_ip4_port( p+24, tmpip, &tmpport )) goto parse_error;
334 livesync_bind_mcast( tmpip, tmpport );
335#endif
336 } else
337 fprintf( stderr, "Unhandled line in config file: %s\n", inbuf );
338 continue;
339 parse_error:
340 fprintf( stderr, "Parse error in config file: %s\n", inbuf);
341 }
342 fclose( accesslist_filehandle );
343 return bound;
243} 344}
244 345
245int main( int argc, char **argv ) { 346int main( int argc, char **argv ) {
246 struct passwd *pws = NULL; 347 struct passwd *pws = NULL;
247 char serverip[4] = {0,0,0,0}, tmpip[4]; 348 char serverip[4] = {0,0,0,0}, tmpip[4];
248 char *serverdir = ".";
249 int bound = 0, scanon = 1; 349 int bound = 0, scanon = 1;
250#ifdef WANT_ACCESS_CONTROL 350
251 char *accesslist_filename = NULL; 351while( scanon ) {
252#endif 352 switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:v"
253 353#ifdef WANT_ACCESSLIST_BLACK
254 while( scanon ) {
255 switch( getopt( argc, argv, ":i:p:A:P:d:r:v"
256#ifdef WANT_BLACKLISTING
257"b:" 354"b:"
258#elif defined( WANT_CLOSED_TRACKER ) 355#elif defined( WANT_ACCESSLIST_WHITE )
259"w:" 356"w:"
260#endif 357#endif
261 "h" ) ) { 358 "h" ) ) {
262 case -1 : scanon = 0; break; 359 case -1 : scanon = 0; break;
263 case 'i': scan_ip4( optarg, serverip ); break; 360 case 'i': scan_ip4( optarg, serverip ); break;
264#ifdef WANT_BLACKLISTING 361#ifdef WANT_ACCESSLIST_BLACK
265 case 'b': accesslist_filename = optarg; break; 362 case 'b': set_config_option( &g_accesslist_filename, optarg); break;
266#elif defined( WANT_CLOSED_TRACKER ) 363#elif defined( WANT_ACCESSLIST_WHITE )
267 case 'w': accesslist_filename = optarg; break; 364 case 'w': set_config_option( &g_accesslist_filename, optarg); break;
268#endif 365#endif
269 case 'p': ot_try_bind( serverip, (uint16)atol( optarg ), 1 ); bound++; break; 366 case 'p': ot_try_bind( serverip, (uint16)atol( optarg ), FLAG_TCP ); bound++; break;
270 case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), 0 ); bound++; break; 367 case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), FLAG_UDP ); bound++; break;
271 case 'd': serverdir = optarg; break; 368#ifdef WANT_SYNC_LIVE
272 case 'r': g_redirecturl = optarg; break; 369 case 's': livesync_bind_mcast( serverip, (uint16)atol( optarg )); break;
370#endif
371 case 'd': set_config_option( &g_serverdir, optarg ); break;
372 case 'r': set_config_option( &g_redirecturl, optarg ); break;
273 case 'A': 373 case 'A':
274 scan_ip4( optarg, tmpip ); 374 scan_ip4( optarg, tmpip );
275 accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */ 375 accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */
276 break; 376 break;
377 case 'f': bound += parse_configfile( optarg ); break;
277 case 'h': help( argv[0] ); exit( 0 ); 378 case 'h': help( argv[0] ); exit( 0 );
278 case 'v': write( 2, static_inbuf, stats_return_tracker_version( static_inbuf )); exit( 0 ); 379 case 'v': write( 2, static_inbuf, stats_return_tracker_version( static_inbuf )); exit( 0 );
279 default: 380 default:
@@ -283,8 +384,8 @@ int main( int argc, char **argv ) {
283 384
284 /* Bind to our default tcp/udp ports */ 385 /* Bind to our default tcp/udp ports */
285 if( !bound) { 386 if( !bound) {
286 ot_try_bind( serverip, 6969, 1 ); 387 ot_try_bind( serverip, 6969, FLAG_TCP );
287 ot_try_bind( serverip, 6969, 0 ); 388 ot_try_bind( serverip, 6969, FLAG_UDP );
288 } 389 }
289 390
290 /* Drop permissions */ 391 /* Drop permissions */
@@ -298,15 +399,13 @@ int main( int argc, char **argv ) {
298 } 399 }
299 endpwent(); 400 endpwent();
300 401
301 accesslist_init( accesslist_filename );
302
303 signal( SIGPIPE, SIG_IGN ); 402 signal( SIGPIPE, SIG_IGN );
304 signal( SIGINT, signal_handler ); 403 signal( SIGINT, signal_handler );
305 signal( SIGALRM, signal_handler ); 404 signal( SIGALRM, signal_handler );
306 405
307 g_now = time( NULL ); 406 g_now = time( NULL );
308 407
309 if( trackerlogic_init( serverdir ) == -1 ) 408 if( trackerlogic_init( g_serverdir ? g_serverdir : "." ) == -1 )
310 panic( "Logic not started" ); 409 panic( "Logic not started" );
311 410
312 alarm(5); 411 alarm(5);