summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c829
1 files changed, 447 insertions, 382 deletions
diff --git a/opentracker.c b/opentracker.c
index a896762..392f6df 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -5,59 +5,59 @@
5 $Id$ */ 5 $Id$ */
6 6
7/* System */ 7/* System */
8#include <stdlib.h>
9#include <string.h>
10#include <arpa/inet.h> 8#include <arpa/inet.h>
11#include <sys/socket.h> 9#include <ctype.h>
12#include <unistd.h>
13#include <errno.h> 10#include <errno.h>
11#include <pthread.h>
12#include <pwd.h>
14#include <signal.h> 13#include <signal.h>
15#include <stdio.h> 14#include <stdio.h>
16#include <pwd.h> 15#include <stdlib.h>
17#include <ctype.h> 16#include <string.h>
18#include <pthread.h> 17#include <sys/socket.h>
18#include <unistd.h>
19#ifdef WANT_SYSLOGS 19#ifdef WANT_SYSLOGS
20#include <syslog.h> 20#include <syslog.h>
21#endif 21#endif
22 22
23/* Libowfat */ 23/* Libowfat */
24#include "socket.h" 24#include "byte.h"
25#include "io.h" 25#include "io.h"
26#include "iob.h" 26#include "iob.h"
27#include "byte.h"
28#include "scan.h"
29#include "ip6.h" 27#include "ip6.h"
28#include "scan.h"
29#include "socket.h"
30 30
31/* Opentracker */ 31/* Opentracker */
32#include "trackerlogic.h"
33#include "ot_mutex.h"
34#include "ot_http.h"
35#include "ot_udp.h"
36#include "ot_accesslist.h" 32#include "ot_accesslist.h"
37#include "ot_stats.h" 33#include "ot_http.h"
38#include "ot_livesync.h" 34#include "ot_livesync.h"
35#include "ot_mutex.h"
36#include "ot_stats.h"
37#include "ot_udp.h"
38#include "trackerlogic.h"
39 39
40/* Globals */ 40/* Globals */
41time_t g_now_seconds; 41time_t g_now_seconds;
42char * g_redirecturl; 42char *g_redirecturl;
43uint32_t g_tracker_id; 43uint32_t g_tracker_id;
44volatile int g_opentracker_running = 1; 44volatile int g_opentracker_running = 1;
45int g_self_pipe[2]; 45int g_self_pipe[2];
46 46
47static char * g_serverdir; 47static char *g_serverdir;
48static char * g_serveruser; 48static char *g_serveruser;
49static unsigned int g_udp_workers; 49static unsigned int g_udp_workers;
50 50
51static void panic( const char *routine ) __attribute__ ((noreturn)); 51static void panic(const char *routine) __attribute__((noreturn));
52static void panic( const char *routine ) { 52static void panic(const char *routine) {
53 fprintf( stderr, "%s: %s\n", routine, strerror(errno) ); 53 fprintf(stderr, "%s: %s\n", routine, strerror(errno));
54 exit( 111 ); 54 exit(111);
55} 55}
56 56
57static void signal_handler( int s ) { 57static void signal_handler(int s) {
58 if( s == SIGINT ) { 58 if (s == SIGINT) {
59 /* Any new interrupt signal quits the application */ 59 /* Any new interrupt signal quits the application */
60 signal( SIGINT, SIG_DFL); 60 signal(SIGINT, SIG_DFL);
61 61
62 /* Tell all other threads to not acquire any new lock on a bucket 62 /* Tell all other threads to not acquire any new lock on a bucket
63 but cancel their operations and return */ 63 but cancel their operations and return */
@@ -69,61 +69,63 @@ static void signal_handler( int s ) {
69 closelog(); 69 closelog();
70#endif 70#endif
71 71
72 exit( 0 ); 72 exit(0);
73 } 73 }
74} 74}
75 75
76static void defaul_signal_handlers( void ) { 76static void defaul_signal_handlers(void) {
77 sigset_t signal_mask; 77 sigset_t signal_mask;
78 sigemptyset(&signal_mask); 78 sigemptyset(&signal_mask);
79 sigaddset (&signal_mask, SIGPIPE); 79 sigaddset(&signal_mask, SIGPIPE);
80 sigaddset (&signal_mask, SIGHUP); 80 sigaddset(&signal_mask, SIGHUP);
81 sigaddset (&signal_mask, SIGINT); 81 sigaddset(&signal_mask, SIGINT);
82 sigaddset (&signal_mask, SIGALRM); 82 sigaddset(&signal_mask, SIGALRM);
83 pthread_sigmask (SIG_BLOCK, &signal_mask, NULL); 83 pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
84} 84}
85 85
86static void install_signal_handlers( void ) { 86static void install_signal_handlers(void) {
87 struct sigaction sa; 87 struct sigaction sa;
88 sigset_t signal_mask; 88 sigset_t signal_mask;
89 sigemptyset(&signal_mask); 89 sigemptyset(&signal_mask);
90 90
91 sa.sa_handler = signal_handler; 91 sa.sa_handler = signal_handler;
92 sigemptyset(&sa.sa_mask); 92 sigemptyset(&sa.sa_mask);
93 sa.sa_flags = SA_RESTART; 93 sa.sa_flags = SA_RESTART;
94 if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1) ) 94 if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1))
95 panic( "install_signal_handlers" ); 95 panic("install_signal_handlers");
96 96
97 sigaddset (&signal_mask, SIGINT); 97 sigaddset(&signal_mask, SIGINT);
98 pthread_sigmask (SIG_UNBLOCK, &signal_mask, NULL); 98 pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL);
99} 99}
100 100
101static void usage( char *name ) { 101static void usage(char *name) {
102 fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-u user] [-A ip[/bits]] [-f config] [-s livesyncport]" 102 fprintf(stderr,
103 "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-u user] [-A ip[/bits]] [-f config] [-s livesyncport]"
103#ifdef WANT_ACCESSLIST_BLACK 104#ifdef WANT_ACCESSLIST_BLACK
104 " [-b blacklistfile]" 105 " [-b blacklistfile]"
105#elif defined ( WANT_ACCESSLIST_WHITE ) 106#elif defined(WANT_ACCESSLIST_WHITE)
106 " [-w whitelistfile]" 107 " [-w whitelistfile]"
107#endif 108#endif
108 "\n", name ); 109 "\n",
110 name);
109} 111}
110 112
111#define HELPLINE(opt,desc) fprintf(stderr, "\t%-10s%s\n",opt,desc) 113#define HELPLINE(opt, desc) fprintf(stderr, "\t%-10s%s\n", opt, desc)
112static void help( char *name ) { 114static void help(char *name) {
113 usage( name ); 115 usage(name);
114 116
115 HELPLINE("-f config","include and execute the config file"); 117 HELPLINE("-f config", "include and execute the config file");
116 HELPLINE("-i ip","specify ip to bind to with next -[pP] (default: any, overrides preceeding ones)"); 118 HELPLINE("-i ip", "specify ip to bind to with next -[pP] (default: any, overrides preceeding ones)");
117 HELPLINE("-p port","do bind to tcp port (default: 6969, you may specify more than one)"); 119 HELPLINE("-p port", "do bind to tcp port (default: 6969, you may specify more than one)");
118 HELPLINE("-P port","do bind to udp port (default: 6969, you may specify more than one)"); 120 HELPLINE("-P port", "do bind to udp port (default: 6969, you may specify more than one)");
119 HELPLINE("-r redirecturl","specify url where / should be redirected to (default none)"); 121 HELPLINE("-r redirecturl", "specify url where / should be redirected to (default none)");
120 HELPLINE("-d dir","specify directory to try to chroot to (default: \".\")"); 122 HELPLINE("-d dir", "specify directory to try to chroot to (default: \".\")");
121 HELPLINE("-u user","specify user under whose privileges opentracker should run (default: \"nobody\")"); 123 HELPLINE("-u user", "specify user under whose privileges opentracker should run (default: \"nobody\")");
122 HELPLINE("-A ip[/bits]","bless an ip address or net as admin address (e.g. to allow syncs from this address)"); 124 HELPLINE("-A ip[/bits]", "bless an ip address or net as admin address (e.g. to allow syncs from this address)");
123#ifdef WANT_ACCESSLIST_BLACK 125#ifdef WANT_ACCESSLIST_BLACK
124 HELPLINE("-b file","specify blacklist file."); 126 HELPLINE("-b file", "specify blacklist file.");
125#elif defined( WANT_ACCESSLIST_WHITE ) 127#elif defined(WANT_ACCESSLIST_WHITE)
126 HELPLINE("-w file","specify whitelist file."); 128 HELPLINE("-w file", "specify whitelist file.");
127#endif 129#endif
128 130
129 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"); 131 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");
@@ -133,165 +135,165 @@ static void help( char *name ) {
133} 135}
134#undef HELPLINE 136#undef HELPLINE
135 137
136static ssize_t header_complete( char * request, ssize_t byte_count ) { 138static ssize_t header_complete(char *request, ssize_t byte_count) {
137 ssize_t i = 0, state = 0; 139 ssize_t i = 0, state = 0;
138 140
139 for( i=1; i < byte_count; i+=2 ) 141 for (i = 1; i < byte_count; i += 2)
140 if( request[i] <= 13 ) { 142 if (request[i] <= 13) {
141 i--; 143 i--;
142 for( state = 0 ; i < byte_count; ++i ) { 144 for (state = 0; i < byte_count; ++i) {
143 char c = request[i]; 145 char c = request[i];
144 if( c == '\r' || c == '\n' ) 146 if (c == '\r' || c == '\n')
145 state = ( state >> 2 ) | ( ( c << 6 ) & 0xc0 ); 147 state = (state >> 2) | ((c << 6) & 0xc0);
146 else 148 else
147 break; 149 break;
148 if( state >= 0xa0 || state == 0x99 ) return i + 1; 150 if (state >= 0xa0 || state == 0x99)
151 return i + 1;
149 } 152 }
150 } 153 }
151 return 0; 154 return 0;
152} 155}
153 156
154static void handle_dead( const int64 sock ) { 157static void handle_dead(const int64 sock) {
155 struct http_data* cookie=io_getcookie( sock ); 158 struct http_data *cookie = io_getcookie(sock);
156 if( cookie ) { 159 if (cookie) {
157 size_t i; 160 size_t i;
158 for ( i = 0; i < cookie->batches; ++i) 161 for (i = 0; i < cookie->batches; ++i)
159 iob_reset( cookie->batch + i ); 162 iob_reset(cookie->batch + i);
160 free( cookie->batch ); 163 free(cookie->batch);
161 array_reset( &cookie->request ); 164 array_reset(&cookie->request);
162 if( cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) ) 165 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER))
163 mutex_workqueue_canceltask( sock ); 166 mutex_workqueue_canceltask(sock);
164 free( cookie ); 167 free(cookie);
165 } 168 }
166 io_close( sock ); 169 io_close(sock);
167} 170}
168 171
169static void handle_read( const int64 sock, struct ot_workstruct *ws ) { 172static void handle_read(const int64 sock, struct ot_workstruct *ws) {
170 struct http_data* cookie = io_getcookie( sock ); 173 struct http_data *cookie = io_getcookie(sock);
171 ssize_t byte_count = io_tryread( sock, ws->inbuf, G_INBUF_SIZE ); 174 ssize_t byte_count = io_tryread(sock, ws->inbuf, G_INBUF_SIZE);
172 175
173 if( byte_count == 0 || byte_count == -3 ) { 176 if (byte_count == 0 || byte_count == -3) {
174 handle_dead( sock ); 177 handle_dead(sock);
175 return; 178 return;
176 } 179 }
177 180
178 if( byte_count == -1) 181 if (byte_count == -1)
179 return; 182 return;
180 183
181 /* If we get the whole request in one packet, handle it without copying */ 184 /* If we get the whole request in one packet, handle it without copying */
182 if( !array_start( &cookie->request ) ) { 185 if (!array_start(&cookie->request)) {
183 if( ( ws->header_size = header_complete( ws->inbuf, byte_count ) ) ) { 186 if ((ws->header_size = header_complete(ws->inbuf, byte_count))) {
184 ws->request = ws->inbuf; 187 ws->request = ws->inbuf;
185 ws->request_size = byte_count; 188 ws->request_size = byte_count;
186 http_handle_request( sock, ws ); 189 http_handle_request(sock, ws);
187 } else 190 } else
188 array_catb( &cookie->request, ws->inbuf, (size_t)byte_count ); 191 array_catb(&cookie->request, ws->inbuf, (size_t)byte_count);
189 return; 192 return;
190 } 193 }
191 194
192 array_catb( &cookie->request, ws->inbuf, byte_count ); 195 array_catb(&cookie->request, ws->inbuf, byte_count);
193 if( array_failed( &cookie->request ) || array_bytes( &cookie->request ) > 8192 ) { 196 if (array_failed(&cookie->request) || array_bytes(&cookie->request) > 8192) {
194 http_issue_error( sock, ws, CODE_HTTPERROR_500 ); 197 http_issue_error(sock, ws, CODE_HTTPERROR_500);
195 return; 198 return;
196 } 199 }
197 200
198 while( ( ws->header_size = header_complete( array_start( &cookie->request ), array_bytes( &cookie->request ) ) ) ) { 201 while ((ws->header_size = header_complete(array_start(&cookie->request), array_bytes(&cookie->request)))) {
199 ws->request = array_start( &cookie->request ); 202 ws->request = array_start(&cookie->request);
200 ws->request_size = array_bytes( &cookie->request ); 203 ws->request_size = array_bytes(&cookie->request);
201 http_handle_request( sock, ws ); 204 http_handle_request(sock, ws);
202#ifdef WANT_KEEPALIVE 205#ifdef WANT_KEEPALIVE
203 if( !ws->keep_alive ) 206 if (!ws->keep_alive)
204#endif 207#endif
205 return; 208 return;
206 } 209 }
207} 210}
208 211
209static void handle_write( const int64 sock ) { 212static void handle_write(const int64 sock) {
210 struct http_data* cookie=io_getcookie( sock ); 213 struct http_data *cookie = io_getcookie(sock);
211 size_t i; 214 size_t i;
212 int chunked = 0; 215 int chunked = 0;
213 216
214 /* Look for the first io_batch still containing bytes to write */ 217 /* Look for the first io_batch still containing bytes to write */
215 if( cookie ) { 218 if (cookie) {
216 if( cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER ) 219 if (cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)
217 chunked = 1; 220 chunked = 1;
218 221
219 for( i = 0; i < cookie->batches; ++i ) { 222 for (i = 0; i < cookie->batches; ++i) {
220 if( cookie->batch[i].bytesleft ) { 223 if (cookie->batch[i].bytesleft) {
221 int64 res = iob_send( sock, cookie->batch + i ); 224 int64 res = iob_send(sock, cookie->batch + i);
222 225
223 if( res == -3 ) { 226 if (res == -3) {
224 handle_dead( sock ); 227 handle_dead(sock);
225 return; 228 return;
226 } 229 }
227 230
228 if( !cookie->batch[i].bytesleft ) 231 if (!cookie->batch[i].bytesleft)
229 continue; 232 continue;
230 233
231 if( res == -1 || res > 0 || i < cookie->batches - 1 ) 234 if (res == -1 || res > 0 || i < cookie->batches - 1)
232 return; 235 return;
233 } 236 }
234 } 237 }
235 } 238 }
236 239
237 /* In a chunked transfer after all batches accumulated have been sent, wait for the next one */ 240 /* In a chunked transfer after all batches accumulated have been sent, wait for the next one */
238 if( chunked ) 241 if (chunked)
239 io_dontwantwrite( sock ); 242 io_dontwantwrite(sock);
240 else 243 else
241 handle_dead( sock ); 244 handle_dead(sock);
242} 245}
243 246
244static void handle_accept( const int64 serversocket ) { 247static void handle_accept(const int64 serversocket) {
245 struct http_data *cookie; 248 struct http_data *cookie;
246 int64 sock; 249 int64 sock;
247 ot_ip6 ip; 250 ot_ip6 ip;
248 uint16 port; 251 uint16 port;
249 tai6464 t; 252 tai6464 t;
250 253
251 while( ( sock = socket_accept6( serversocket, ip, &port, NULL ) ) != -1 ) { 254 while ((sock = socket_accept6(serversocket, ip, &port, NULL)) != -1) {
252 255
253 /* Put fd into a non-blocking mode */ 256 /* Put fd into a non-blocking mode */
254 io_nonblock( sock ); 257 io_nonblock(sock);
255 258
256 if( !io_fd( sock ) || 259 if (!io_fd(sock) || !(cookie = (struct http_data *)malloc(sizeof(struct http_data)))) {
257 !( cookie = (struct http_data*)malloc( sizeof(struct http_data) ) ) ) { 260 io_close(sock);
258 io_close( sock );
259 continue; 261 continue;
260 } 262 }
261 memset(cookie, 0, sizeof( struct http_data ) ); 263 memset(cookie, 0, sizeof(struct http_data));
262 memcpy(cookie->ip,ip,sizeof(ot_ip6)); 264 memcpy(cookie->ip, ip, sizeof(ot_ip6));
263 265
264 io_setcookie( sock, cookie ); 266 io_setcookie(sock, cookie);
265 io_wantread( sock ); 267 io_wantread(sock);
266 268
267 stats_issue_event( EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip); 269 stats_issue_event(EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip);
268 270
269 /* That breaks taia encapsulation. But there is no way to take system 271 /* That breaks taia encapsulation. But there is no way to take system
270 time this often in FreeBSD and libowfat does not allow to set unix time */ 272 time this often in FreeBSD and libowfat does not allow to set unix time */
271 taia_uint( &t, 0 ); /* Clear t */ 273 taia_uint(&t, 0); /* Clear t */
272 tai_unix( &(t.sec), (g_now_seconds + OT_CLIENT_TIMEOUT) ); 274 tai_unix(&(t.sec), (g_now_seconds + OT_CLIENT_TIMEOUT));
273 io_timeout( sock, t ); 275 io_timeout(sock, t);
274 } 276 }
275 io_eagain(serversocket); 277 io_eagain(serversocket);
276} 278}
277 279
278static void * server_mainloop( void * args ) { 280static void *server_mainloop(void *args) {
279 struct ot_workstruct ws; 281 struct ot_workstruct ws;
280 time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; 282 time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
281 struct iovec *iovector; 283 struct iovec *iovector;
282 int iovec_entries, is_partial; 284 int iovec_entries, is_partial;
283 285
284 (void)args; 286 (void)args;
285 287
286 /* Initialize our "thread local storage" */ 288 /* Initialize our "thread local storage" */
287 ws.inbuf = malloc( G_INBUF_SIZE ); 289 ws.inbuf = malloc(G_INBUF_SIZE);
288 ws.outbuf = malloc( G_OUTBUF_SIZE ); 290 ws.outbuf = malloc(G_OUTBUF_SIZE);
289#ifdef _DEBUG_HTTPERROR 291#ifdef _DEBUG_HTTPERROR
290 ws.debugbuf= malloc( G_DEBUGBUF_SIZE ); 292 ws.debugbuf = malloc(G_DEBUGBUF_SIZE);
291#endif 293#endif
292 294
293 if( !ws.inbuf || !ws.outbuf ) 295 if (!ws.inbuf || !ws.outbuf)
294 panic( "Initializing worker failed" ); 296 panic("Initializing worker failed");
295 297
296#ifdef WANT_ARC4RANDOM 298#ifdef WANT_ARC4RANDOM
297 arc4random_buf(&ws.rand48_state[0], 3 * sizeof(uint16_t)); 299 arc4random_buf(&ws.rand48_state[0], 3 * sizeof(uint16_t));
@@ -301,32 +303,32 @@ static void * server_mainloop( void * args ) {
301 ws.rand48_state[2] = (uint16_t)random(); 303 ws.rand48_state[2] = (uint16_t)random();
302#endif 304#endif
303 305
304 for( ; ; ) { 306 for (;;) {
305 int64 sock; 307 int64 sock;
306 308
307 io_wait(); 309 io_wait();
308 310
309 while( ( sock = io_canread( ) ) != -1 ) { 311 while ((sock = io_canread()) != -1) {
310 const void *cookie = io_getcookie( sock ); 312 const void *cookie = io_getcookie(sock);
311 if( (intptr_t)cookie == FLAG_TCP ) 313 if ((intptr_t)cookie == FLAG_TCP)
312 handle_accept( sock ); 314 handle_accept(sock);
313 else if( (intptr_t)cookie == FLAG_UDP ) 315 else if ((intptr_t)cookie == FLAG_UDP)
314 handle_udp6( sock, &ws ); 316 handle_udp6(sock, &ws);
315 else if( (intptr_t)cookie == FLAG_SELFPIPE ) 317 else if ((intptr_t)cookie == FLAG_SELFPIPE)
316 io_tryread( sock, ws.inbuf, G_INBUF_SIZE ); 318 io_tryread(sock, ws.inbuf, G_INBUF_SIZE);
317 else 319 else
318 handle_read( sock, &ws ); 320 handle_read(sock, &ws);
319 } 321 }
320 322
321 while( ( sock = mutex_workqueue_popresult( &iovec_entries, &iovector, &is_partial ) ) != -1 ) 323 while ((sock = mutex_workqueue_popresult(&iovec_entries, &iovector, &is_partial)) != -1)
322 http_sendiovecdata( sock, &ws, iovec_entries, iovector, is_partial ); 324 http_sendiovecdata(sock, &ws, iovec_entries, iovector, is_partial);
323 325
324 while( ( sock = io_canwrite( ) ) != -1 ) 326 while ((sock = io_canwrite()) != -1)
325 handle_write( sock ); 327 handle_write(sock);
326 328
327 if( g_now_seconds > next_timeout_check ) { 329 if (g_now_seconds > next_timeout_check) {
328 while( ( sock = io_timeouted() ) != -1 ) 330 while ((sock = io_timeouted()) != -1)
329 handle_dead( sock ); 331 handle_dead(sock);
330 next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; 332 next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
331 } 333 }
332 334
@@ -335,276 +337,298 @@ static void * server_mainloop( void * args ) {
335 return 0; 337 return 0;
336} 338}
337 339
338static int64_t ot_try_bind( ot_ip6 ip, uint16_t port, PROTO_FLAG proto ) { 340static int64_t ot_try_bind(ot_ip6 ip, uint16_t port, PROTO_FLAG proto) {
339 int64 sock = proto == FLAG_TCP ? socket_tcp6( ) : socket_udp6( ); 341 int64 sock = proto == FLAG_TCP ? socket_tcp6() : socket_udp6();
340 342
341#ifdef _DEBUG 343#ifdef _DEBUG
342 { 344 {
343 char *protos[] = {"TCP","UDP","UDP mcast"}; 345 char *protos[] = {"TCP", "UDP", "UDP mcast"};
344 char _debug[512]; 346 char _debug[512];
345 int off = snprintf( _debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto] ); 347 int off = snprintf(_debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto]);
346 off += fmt_ip6c( _debug+off, ip); 348 off += fmt_ip6c(_debug + off, ip);
347 snprintf( _debug + off, sizeof(_debug)-off, "]:%d...", port); 349 snprintf(_debug + off, sizeof(_debug) - off, "]:%d...", port);
348 fputs( _debug, stderr ); 350 fputs(_debug, stderr);
349 } 351 }
350#endif 352#endif
351 353
352 if( socket_bind6_reuse( sock, ip, port, 0 ) == -1 ) 354 if (socket_bind6_reuse(sock, ip, port, 0) == -1)
353 panic( "socket_bind6_reuse" ); 355 panic("socket_bind6_reuse");
354 356
355 if( ( proto == FLAG_TCP ) && ( socket_listen( sock, SOMAXCONN) == -1 ) ) 357 if ((proto == FLAG_TCP) && (socket_listen(sock, SOMAXCONN) == -1))
356 panic( "socket_listen" ); 358 panic("socket_listen");
357 359
358 if( !io_fd( sock ) ) 360 if (!io_fd(sock))
359 panic( "io_fd" ); 361 panic("io_fd");
360 362
361 io_setcookie( sock, (void*)proto ); 363 io_setcookie(sock, (void *)proto);
362 364
363 if( (proto == FLAG_UDP) && g_udp_workers ) { 365 if ((proto == FLAG_UDP) && g_udp_workers) {
364 io_block( sock ); 366 io_block(sock);
365 udp_init( sock, g_udp_workers ); 367 udp_init(sock, g_udp_workers);
366 } else 368 } else
367 io_wantread( sock ); 369 io_wantread(sock);
368 370
369#ifdef _DEBUG 371#ifdef _DEBUG
370 fputs( " success.\n", stderr); 372 fputs(" success.\n", stderr);
371#endif 373#endif
372 374
373 return sock; 375 return sock;
374} 376}
375 377
376char * set_config_option( char **option, char *value ) { 378char *set_config_option(char **option, char *value) {
377#ifdef _DEBUG 379#ifdef _DEBUG
378 fprintf( stderr, "Setting config option: %s\n", value ); 380 fprintf(stderr, "Setting config option: %s\n", value);
379#endif 381#endif
380 while( isspace(*value) ) ++value; 382 while (isspace(*value))
381 free( *option ); 383 ++value;
382 return *option = strdup( value ); 384 free(*option);
385 return *option = strdup(value);
383} 386}
384 387
385static int scan_ip6_port( const char *src, ot_ip6 ip, uint16 *port ) { 388static int scan_ip6_port(const char *src, ot_ip6 ip, uint16 *port) {
386 const char *s = src; 389 const char *s = src;
387 int off, bracket = 0; 390 int off, bracket = 0;
388 while( isspace(*s) ) ++s; 391 while (isspace(*s))
389 if( *s == '[' ) ++s, ++bracket; /* for v6 style notation */ 392 ++s;
390 if( !(off = scan_ip6( s, ip ) ) ) 393 if (*s == '[')
394 ++s, ++bracket; /* for v6 style notation */
395 if (!(off = scan_ip6(s, ip)))
391 return 0; 396 return 0;
392 s += off; 397 s += off;
393 if( bracket && *s == ']' ) ++s; 398 if (bracket && *s == ']')
394 if( *s == 0 || isspace(*s)) return s-src; 399 ++s;
395 if( !ip6_isv4mapped(ip)) { 400 if (*s == 0 || isspace(*s))
396 if( *s != ':' && *s != '.' ) return 0; 401 return s - src;
397 if( !bracket && *(s) == ':' ) return 0; 402 if (!ip6_isv4mapped(ip)) {
403 if (*s != ':' && *s != '.')
404 return 0;
405 if (!bracket && *(s) == ':')
406 return 0;
398 s++; 407 s++;
399 } else { 408 } else {
400 if( *(s++) != ':' ) return 0; 409 if (*(s++) != ':')
410 return 0;
401 } 411 }
402 if( !(off = scan_ushort (s, port ) ) ) 412 if (!(off = scan_ushort(s, port)))
403 return 0; 413 return 0;
404 return off+s-src; 414 return off + s - src;
405} 415}
406 416
407static int scan_ip6_net( const char *src, ot_net *net) { 417static int scan_ip6_net(const char *src, ot_net *net) {
408 const char *s = src; 418 const char *s = src;
409 int off; 419 int off;
410 while( isspace(*s) ) ++s; 420 while (isspace(*s))
411 if( !(off = scan_ip6( s, net->address ) ) ) 421 ++s;
422 if (!(off = scan_ip6(s, net->address)))
412 return 0; 423 return 0;
413 s += off; 424 s += off;
414 if(*s!='/') 425 if (*s != '/')
415 net->bits = 128; 426 net->bits = 128;
416 else { 427 else {
417 s++; 428 s++;
418 if( !(off = scan_int (s, &net->bits ) ) ) 429 if (!(off = scan_int(s, &net->bits)))
419 return 0; 430 return 0;
420 if( ip6_isv4mapped(net->address)) 431 if (ip6_isv4mapped(net->address))
421 net->bits += 96; 432 net->bits += 96;
422 if(net->bits > 128) 433 if (net->bits > 128)
423 return 0; 434 return 0;
424 s += off; 435 s += off;
425 } 436 }
426 return off+s-src; 437 return off + s - src;
427} 438}
428 439
429int parse_configfile( char * config_filename ) { 440int parse_configfile(char *config_filename) {
430 FILE * accesslist_filehandle; 441 FILE *accesslist_filehandle;
431 char inbuf[512]; 442 char inbuf[512];
432 ot_ip6 tmpip; 443 ot_ip6 tmpip;
433#if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE) 444#if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE)
434 ot_net tmpnet; 445 ot_net tmpnet;
435#endif 446#endif
436 int bound = 0; 447 int bound = 0;
437 448
438 accesslist_filehandle = fopen( config_filename, "r" ); 449 accesslist_filehandle = fopen(config_filename, "r");
439 450
440 if( accesslist_filehandle == NULL ) { 451 if (accesslist_filehandle == NULL) {
441 fprintf( stderr, "Warning: Can't open config file: %s.", config_filename ); 452 fprintf(stderr, "Warning: Can't open config file: %s.", config_filename);
442 return 0; 453 return 0;
443 } 454 }
444 455
445 while( fgets( inbuf, sizeof(inbuf), accesslist_filehandle ) ) { 456 while (fgets(inbuf, sizeof(inbuf), accesslist_filehandle)) {
446 char *p = inbuf; 457 char *p = inbuf;
447 size_t strl; 458 size_t strl;
448 459
449 /* Skip white spaces */ 460 /* Skip white spaces */
450 while(isspace(*p)) ++p; 461 while (isspace(*p))
462 ++p;
451 463
452 /* Ignore comments and empty lines */ 464 /* Ignore comments and empty lines */
453 if((*p=='#')||(*p=='\n')||(*p==0)) continue; 465 if ((*p == '#') || (*p == '\n') || (*p == 0))
466 continue;
454 467
455 /* consume trailing new lines and spaces */ 468 /* consume trailing new lines and spaces */
456 strl = strlen(p); 469 strl = strlen(p);
457 while( strl && isspace(p[strl-1])) 470 while (strl && isspace(p[strl - 1]))
458 p[--strl] = 0; 471 p[--strl] = 0;
459 472
460 /* Scan for commands */ 473 /* Scan for commands */
461 if(!byte_diff(p,15,"tracker.rootdir" ) && isspace(p[15])) { 474 if (!byte_diff(p, 15, "tracker.rootdir") && isspace(p[15])) {
462 set_config_option( &g_serverdir, p+16 ); 475 set_config_option(&g_serverdir, p + 16);
463 } else if(!byte_diff(p,12,"tracker.user" ) && isspace(p[12])) { 476 } else if (!byte_diff(p, 12, "tracker.user") && isspace(p[12])) {
464 set_config_option( &g_serveruser, p+13 ); 477 set_config_option(&g_serveruser, p + 13);
465 } else if(!byte_diff(p,14,"listen.tcp_udp" ) && isspace(p[14])) { 478 } else if (!byte_diff(p, 14, "listen.tcp_udp") && isspace(p[14])) {
466 uint16_t tmpport = 6969; 479 uint16_t tmpport = 6969;
467 if( !scan_ip6_port( p+15, tmpip, &tmpport )) goto parse_error; 480 if (!scan_ip6_port(p + 15, tmpip, &tmpport))
468 ot_try_bind( tmpip, tmpport, FLAG_TCP ); ++bound; 481 goto parse_error;
469 ot_try_bind( tmpip, tmpport, FLAG_UDP ); ++bound; 482 ot_try_bind(tmpip, tmpport, FLAG_TCP);
470 } else if(!byte_diff(p,10,"listen.tcp" ) && isspace(p[10])) { 483 ++bound;
484 ot_try_bind(tmpip, tmpport, FLAG_UDP);
485 ++bound;
486 } else if (!byte_diff(p, 10, "listen.tcp") && isspace(p[10])) {
471 uint16_t tmpport = 6969; 487 uint16_t tmpport = 6969;
472 if( !scan_ip6_port( p+11, tmpip, &tmpport )) goto parse_error; 488 if (!scan_ip6_port(p + 11, tmpip, &tmpport))
473 ot_try_bind( tmpip, tmpport, FLAG_TCP ); 489 goto parse_error;
490 ot_try_bind(tmpip, tmpport, FLAG_TCP);
474 ++bound; 491 ++bound;
475 } else if(!byte_diff(p, 10, "listen.udp" ) && isspace(p[10])) { 492 } else if (!byte_diff(p, 10, "listen.udp") && isspace(p[10])) {
476 uint16_t tmpport = 6969; 493 uint16_t tmpport = 6969;
477 if( !scan_ip6_port( p+11, tmpip, &tmpport )) goto parse_error; 494 if (!scan_ip6_port(p + 11, tmpip, &tmpport))
478 ot_try_bind( tmpip, tmpport, FLAG_UDP ); 495 goto parse_error;
496 ot_try_bind(tmpip, tmpport, FLAG_UDP);
479 ++bound; 497 ++bound;
480 } else if(!byte_diff(p,18,"listen.udp.workers" ) && isspace(p[18])) { 498 } else if (!byte_diff(p, 18, "listen.udp.workers") && isspace(p[18])) {
481 char *value = p + 18; 499 char *value = p + 18;
482 while( isspace(*value) ) ++value; 500 while (isspace(*value))
483 scan_uint( value, &g_udp_workers ); 501 ++value;
502 scan_uint(value, &g_udp_workers);
484#ifdef WANT_ACCESSLIST_WHITE 503#ifdef WANT_ACCESSLIST_WHITE
485 } else if(!byte_diff(p, 16, "access.whitelist" ) && isspace(p[16])) { 504 } else if (!byte_diff(p, 16, "access.whitelist") && isspace(p[16])) {
486 set_config_option( &g_accesslist_filename, p+17 ); 505 set_config_option(&g_accesslist_filename, p + 17);
487#elif defined( WANT_ACCESSLIST_BLACK ) 506#elif defined(WANT_ACCESSLIST_BLACK)
488 } else if(!byte_diff(p, 16, "access.blacklist" ) && isspace(p[16])) { 507 } else if (!byte_diff(p, 16, "access.blacklist") && isspace(p[16])) {
489 set_config_option( &g_accesslist_filename, p+17 ); 508 set_config_option(&g_accesslist_filename, p + 17);
490#endif 509#endif
491#ifdef WANT_DYNAMIC_ACCESSLIST 510#ifdef WANT_DYNAMIC_ACCESSLIST
492 } else if(!byte_diff(p, 15, "access.fifo_add" ) && isspace(p[15])) { 511 } else if (!byte_diff(p, 15, "access.fifo_add") && isspace(p[15])) {
493 set_config_option( &g_accesslist_pipe_add, p+16 ); 512 set_config_option(&g_accesslist_pipe_add, p + 16);
494 } else if(!byte_diff(p, 18, "access.fifo_delete" ) && isspace(p[18])) { 513 } else if (!byte_diff(p, 18, "access.fifo_delete") && isspace(p[18])) {
495 set_config_option( &g_accesslist_pipe_delete, p+19 ); 514 set_config_option(&g_accesslist_pipe_delete, p + 19);
496#endif 515#endif
497#ifdef WANT_RESTRICT_STATS 516#ifdef WANT_RESTRICT_STATS
498 } else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) { 517 } else if (!byte_diff(p, 12, "access.stats") && isspace(p[12])) {
499 if( !scan_ip6_net( p+13, &tmpnet )) goto parse_error; 518 if (!scan_ip6_net(p + 13, &tmpnet))
500 accesslist_bless_net( &tmpnet, OT_PERMISSION_MAY_STAT ); 519 goto parse_error;
520 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT);
501#endif 521#endif
502 } else if(!byte_diff(p, 17, "access.stats_path" ) && isspace(p[17])) { 522 } else if (!byte_diff(p, 17, "access.stats_path") && isspace(p[17])) {
503 set_config_option( &g_stats_path, p+18 ); 523 set_config_option(&g_stats_path, p + 18);
504#ifdef WANT_IP_FROM_PROXY 524#ifdef WANT_IP_FROM_PROXY
505 } else if(!byte_diff(p, 12, "access.proxy" ) && isspace(p[12])) { 525 } else if (!byte_diff(p, 12, "access.proxy") && isspace(p[12])) {
506 if( !scan_ip6_net( p+13, &tmpnet )) goto parse_error; 526 if (!scan_ip6_net(p + 13, &tmpnet))
507 accesslist_bless_net( &tmpnet, OT_PERMISSION_MAY_PROXY ); 527 goto parse_error;
528 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY);
508#endif 529#endif
509 } else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) { 530 } else if (!byte_diff(p, 20, "tracker.redirect_url") && isspace(p[20])) {
510 set_config_option( &g_redirecturl, p+21 ); 531 set_config_option(&g_redirecturl, p + 21);
511#ifdef WANT_SYNC_LIVE 532#ifdef WANT_SYNC_LIVE
512 } else if(!byte_diff(p, 24, "livesync.cluster.node_ip" ) && isspace(p[24])) { 533 } else if (!byte_diff(p, 24, "livesync.cluster.node_ip") && isspace(p[24])) {
513 if( !scan_ip6_net( p+25, &tmpnet )) goto parse_error; 534 if (!scan_ip6_net(p + 25, &tmpnet))
514 accesslist_bless_net( &tmpnet, OT_PERMISSION_MAY_LIVESYNC ); 535 goto parse_error;
515 } else if(!byte_diff(p, 23, "livesync.cluster.listen" ) && isspace(p[23])) { 536 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC);
537 } else if (!byte_diff(p, 23, "livesync.cluster.listen") && isspace(p[23])) {
516 uint16_t tmpport = LIVESYNC_PORT; 538 uint16_t tmpport = LIVESYNC_PORT;
517 if( !scan_ip6_port( p+24, tmpip, &tmpport )) goto parse_error; 539 if (!scan_ip6_port(p + 24, tmpip, &tmpport))
518 livesync_bind_mcast( tmpip, tmpport ); 540 goto parse_error;
541 livesync_bind_mcast(tmpip, tmpport);
519#endif 542#endif
520 } else 543 } else
521 fprintf( stderr, "Unhandled line in config file: %s\n", inbuf ); 544 fprintf(stderr, "Unhandled line in config file: %s\n", inbuf);
522 continue; 545 continue;
523 parse_error: 546 parse_error:
524 fprintf( stderr, "Parse error in config file: %s\n", inbuf); 547 fprintf(stderr, "Parse error in config file: %s\n", inbuf);
525 } 548 }
526 fclose( accesslist_filehandle ); 549 fclose(accesslist_filehandle);
527 return bound; 550 return bound;
528} 551}
529 552
530void load_state(const char * const state_filename ) { 553void load_state(const char *const state_filename) {
531 FILE * state_filehandle; 554 FILE *state_filehandle;
532 char inbuf[512]; 555 char inbuf[512];
533 ot_hash infohash; 556 ot_hash infohash;
534 unsigned long long base, downcount; 557 unsigned long long base, downcount;
535 int consumed; 558 int consumed;
536 559
537 state_filehandle = fopen( state_filename, "r" ); 560 state_filehandle = fopen(state_filename, "r");
538 561
539 if( state_filehandle == NULL ) { 562 if (state_filehandle == NULL) {
540 fprintf( stderr, "Warning: Can't open config file: %s.", state_filename ); 563 fprintf(stderr, "Warning: Can't open config file: %s.", state_filename);
541 return; 564 return;
542 } 565 }
543 566
544 /* We do ignore anything that is not of the form "^[:xdigit:]:\d+:\d+" */ 567 /* We do ignore anything that is not of the form "^[:xdigit:]:\d+:\d+" */
545 while( fgets( inbuf, sizeof(inbuf), state_filehandle ) ) { 568 while (fgets(inbuf, sizeof(inbuf), state_filehandle)) {
546 int i; 569 int i;
547 for( i=0; i<(int)sizeof(ot_hash); ++i ) { 570 for (i = 0; i < (int)sizeof(ot_hash); ++i) {
548 int eger = 16 * scan_fromhex( inbuf[ 2*i ] ) + scan_fromhex( inbuf[ 1 + 2*i ] ); 571 int eger = 16 * scan_fromhex(inbuf[2 * i]) + scan_fromhex(inbuf[1 + 2 * i]);
549 if( eger < 0 ) 572 if (eger < 0)
550 continue; 573 continue;
551 infohash[i] = eger; 574 infohash[i] = eger;
552 } 575 }
553 576
554 if( i != (int)sizeof(ot_hash) ) continue; 577 if (i != (int)sizeof(ot_hash))
578 continue;
555 i *= 2; 579 i *= 2;
556 580
557 if( inbuf[ i++ ] != ':' || !( consumed = scan_ulonglong( inbuf+i, &base ) ) ) continue; 581 if (inbuf[i++] != ':' || !(consumed = scan_ulonglong(inbuf + i, &base)))
582 continue;
558 i += consumed; 583 i += consumed;
559 if( inbuf[ i++ ] != ':' || !( consumed = scan_ulonglong( inbuf+i, &downcount ) ) ) continue; 584 if (inbuf[i++] != ':' || !(consumed = scan_ulonglong(inbuf + i, &downcount)))
560 add_torrent_from_saved_state( infohash, base, downcount ); 585 continue;
586 add_torrent_from_saved_state(infohash, base, downcount);
561 } 587 }
562 588
563 fclose( state_filehandle ); 589 fclose(state_filehandle);
564} 590}
565 591
566int drop_privileges ( const char * const serveruser, const char * const serverdir ) { 592int drop_privileges(const char *const serveruser, const char *const serverdir) {
567 struct passwd *pws = NULL; 593 struct passwd *pws = NULL;
568 594
569#ifdef _DEBUG 595#ifdef _DEBUG
570 if( !geteuid() ) 596 if (!geteuid())
571 fprintf( stderr, "Dropping to user %s.\n", serveruser ); 597 fprintf(stderr, "Dropping to user %s.\n", serveruser);
572 if( serverdir ) 598 if (serverdir)
573 fprintf( stderr, "ch%s'ing to directory %s.\n", geteuid() ? "dir" : "root", serverdir ); 599 fprintf(stderr, "ch%s'ing to directory %s.\n", geteuid() ? "dir" : "root", serverdir);
574#endif 600#endif
575 601
576 /* Grab pws entry before chrooting */ 602 /* Grab pws entry before chrooting */
577 pws = getpwnam( serveruser ); 603 pws = getpwnam(serveruser);
578 endpwent(); 604 endpwent();
579 605
580 if( geteuid() == 0 ) { 606 if (geteuid() == 0) {
581 /* Running as root: chroot and drop privileges */ 607 /* Running as root: chroot and drop privileges */
582 if( serverdir && chroot( serverdir ) ) { 608 if (serverdir && chroot(serverdir)) {
583 fprintf( stderr, "Could not chroot to %s, because: %s\n", serverdir, strerror(errno) ); 609 fprintf(stderr, "Could not chroot to %s, because: %s\n", serverdir, strerror(errno));
584 return -1; 610 return -1;
585 } 611 }
586 612
587 if(chdir("/")) 613 if (chdir("/"))
588 panic("chdir() failed after chrooting: "); 614 panic("chdir() failed after chrooting: ");
589 615
590 /* If we can't find server user, revert to nobody's default uid */ 616 /* If we can't find server user, revert to nobody's default uid */
591 if( !pws ) { 617 if (!pws) {
592 fprintf( stderr, "Warning: Could not get password entry for %s. Reverting to uid -2.\n", serveruser ); 618 fprintf(stderr, "Warning: Could not get password entry for %s. Reverting to uid -2.\n", serveruser);
593 if (setegid( (gid_t)-2 ) || setgid( (gid_t)-2 ) || setuid( (uid_t)-2 ) || seteuid( (uid_t)-2 )) 619 if (setegid((gid_t)-2) || setgid((gid_t)-2) || setuid((uid_t)-2) || seteuid((uid_t)-2))
594 panic("Could not set uid to value -2"); 620 panic("Could not set uid to value -2");
595 } 621 } else {
596 else { 622 if (setegid(pws->pw_gid) || setgid(pws->pw_gid) || setuid(pws->pw_uid) || seteuid(pws->pw_uid))
597 if (setegid( pws->pw_gid ) || setgid( pws->pw_gid ) || setuid( pws->pw_uid ) || seteuid( pws->pw_uid ))
598 panic("Could not set uid to specified value"); 623 panic("Could not set uid to specified value");
599 } 624 }
600 625
601 if( geteuid() == 0 || getegid() == 0 ) 626 if (geteuid() == 0 || getegid() == 0)
602 panic("Still running with root privileges?!"); 627 panic("Still running with root privileges?!");
603 } 628 } else {
604 else {
605 /* Normal user, just chdir() */ 629 /* Normal user, just chdir() */
606 if( serverdir && chdir( serverdir ) ) { 630 if (serverdir && chdir(serverdir)) {
607 fprintf( stderr, "Could not chroot to %s, because: %s\n", serverdir, strerror(errno) ); 631 fprintf(stderr, "Could not chroot to %s, because: %s\n", serverdir, strerror(errno));
608 return -1; 632 return -1;
609 } 633 }
610 } 634 }
@@ -613,7 +637,7 @@ int drop_privileges ( const char * const serveruser, const char * const serverdi
613} 637}
614 638
615/* Maintain our copy of the clock. time() on BSDs is very expensive. */ 639/* Maintain our copy of the clock. time() on BSDs is very expensive. */
616static void *time_caching_worker(void*args) { 640static void *time_caching_worker(void *args) {
617 (void)args; 641 (void)args;
618 while (1) { 642 while (1) {
619 g_now_seconds = time(NULL); 643 g_now_seconds = time(NULL);
@@ -621,105 +645,146 @@ static void *time_caching_worker(void*args) {
621 } 645 }
622} 646}
623 647
624int main( int argc, char **argv ) { 648int main(int argc, char **argv) {
625 ot_ip6 serverip; 649 ot_ip6 serverip;
626 ot_net tmpnet; 650 ot_net tmpnet;
627 int bound = 0, scanon = 1; 651 int bound = 0, scanon = 1;
628 uint16_t tmpport; 652 uint16_t tmpport;
629 char * statefile = 0; 653 char *statefile = 0;
630 pthread_t thread_id; /* time cacher */ 654 pthread_t thread_id; /* time cacher */
631 655
632 memset( serverip, 0, sizeof(ot_ip6) ); 656 memset(serverip, 0, sizeof(ot_ip6));
633#ifdef WANT_V4_ONLY 657#ifdef WANT_V4_ONLY
634 serverip[10]=serverip[11]=-1; 658 serverip[10] = serverip[11] = -1;
635#endif 659#endif
636 660
637#ifdef WANT_DEV_RANDOM 661#ifdef WANT_DEV_RANDOM
638 srandomdev(); 662 srandomdev();
639#else 663#else
640 srandom( time(NULL) ); 664 srandom(time(NULL));
641#endif 665#endif
642 666
643 while( scanon ) { 667 while (scanon) {
644 switch( getopt( argc, argv, ":i:p:A:P:d:u:r:s:f:l:v" 668 switch (getopt(argc, argv,
669 ":i:p:A:P:d:u:r:s:f:l:v"
645#ifdef WANT_ACCESSLIST_BLACK 670#ifdef WANT_ACCESSLIST_BLACK
646"b:" 671 "b:"
647#elif defined( WANT_ACCESSLIST_WHITE ) 672#elif defined(WANT_ACCESSLIST_WHITE)
648"w:" 673 "w:"
649#endif 674#endif
650 "h" ) ) { 675 "h")) {
651 case -1 : scanon = 0; break; 676 case -1:
652 case 'i': 677 scanon = 0;
653 if( !scan_ip6( optarg, serverip )) { usage( argv[0] ); exit( 1 ); } 678 break;
654 break; 679 case 'i':
680 if (!scan_ip6(optarg, serverip)) {
681 usage(argv[0]);
682 exit(1);
683 }
684 break;
655#ifdef WANT_ACCESSLIST_BLACK 685#ifdef WANT_ACCESSLIST_BLACK
656 case 'b': set_config_option( &g_accesslist_filename, optarg); break; 686 case 'b':
657#elif defined( WANT_ACCESSLIST_WHITE ) 687 set_config_option(&g_accesslist_filename, optarg);
658 case 'w': set_config_option( &g_accesslist_filename, optarg); break; 688 break;
689#elif defined(WANT_ACCESSLIST_WHITE)
690 case 'w':
691 set_config_option(&g_accesslist_filename, optarg);
692 break;
659#endif 693#endif
660 case 'p': 694 case 'p':
661 if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); } 695 if (!scan_ushort(optarg, &tmpport)) {
662 ot_try_bind( serverip, tmpport, FLAG_TCP ); bound++; break; 696 usage(argv[0]);
663 case 'P': 697 exit(1);
664 if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); } 698 }
665 ot_try_bind( serverip, tmpport, FLAG_UDP ); bound++; break; 699 ot_try_bind(serverip, tmpport, FLAG_TCP);
700 bound++;
701 break;
702 case 'P':
703 if (!scan_ushort(optarg, &tmpport)) {
704 usage(argv[0]);
705 exit(1);
706 }
707 ot_try_bind(serverip, tmpport, FLAG_UDP);
708 bound++;
709 break;
666#ifdef WANT_SYNC_LIVE 710#ifdef WANT_SYNC_LIVE
667 case 's': 711 case 's':
668 if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); } 712 if (!scan_ushort(optarg, &tmpport)) {
669 livesync_bind_mcast( serverip, tmpport); break; 713 usage(argv[0]);
714 exit(1);
715 }
716 livesync_bind_mcast(serverip, tmpport);
717 break;
670#endif 718#endif
671 case 'd': set_config_option( &g_serverdir, optarg ); break; 719 case 'd':
672 case 'u': set_config_option( &g_serveruser, optarg ); break; 720 set_config_option(&g_serverdir, optarg);
673 case 'r': set_config_option( &g_redirecturl, optarg ); break; 721 break;
674 case 'l': statefile = optarg; break; 722 case 'u':
675 case 'A': 723 set_config_option(&g_serveruser, optarg);
676 if( !scan_ip6_net( optarg, &tmpnet )) { usage( argv[0] ); exit( 1 ); } 724 break;
677 accesslist_bless_net( &tmpnet, 0xffff ); /* Allow everything for now */ 725 case 'r':
678 break; 726 set_config_option(&g_redirecturl, optarg);
679 case 'f': bound += parse_configfile( optarg ); break; 727 break;
680 case 'h': help( argv[0] ); exit( 0 ); 728 case 'l':
681 case 'v': { 729 statefile = optarg;
682 char buffer[8192]; 730 break;
683 stats_return_tracker_version( buffer ); 731 case 'A':
684 fputs( buffer, stderr ); 732 if (!scan_ip6_net(optarg, &tmpnet)) {
685 exit( 0 ); 733 usage(argv[0]);
734 exit(1);
686 } 735 }
687 default: 736 accesslist_bless_net(&tmpnet, 0xffff); /* Allow everything for now */
688 case '?': usage( argv[0] ); exit( 1 ); 737 break;
738 case 'f':
739 bound += parse_configfile(optarg);
740 break;
741 case 'h':
742 help(argv[0]);
743 exit(0);
744 case 'v': {
745 char buffer[8192];
746 stats_return_tracker_version(buffer);
747 fputs(buffer, stderr);
748 exit(0);
749 }
750 default:
751 case '?':
752 usage(argv[0]);
753 exit(1);
689 } 754 }
690 } 755 }
691 756
692 /* Bind to our default tcp/udp ports */ 757 /* Bind to our default tcp/udp ports */
693 if( !bound) { 758 if (!bound) {
694 ot_try_bind( serverip, 6969, FLAG_TCP ); 759 ot_try_bind(serverip, 6969, FLAG_TCP);
695 ot_try_bind( serverip, 6969, FLAG_UDP ); 760 ot_try_bind(serverip, 6969, FLAG_UDP);
696 } 761 }
697 762
698#ifdef WANT_SYSLOGS 763#ifdef WANT_SYSLOGS
699 openlog( "opentracker", 0, LOG_USER ); 764 openlog("opentracker", 0, LOG_USER);
700 setlogmask(LOG_UPTO(LOG_INFO)); 765 setlogmask(LOG_UPTO(LOG_INFO));
701#endif 766#endif
702 767
703 if( drop_privileges( g_serveruser ? g_serveruser : "nobody", g_serverdir ) == -1 ) 768 if (drop_privileges(g_serveruser ? g_serveruser : "nobody", g_serverdir) == -1)
704 panic( "drop_privileges failed, exiting. Last error"); 769 panic("drop_privileges failed, exiting. Last error");
705 770
706 g_now_seconds = time( NULL ); 771 g_now_seconds = time(NULL);
707 pthread_create( &thread_id, NULL, time_caching_worker, NULL); 772 pthread_create(&thread_id, NULL, time_caching_worker, NULL);
708 773
709 /* Create our self pipe which allows us to interrupt mainloops 774 /* Create our self pipe which allows us to interrupt mainloops
710 io_wait in case some data is available to send out */ 775 io_wait in case some data is available to send out */
711 if( pipe( g_self_pipe ) == -1 ) 776 if (pipe(g_self_pipe) == -1)
712 panic( "selfpipe failed: " ); 777 panic("selfpipe failed: ");
713 if( !io_fd( g_self_pipe[0] ) ) 778 if (!io_fd(g_self_pipe[0]))
714 panic( "selfpipe io_fd failed: " ); 779 panic("selfpipe io_fd failed: ");
715 if( !io_fd( g_self_pipe[1] ) ) 780 if (!io_fd(g_self_pipe[1]))
716 panic( "selfpipe io_fd failed: " ); 781 panic("selfpipe io_fd failed: ");
717 io_setcookie( g_self_pipe[0], (void*)FLAG_SELFPIPE ); 782 io_setcookie(g_self_pipe[0], (void *)FLAG_SELFPIPE);
718 io_wantread( g_self_pipe[0] ); 783 io_wantread(g_self_pipe[0]);
719 784
720 defaul_signal_handlers( ); 785 defaul_signal_handlers();
721 /* Init all sub systems. This call may fail with an exit() */ 786 /* Init all sub systems. This call may fail with an exit() */
722 trackerlogic_init( ); 787 trackerlogic_init();
723 788
724#ifdef _DEBUG_RANDOMTORRENTS 789#ifdef _DEBUG_RANDOMTORRENTS
725 fprintf(stderr, "DEBUG: Generating %d random peers on random torrents. This may take a while. (Setting RANDOMTORRENTS in trackerlogic.h)\n", RANDOMTORRENTS); 790 fprintf(stderr, "DEBUG: Generating %d random peers on random torrents. This may take a while. (Setting RANDOMTORRENTS in trackerlogic.h)\n", RANDOMTORRENTS);
@@ -727,15 +792,15 @@ int main( int argc, char **argv ) {
727 fprintf(stderr, "... done.\n"); 792 fprintf(stderr, "... done.\n");
728#endif 793#endif
729 794
730 if( statefile ) 795 if (statefile)
731 load_state( statefile ); 796 load_state(statefile);
732 797
733 install_signal_handlers( ); 798 install_signal_handlers();
734 799
735 if( !g_udp_workers ) 800 if (!g_udp_workers)
736 udp_init( -1, 0 ); 801 udp_init(-1, 0);
737 802
738 server_mainloop( 0 ); 803 server_mainloop(0);
739 804
740 return 0; 805 return 0;
741} 806}