diff options
Diffstat (limited to 'ot_accesslist.c')
| -rw-r--r-- | ot_accesslist.c | 78 |
1 files changed, 42 insertions, 36 deletions
diff --git a/ot_accesslist.c b/ot_accesslist.c index e8e0476..86f9a7d 100644 --- a/ot_accesslist.c +++ b/ot_accesslist.c | |||
| @@ -1,7 +1,5 @@ | |||
| 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> |
| 2 | It is considered beerware. Prost. Skol. Cheers or whatever. | 2 | It is considered beerware. Prost. Skol. Cheers or whatever. */ |
| 3 | |||
| 4 | $id$ */ | ||
| 5 | 3 | ||
| 6 | /* System */ | 4 | /* System */ |
| 7 | #include <pthread.h> | 5 | #include <pthread.h> |
| @@ -273,7 +271,8 @@ static void *accesslist_worker(void *args) { | |||
| 273 | } | 271 | } |
| 274 | 272 | ||
| 275 | #ifdef WANT_DYNAMIC_ACCESSLIST | 273 | #ifdef WANT_DYNAMIC_ACCESSLIST |
| 276 | static pthread_t thread_adder_id, thread_deleter_id; | 274 | static pthread_t thread_adder_id, thread_deleter_id; |
| 275 | static _Atomic int adder_left, deleter_left; | ||
| 277 | static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_Atomic *adding_to, ot_accesslist *_Atomic *removing_from) { | 276 | static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_Atomic *adding_to, ot_accesslist *_Atomic *removing_from) { |
| 278 | struct stat st; | 277 | struct stat st; |
| 279 | 278 | ||
| @@ -297,6 +296,9 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 297 | ssize_t linelen; | 296 | ssize_t linelen; |
| 298 | 297 | ||
| 299 | if (!fifo) { | 298 | if (!fifo) { |
| 299 | /* Woken on purpose: the loop condition above decides what happens next */ | ||
| 300 | if (errno == EINTR) | ||
| 301 | continue; | ||
| 300 | fprintf(stderr, "Error when reading dynamic accesslists: Couldn't open FIFO at %s, error: %s\n", fifoname, strerror(errno)); | 302 | fprintf(stderr, "Error when reading dynamic accesslists: Couldn't open FIFO at %s, error: %s\n", fifoname, strerror(errno)); |
| 301 | return NULL; | 303 | return NULL; |
| 302 | } | 304 | } |
| @@ -324,8 +326,14 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 324 | ptrdiff_t off = exactmatch - (*removing_from)->list; | 326 | ptrdiff_t off = exactmatch - (*removing_from)->list; |
| 325 | ot_accesslist *accesslist_new = accesslist_make(*removing_from, (*removing_from)->size - 1); | 327 | ot_accesslist *accesslist_new = accesslist_make(*removing_from, (*removing_from)->size - 1); |
| 326 | if (accesslist_new) { | 328 | if (accesslist_new) { |
| 327 | memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off); | 329 | size_t after = (*removing_from)->size - off - 1; |
| 328 | memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, sizeof(ot_hash) * ((*removing_from)->size - off - 1)); | 330 | |
| 331 | /* Removing the only entry leaves a list with no room at all, and | ||
| 332 | memcpy may not be handed that even for nothing */ | ||
| 333 | if (off) | ||
| 334 | memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off); | ||
| 335 | if (after) | ||
| 336 | memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, sizeof(ot_hash) * after); | ||
| 329 | (*removing_from)->base = time_now_minutes(); | 337 | (*removing_from)->base = time_now_minutes(); |
| 330 | *removing_from = accesslist_new; | 338 | *removing_from = accesslist_new; |
| 331 | } | 339 | } |
| @@ -360,6 +368,7 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 360 | pthread_mutex_unlock(&g_accesslist_mutex); | 368 | pthread_mutex_unlock(&g_accesslist_mutex); |
| 361 | } | 369 | } |
| 362 | 370 | ||
| 371 | free(line); | ||
| 363 | fclose(fifo); | 372 | fclose(fifo); |
| 364 | } | 373 | } |
| 365 | return NULL; | 374 | return NULL; |
| @@ -367,11 +376,30 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 367 | 376 | ||
| 368 | static void *accesslist_adder_worker(void *args) { | 377 | static void *accesslist_adder_worker(void *args) { |
| 369 | (void)args; | 378 | (void)args; |
| 370 | return accesslist_adddel_worker(g_accesslist_pipe_add, &g_accesslist_add, &g_accesslist_delete); | 379 | accesslist_adddel_worker(g_accesslist_pipe_add, &g_accesslist_add, &g_accesslist_delete); |
| 380 | atomic_store(&adder_left, 1); | ||
| 381 | return NULL; | ||
| 371 | } | 382 | } |
| 372 | static void *accesslist_deleter_worker(void *args) { | 383 | static void *accesslist_deleter_worker(void *args) { |
| 373 | (void)args; | 384 | (void)args; |
| 374 | return accesslist_adddel_worker(g_accesslist_pipe_delete, &g_accesslist_delete, &g_accesslist_add); | 385 | accesslist_adddel_worker(g_accesslist_pipe_delete, &g_accesslist_delete, &g_accesslist_add); |
| 386 | atomic_store(&deleter_left, 1); | ||
| 387 | return NULL; | ||
| 388 | } | ||
| 389 | |||
| 390 | /* These sit in a blocking open or read on a FIFO, so they are woken the way | ||
| 391 | the other workers are, and the signal is repeated because it only | ||
| 392 | interrupts a call already under way. The pipe name is what says whether | ||
| 393 | the thread was ever started. */ | ||
| 394 | static void accesslist_stop_fifo_worker(pthread_t thread, _Atomic int *left, const char *pipe_name) { | ||
| 395 | if (!pipe_name) | ||
| 396 | return; | ||
| 397 | |||
| 398 | while (!atomic_load(left)) { | ||
| 399 | pthread_kill(thread, OT_SIGNAL_WAKE); | ||
| 400 | usleep(1000); | ||
| 401 | } | ||
| 402 | pthread_join(thread, NULL); | ||
| 375 | } | 403 | } |
| 376 | #endif | 404 | #endif |
| 377 | 405 | ||
| @@ -392,6 +420,12 @@ void accesslist_deinit(void) { | |||
| 392 | pthread_kill(thread_id, SIGHUP); | 420 | pthread_kill(thread_id, SIGHUP); |
| 393 | pthread_join(thread_id, NULL); | 421 | pthread_join(thread_id, NULL); |
| 394 | 422 | ||
| 423 | #ifdef WANT_DYNAMIC_ACCESSLIST | ||
| 424 | /* Before the lists they are reading are freed below */ | ||
| 425 | accesslist_stop_fifo_worker(thread_adder_id, &adder_left, g_accesslist_pipe_add); | ||
| 426 | accesslist_stop_fifo_worker(thread_deleter_id, &deleter_left, g_accesslist_pipe_delete); | ||
| 427 | #endif | ||
| 428 | |||
| 395 | pthread_mutex_lock(&g_accesslist_mutex); | 429 | pthread_mutex_lock(&g_accesslist_mutex); |
| 396 | 430 | ||
| 397 | g_accesslist = accesslist_free(g_accesslist); | 431 | g_accesslist = accesslist_free(g_accesslist); |
| @@ -467,34 +501,6 @@ void *accesslist_get_value_for_net(const ot_ip6 address, const ot_vector *vector | |||
| 467 | return (void *)net; | 501 | return (void *)net; |
| 468 | } | 502 | } |
| 469 | 503 | ||
| 470 | #ifdef WANT_FULLLOG_NETWORKS | ||
| 471 | static ot_vector g_lognets_list; | ||
| 472 | ot_log *g_logchain_first, *g_logchain_last; | ||
| 473 | static pthread_mutex_t g_lognets_list_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
| 474 | |||
| 475 | void loglist_add_network(const ot_net *net) { | ||
| 476 | pthread_mutex_lock(&g_lognets_list_mutex); | ||
| 477 | accesslist_set_value_for_net(net, &g_lognets_list, NULL, sizeof(ot_net)); | ||
| 478 | pthread_mutex_unlock(&g_lognets_list_mutex); | ||
| 479 | } | ||
| 480 | |||
| 481 | void loglist_reset(void) { | ||
| 482 | pthread_mutex_lock(&g_lognets_list_mutex); | ||
| 483 | free(g_lognets_list.data); | ||
| 484 | g_lognets_list.data = 0; | ||
| 485 | g_lognets_list.size = g_lognets_list.space = 0; | ||
| 486 | pthread_mutex_unlock(&g_lognets_list_mutex); | ||
| 487 | } | ||
| 488 | |||
| 489 | int loglist_check_address(const ot_ip6 address) { | ||
| 490 | int result; | ||
| 491 | pthread_mutex_lock(&g_lognets_list_mutex); | ||
| 492 | result = (NULL != accesslist_get_value_for_net(address, &g_lognets_list, sizeof(ot_net))); | ||
| 493 | pthread_mutex_unlock(&g_lognets_list_mutex); | ||
| 494 | return result; | ||
| 495 | } | ||
| 496 | #endif | ||
| 497 | |||
| 498 | #ifdef WANT_IP_FROM_PROXY | 504 | #ifdef WANT_IP_FROM_PROXY |
| 499 | typedef struct { | 505 | typedef struct { |
| 500 | ot_net *proxy; | 506 | ot_net *proxy; |
