An open and free bittorrent tracker https://erdgeist.org/gitweb/opentracker
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

668 lines
20 KiB

15 years ago
3 years ago
15 years ago
15 years ago
15 years ago
13 years ago
3 years ago
15 years ago
15 years ago
15 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
3 years ago
15 years ago
3 years ago
  1. /* This software was written by Dirk Engling <erdgeist@erdgeist.org>
  2. It is considered beerware. Prost. Skol. Cheers or whatever.
  3. Some of the stuff below is stolen from Fefes example libowfat httpd.
  4. $Id: opentracker.c,v 1.240 2018/01/29 17:43:33 erdgeist Exp $ */
  5. /* System */
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <arpa/inet.h>
  9. #include <sys/socket.h>
  10. #include <unistd.h>
  11. #include <errno.h>
  12. #include <signal.h>
  13. #include <stdio.h>
  14. #include <pwd.h>
  15. #include <ctype.h>
  16. #include <pthread.h>
  17. #ifdef WANT_SYSLOGS
  18. #include <syslog.h>
  19. #endif
  20. /* Libowfat */
  21. #include "socket.h"
  22. #include "io.h"
  23. #include "iob.h"
  24. #include "byte.h"
  25. #include "scan.h"
  26. #include "ip6.h"
  27. /* Opentracker */
  28. #include "trackerlogic.h"
  29. #include "ot_mutex.h"
  30. #include "ot_http.h"
  31. #include "ot_udp.h"
  32. #include "ot_accesslist.h"
  33. #include "ot_stats.h"
  34. #include "ot_livesync.h"
  35. /* Globals */
  36. time_t g_now_seconds;
  37. char * g_redirecturl;
  38. uint32_t g_tracker_id;
  39. volatile int g_opentracker_running = 1;
  40. int g_self_pipe[2];
  41. static char * g_serverdir;
  42. static char * g_serveruser;
  43. static unsigned int g_udp_workers;
  44. static void panic( const char *routing ) __attribute__ ((noreturn));
  45. static void panic( const char *routine ) {
  46. fprintf( stderr, "%s: %s\n", routine, strerror(errno) );
  47. exit( 111 );
  48. }
  49. static void signal_handler( int s ) {
  50. if( s == SIGINT ) {
  51. /* Any new interrupt signal quits the application */
  52. signal( SIGINT, SIG_DFL);
  53. /* Tell all other threads to not acquire any new lock on a bucket
  54. but cancel their operations and return */
  55. g_opentracker_running = 0;
  56. trackerlogic_deinit();
  57. #ifdef WANT_SYSLOGS
  58. closelog();
  59. #endif
  60. exit( 0 );
  61. } else if( s == SIGALRM ) {
  62. /* Maintain our copy of the clock. time() on BSDs is very expensive. */
  63. g_now_seconds = time(NULL);
  64. alarm(5);
  65. }
  66. }
  67. static void defaul_signal_handlers( void ) {
  68. sigset_t signal_mask;
  69. sigemptyset(&signal_mask);
  70. sigaddset (&signal_mask, SIGPIPE);
  71. sigaddset (&signal_mask, SIGHUP);
  72. sigaddset (&signal_mask, SIGINT);
  73. sigaddset (&signal_mask, SIGALRM);
  74. pthread_sigmask (SIG_BLOCK, &signal_mask, NULL);
  75. }
  76. static void install_signal_handlers( void ) {
  77. struct sigaction sa;
  78. sigset_t signal_mask;
  79. sigemptyset(&signal_mask);
  80. sa.sa_handler = signal_handler;
  81. sigemptyset(&sa.sa_mask);
  82. sa.sa_flags = SA_RESTART;
  83. if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1) )
  84. panic( "install_signal_handlers" );
  85. sigaddset (&signal_mask, SIGINT);
  86. sigaddset (&signal_mask, SIGALRM);
  87. pthread_sigmask (SIG_UNBLOCK, &signal_mask, NULL);
  88. }
  89. static void usage( char *name ) {
  90. fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-u user] [-A ip] [-f config] [-s livesyncport]"
  91. #ifdef WANT_ACCESSLIST_BLACK
  92. " [-b blacklistfile]"
  93. #elif defined ( WANT_ACCESSLIST_WHITE )
  94. " [-w whitelistfile]"
  95. #endif
  96. "\n", name );
  97. }
  98. #define HELPLINE(opt,desc) fprintf(stderr, "\t%-10s%s\n",opt,desc)
  99. static void help( char *name ) {
  100. usage( name );
  101. HELPLINE("-f config","include and execute the config file");
  102. HELPLINE("-i ip","specify ip to bind to (default: *, you may specify more than one)");
  103. HELPLINE("-p port","specify tcp port to bind to (default: 6969, you may specify more than one)");
  104. HELPLINE("-P port","specify udp port to bind to (default: 6969, you may specify more than one)");
  105. HELPLINE("-r redirecturl","specify url where / should be redirected to (default none)");
  106. HELPLINE("-d dir","specify directory to try to chroot to (default: \".\")");
  107. HELPLINE("-u user","specify user under whose priviliges opentracker should run (default: \"nobody\")");
  108. HELPLINE("-A ip","bless an ip address as admin address (e.g. to allow syncs from this address)");
  109. #ifdef WANT_ACCESSLIST_BLACK
  110. HELPLINE("-b file","specify blacklist file.");
  111. #elif defined( WANT_ACCESSLIST_WHITE )
  112. HELPLINE("-w file","specify whitelist file.");
  113. #endif
  114. fprintf( stderr, "\nExample: ./opentracker -i 127.0.0.1 -p 6969 -P 6969 -f ./opentracker.conf -i 10.1.1.23 -p 2710 -p 80\n" );
  115. }
  116. #undef HELPLINE
  117. static size_t header_complete( char * request, ssize_t byte_count ) {
  118. int i = 0, state = 0;
  119. for( i=1; i < byte_count; i+=2 )
  120. if( request[i] <= 13 ) {
  121. i--;
  122. for( state = 0 ; i < byte_count; ++i ) {
  123. char c = request[i];
  124. if( c == '\r' || c == '\n' )
  125. state = ( state >> 2 ) | ( ( c << 6 ) & 0xc0 );
  126. else
  127. break;
  128. if( state >= 0xa0 || state == 0x99 ) return i + 1;
  129. }
  130. }
  131. return 0;
  132. }
  133. static void handle_dead( const int64 sock ) {
  134. struct http_data* cookie=io_getcookie( sock );
  135. if( cookie ) {
  136. iob_reset( &cookie->batch );
  137. array_reset( &cookie->request );
  138. if( cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK )
  139. mutex_workqueue_canceltask( sock );
  140. free( cookie );
  141. }
  142. io_close( sock );
  143. }
  144. static void handle_read( const int64 sock, struct ot_workstruct *ws ) {
  145. struct http_data* cookie = io_getcookie( sock );
  146. ssize_t byte_count;
  147. if( ( byte_count = io_tryread( sock, ws->inbuf, G_INBUF_SIZE ) ) <= 0 ) {
  148. handle_dead( sock );
  149. return;
  150. }
  151. /* If we get the whole request in one packet, handle it without copying */
  152. if( !array_start( &cookie->request ) ) {
  153. if( ( ws->header_size = header_complete( ws->inbuf, byte_count ) ) ) {
  154. ws->request = ws->inbuf;
  155. ws->request_size = byte_count;
  156. http_handle_request( sock, ws );
  157. } else
  158. array_catb( &cookie->request, ws->inbuf, byte_count );
  159. return;
  160. }
  161. array_catb( &cookie->request, ws->inbuf, byte_count );
  162. if( array_failed( &cookie->request ) || array_bytes( &cookie->request ) > 8192 ) {
  163. http_issue_error( sock, ws, CODE_HTTPERROR_500 );
  164. return;
  165. }
  166. while( ( ws->header_size = header_complete( array_start( &cookie->request ), array_bytes( &cookie->request ) ) ) ) {
  167. ws->request = array_start( &cookie->request );
  168. ws->request_size = array_bytes( &cookie->request );
  169. http_handle_request( sock, ws );
  170. #ifdef WANT_KEEPALIVE
  171. if( !ws->keep_alive )
  172. #endif
  173. return;
  174. }
  175. }
  176. static void handle_write( const int64 sock ) {
  177. struct http_data* cookie=io_getcookie( sock );
  178. if( !cookie || ( iob_send( sock, &cookie->batch ) <= 0 ) )
  179. handle_dead( sock );
  180. }
  181. static void handle_accept( const int64 serversocket ) {
  182. struct http_data *cookie;
  183. int64 sock;
  184. ot_ip6 ip;
  185. uint16 port;
  186. tai6464 t;
  187. while( ( sock = socket_accept6( serversocket, ip, &port, NULL ) ) != -1 ) {
  188. /* Put fd into a non-blocking mode */
  189. io_nonblock( sock );
  190. if( !io_fd( sock ) ||
  191. !( cookie = (struct http_data*)malloc( sizeof(struct http_data) ) ) ) {
  192. io_close( sock );
  193. continue;
  194. }
  195. memset(cookie, 0, sizeof( struct http_data ) );
  196. memcpy(cookie->ip,ip,sizeof(ot_ip6));
  197. io_setcookie( sock, cookie );
  198. io_wantread( sock );
  199. stats_issue_event( EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip);
  200. /* That breaks taia encapsulation. But there is no way to take system
  201. time this often in FreeBSD and libowfat does not allow to set unix time */
  202. taia_uint( &t, 0 ); /* Clear t */
  203. tai_unix( &(t.sec), (g_now_seconds + OT_CLIENT_TIMEOUT) );
  204. io_timeout( sock, t );
  205. }
  206. }
  207. static void * server_mainloop( void * args ) {
  208. struct ot_workstruct ws;
  209. time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
  210. struct iovec *iovector;
  211. int iovec_entries;
  212. (void)args;
  213. /* Initialize our "thread local storage" */
  214. ws.inbuf = malloc( G_INBUF_SIZE );
  215. ws.outbuf = malloc( G_OUTBUF_SIZE );
  216. #ifdef _DEBUG_HTTPERROR
  217. ws.debugbuf= malloc( G_DEBUGBUF_SIZE );
  218. #endif
  219. if( !ws.inbuf || !ws.outbuf )
  220. panic( "Initializing worker failed" );
  221. for( ; ; ) {
  222. int64 sock;
  223. io_wait();
  224. while( ( sock = io_canread( ) ) != -1 ) {
  225. const void *cookie = io_getcookie( sock );
  226. if( (intptr_t)cookie == FLAG_TCP )
  227. handle_accept( sock );
  228. else if( (intptr_t)cookie == FLAG_UDP )
  229. handle_udp6( sock, &ws );
  230. else if( (intptr_t)cookie == FLAG_SELFPIPE )
  231. io_tryread( sock, ws.inbuf, G_INBUF_SIZE );
  232. else
  233. handle_read( sock, &ws );
  234. }
  235. while( ( sock = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 )
  236. http_sendiovecdata( sock, &ws, iovec_entries, iovector );
  237. while( ( sock = io_canwrite( ) ) != -1 )
  238. handle_write( sock );
  239. if( g_now_seconds > next_timeout_check ) {
  240. while( ( sock = io_timeouted() ) != -1 )
  241. handle_dead( sock );
  242. next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
  243. }
  244. livesync_ticker();
  245. /* Enforce setting the clock */
  246. signal_handler( SIGALRM );
  247. }
  248. return 0;
  249. }
  250. static int64_t ot_try_bind( ot_ip6 ip, uint16_t port, PROTO_FLAG proto ) {
  251. int64 sock = proto == FLAG_TCP ? socket_tcp6( ) : socket_udp6( );
  252. #ifndef WANT_V6
  253. if( !ip6_isv4mapped(ip) ) {
  254. exerr( "V4 Tracker is V4 only!" );
  255. }
  256. #else
  257. if( ip6_isv4mapped(ip) ) {
  258. exerr( "V6 Tracker is V6 only!" );
  259. }
  260. #endif
  261. #ifdef _DEBUG
  262. {
  263. char *protos[] = {"TCP","UDP","UDP mcast"};
  264. char _debug[512];
  265. int off = snprintf( _debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto] );
  266. off += fmt_ip6c( _debug+off, ip);
  267. snprintf( _debug + off, sizeof(_debug)-off, "]:%d...", port);
  268. fputs( _debug, stderr );
  269. }
  270. #endif
  271. if( socket_bind6_reuse( sock, ip, port, 0 ) == -1 )
  272. panic( "socket_bind6_reuse" );
  273. if( ( proto == FLAG_TCP ) && ( socket_listen( sock, SOMAXCONN) == -1 ) )
  274. panic( "socket_listen" );
  275. if( !io_fd( sock ) )
  276. panic( "io_fd" );
  277. io_setcookie( sock, (void*)proto );
  278. if( (proto == FLAG_UDP) && g_udp_workers ) {
  279. io_block( sock );
  280. udp_init( sock, g_udp_workers );
  281. } else
  282. io_wantread( sock );
  283. #ifdef _DEBUG
  284. fputs( " success.\n", stderr);
  285. #endif
  286. return sock;
  287. }
  288. char * set_config_option( char **option, char *value ) {
  289. #ifdef _DEBUG
  290. fprintf( stderr, "Setting config option: %s\n", value );
  291. #endif
  292. while( isspace(*value) ) ++value;
  293. free( *option );
  294. return *option = strdup( value );
  295. }
  296. static int scan_ip6_port( const char *src, ot_ip6 ip, uint16 *port ) {
  297. const char *s = src;
  298. int off, bracket = 0;
  299. while( isspace(*s) ) ++s;
  300. if( *s == '[' ) ++s, ++bracket; /* for v6 style notation */
  301. if( !(off = scan_ip6( s, ip ) ) )
  302. return 0;
  303. s += off;
  304. if( bracket && *s == ']' ) ++s;
  305. if( *s == 0 || isspace(*s)) return s-src;
  306. if( !ip6_isv4mapped(ip)){
  307. if( *s != ':' && *s != '.' ) return 0;
  308. if( !bracket && *(s) == ':' ) return 0;
  309. s++;
  310. } else {
  311. if( *(s++) != ':' ) return 0;
  312. }
  313. if( !(off = scan_ushort (s, port ) ) )
  314. return 0;
  315. return off+s-src;
  316. }
  317. int parse_configfile( char * config_filename ) {
  318. FILE * accesslist_filehandle;
  319. char inbuf[512];
  320. ot_ip6 tmpip;
  321. int bound = 0;
  322. accesslist_filehandle = fopen( config_filename, "r" );
  323. if( accesslist_filehandle == NULL ) {
  324. fprintf( stderr, "Warning: Can't open config file: %s.", config_filename );
  325. return 0;
  326. }
  327. while( fgets( inbuf, sizeof(inbuf), accesslist_filehandle ) ) {
  328. char *p = inbuf;
  329. size_t strl;
  330. /* Skip white spaces */
  331. while(isspace(*p)) ++p;
  332. /* Ignore comments and empty lines */
  333. if((*p=='#')||(*p=='\n')||(*p==0)) continue;
  334. /* consume trailing new lines and spaces */
  335. strl = strlen(p);
  336. while( strl && isspace(p[strl-1]))
  337. p[--strl] = 0;
  338. /* Scan for commands */
  339. if(!byte_diff(p,15,"tracker.rootdir" ) && isspace(p[15])) {
  340. set_config_option( &g_serverdir, p+16 );
  341. } else if(!byte_diff(p,12,"tracker.user" ) && isspace(p[12])) {
  342. set_config_option( &g_serveruser, p+13 );
  343. } else if(!byte_diff(p,14,"listen.tcp_udp" ) && isspace(p[14])) {
  344. uint16_t tmpport = 6969;
  345. if( !scan_ip6_port( p+15, tmpip, &tmpport )) goto parse_error;
  346. ot_try_bind( tmpip, tmpport, FLAG_TCP ); ++bound;
  347. ot_try_bind( tmpip, tmpport, FLAG_UDP ); ++bound;
  348. } else if(!byte_diff(p,10,"listen.tcp" ) && isspace(p[10])) {
  349. uint16_t tmpport = 6969;
  350. if( !scan_ip6_port( p+11, tmpip, &tmpport )) goto parse_error;
  351. ot_try_bind( tmpip, tmpport, FLAG_TCP );
  352. ++bound;
  353. } else if(!byte_diff(p, 10, "listen.udp" ) && isspace(p[10])) {
  354. uint16_t tmpport = 6969;
  355. if( !scan_ip6_port( p+11, tmpip, &tmpport )) goto parse_error;
  356. ot_try_bind( tmpip, tmpport, FLAG_UDP );
  357. ++bound;
  358. } else if(!byte_diff(p,18,"listen.udp.workers" ) && isspace(p[18])) {
  359. char *value = p + 18;
  360. while( isspace(*value) ) ++value;
  361. scan_uint( value, &g_udp_workers );
  362. #ifdef WANT_ACCESSLIST_WHITE
  363. } else if(!byte_diff(p, 16, "access.whitelist" ) && isspace(p[16])) {
  364. set_config_option( &g_accesslist_filename, p+17 );
  365. #elif defined( WANT_ACCESSLIST_BLACK )
  366. } else if(!byte_diff(p, 16, "access.blacklist" ) && isspace(p[16])) {
  367. set_config_option( &g_accesslist_filename, p+17 );
  368. #endif
  369. #ifdef WANT_RESTRICT_STATS
  370. } else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) {
  371. if( !scan_ip6( p+13, tmpip )) goto parse_error;
  372. accesslist_blessip( tmpip, OT_PERMISSION_MAY_STAT );
  373. #endif
  374. } else if(!byte_diff(p, 17, "access.stats_path" ) && isspace(p[17])) {
  375. set_config_option( &g_stats_path, p+18 );
  376. #ifdef WANT_IP_FROM_PROXY
  377. } else if(!byte_diff(p, 12, "access.proxy" ) && isspace(p[12])) {
  378. if( !scan_ip6( p+13, tmpip )) goto parse_error;
  379. accesslist_blessip( tmpip, OT_PERMISSION_MAY_PROXY );
  380. #endif
  381. } else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) {
  382. set_config_option( &g_redirecturl, p+21 );
  383. #ifdef WANT_SYNC_LIVE
  384. } else if(!byte_diff(p, 24, "livesync.cluster.node_ip" ) && isspace(p[24])) {
  385. if( !scan_ip6( p+25, tmpip )) goto parse_error;
  386. accesslist_blessip( tmpip, OT_PERMISSION_MAY_LIVESYNC );
  387. } else if(!byte_diff(p, 23, "livesync.cluster.listen" ) && isspace(p[23])) {
  388. uint16_t tmpport = LIVESYNC_PORT;
  389. if( !scan_ip6_port( p+24, tmpip, &tmpport )) goto parse_error;
  390. livesync_bind_mcast( tmpip, tmpport );
  391. #endif
  392. } else
  393. fprintf( stderr, "Unhandled line in config file: %s\n", inbuf );
  394. continue;
  395. parse_error:
  396. fprintf( stderr, "Parse error in config file: %s\n", inbuf);
  397. }
  398. fclose( accesslist_filehandle );
  399. return bound;
  400. }
  401. void load_state(const char * const state_filename ) {
  402. FILE * state_filehandle;
  403. char inbuf[512];
  404. ot_hash infohash;
  405. unsigned long long base, downcount;
  406. int consumed;
  407. state_filehandle = fopen( state_filename, "r" );
  408. if( state_filehandle == NULL ) {
  409. fprintf( stderr, "Warning: Can't open config file: %s.", state_filename );
  410. return;
  411. }
  412. /* We do ignore anything that is not of the form "^[:xdigit:]:\d+:\d+" */
  413. while( fgets( inbuf, sizeof(inbuf), state_filehandle ) ) {
  414. int i;
  415. for( i=0; i<(int)sizeof(ot_hash); ++i ) {
  416. int eger = 16 * scan_fromhex( inbuf[ 2*i ] ) + scan_fromhex( inbuf[ 1 + 2*i ] );
  417. if( eger < 0 )
  418. continue;
  419. infohash[i] = eger;
  420. }
  421. if( i != (int)sizeof(ot_hash) ) continue;
  422. i *= 2;
  423. if( inbuf[ i++ ] != ':' || !( consumed = scan_ulonglong( inbuf+i, &base ) ) ) continue;
  424. i += consumed;
  425. if( inbuf[ i++ ] != ':' || !( consumed = scan_ulonglong( inbuf+i, &downcount ) ) ) continue;
  426. add_torrent_from_saved_state( infohash, base, downcount );
  427. }
  428. fclose( state_filehandle );
  429. }
  430. int drop_privileges ( const char * const serveruser, const char * const serverdir ) {
  431. struct passwd *pws = NULL;
  432. #ifdef _DEBUG
  433. if( !geteuid() )
  434. fprintf( stderr, "Dropping to user %s.\n", serveruser );
  435. if( serverdir )
  436. fprintf( stderr, "ch%s'ing to directory %s.\n", geteuid() ? "dir" : "root", serverdir );
  437. #endif
  438. /* Grab pws entry before chrooting */
  439. pws = getpwnam( serveruser );
  440. endpwent();
  441. if( geteuid() == 0 ) {
  442. /* Running as root: chroot and drop privileges */
  443. if( serverdir && chroot( serverdir ) ) {
  444. fprintf( stderr, "Could not chroot to %s, because: %s\n", serverdir, strerror(errno) );
  445. return -1;
  446. }
  447. if(chdir("/"))
  448. panic("chdir() failed after chrooting: ");
  449. /* If we can't find server user, revert to nobody's default uid */
  450. if( !pws ) {
  451. fprintf( stderr, "Warning: Could not get password entry for %s. Reverting to uid -2.\n", serveruser );
  452. setegid( (gid_t)-2 ); setgid( (gid_t)-2 );
  453. setuid( (uid_t)-2 ); seteuid( (uid_t)-2 );
  454. }
  455. else {
  456. setegid( pws->pw_gid ); setgid( pws->pw_gid );
  457. setuid( pws->pw_uid ); seteuid( pws->pw_uid );
  458. }
  459. if( geteuid() == 0 || getegid() == 0 )
  460. panic("Still running with root privileges?!");
  461. }
  462. else {
  463. /* Normal user, just chdir() */
  464. if( serverdir && chdir( serverdir ) ) {
  465. fprintf( stderr, "Could not chroot to %s, because: %s\n", serverdir, strerror(errno) );
  466. return -1;
  467. }
  468. }
  469. return 0;
  470. }
  471. int main( int argc, char **argv ) {
  472. ot_ip6 serverip, tmpip;
  473. int bound = 0, scanon = 1;
  474. uint16_t tmpport;
  475. char * statefile = 0;
  476. memset( serverip, 0, sizeof(ot_ip6) );
  477. #ifndef WANT_V6
  478. serverip[10]=serverip[11]=-1;
  479. noipv6=1;
  480. #endif
  481. #ifdef WANT_DEV_RANDOM
  482. srandomdev();
  483. #else
  484. srandom( time(NULL) );
  485. #endif
  486. while( scanon ) {
  487. switch( getopt( argc, argv, ":i:p:A:P:d:u:r:s:f:l:v"
  488. #ifdef WANT_ACCESSLIST_BLACK
  489. "b:"
  490. #elif defined( WANT_ACCESSLIST_WHITE )
  491. "w:"
  492. #endif
  493. "h" ) ) {
  494. case -1 : scanon = 0; break;
  495. case 'i':
  496. if( !scan_ip6( optarg, serverip )) { usage( argv[0] ); exit( 1 ); }
  497. break;
  498. #ifdef WANT_ACCESSLIST_BLACK
  499. case 'b': set_config_option( &g_accesslist_filename, optarg); break;
  500. #elif defined( WANT_ACCESSLIST_WHITE )
  501. case 'w': set_config_option( &g_accesslist_filename, optarg); break;
  502. #endif
  503. case 'p':
  504. if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); }
  505. ot_try_bind( serverip, tmpport, FLAG_TCP ); bound++; break;
  506. case 'P':
  507. if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); }
  508. ot_try_bind( serverip, tmpport, FLAG_UDP ); bound++; break;
  509. #ifdef WANT_SYNC_LIVE
  510. case 's':
  511. if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); }
  512. livesync_bind_mcast( serverip, tmpport); break;
  513. #endif
  514. case 'd': set_config_option( &g_serverdir, optarg ); break;
  515. case 'u': set_config_option( &g_serveruser, optarg ); break;
  516. case 'r': set_config_option( &g_redirecturl, optarg ); break;
  517. case 'l': statefile = optarg; break;
  518. case 'A':
  519. if( !scan_ip6( optarg, tmpip )) { usage( argv[0] ); exit( 1 ); }
  520. accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */
  521. break;
  522. case 'f': bound += parse_configfile( optarg ); break;
  523. case 'h': help( argv[0] ); exit( 0 );
  524. case 'v': {
  525. char buffer[8192];
  526. stats_return_tracker_version( buffer );
  527. fputs( buffer, stderr );
  528. exit( 0 );
  529. }
  530. default:
  531. case '?': usage( argv[0] ); exit( 1 );
  532. }
  533. }
  534. /* Bind to our default tcp/udp ports */
  535. if( !bound) {
  536. ot_try_bind( serverip, 6969, FLAG_TCP );
  537. ot_try_bind( serverip, 6969, FLAG_UDP );
  538. }
  539. #ifdef WANT_SYSLOGS
  540. openlog( "opentracker", 0, LOG_USER );
  541. setlogmask(LOG_UPTO(LOG_INFO));
  542. #endif
  543. if( drop_privileges( g_serveruser ? g_serveruser : "nobody", g_serverdir ) == -1 )
  544. panic( "drop_privileges failed, exiting. Last error");
  545. g_now_seconds = time( NULL );
  546. /* Create our self pipe which allows us to interrupt mainloops
  547. io_wait in case some data is available to send out */
  548. if( pipe( g_self_pipe ) == -1 )
  549. panic( "selfpipe failed: " );
  550. if( !io_fd( g_self_pipe[0] ) )
  551. panic( "selfpipe io_fd failed: " );
  552. if( !io_fd( g_self_pipe[1] ) )
  553. panic( "selfpipe io_fd failed: " );
  554. io_setcookie( g_self_pipe[0], (void*)FLAG_SELFPIPE );
  555. io_wantread( g_self_pipe[0] );
  556. defaul_signal_handlers( );
  557. /* Init all sub systems. This call may fail with an exit() */
  558. trackerlogic_init( );
  559. if( statefile )
  560. load_state( statefile );
  561. install_signal_handlers( );
  562. if( !g_udp_workers )
  563. udp_init( -1, 0 );
  564. /* Kick off our initial clock setting alarm */
  565. alarm(5);
  566. server_mainloop( 0 );
  567. return 0;
  568. }
  569. const char *g_version_opentracker_c = "$Source: /home/cvsroot/opentracker/opentracker.c,v $: $Revision: 1.240 $\n";