summaryrefslogtreecommitdiff
path: root/ot_accesslist.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_accesslist.c')
-rw-r--r--ot_accesslist.c327
1 files changed, 169 insertions, 158 deletions
diff --git a/ot_accesslist.c b/ot_accesslist.c
index 7df503f..4b88c40 100644
--- a/ot_accesslist.c
+++ b/ot_accesslist.c
@@ -5,34 +5,35 @@
5 5
6/* System */ 6/* System */
7#include <pthread.h> 7#include <pthread.h>
8#include <signal.h>
9#include <stdio.h>
8#include <stdlib.h> 10#include <stdlib.h>
9#include <string.h> 11#include <string.h>
10#include <stdio.h>
11#include <signal.h>
12#include <unistd.h> 12#include <unistd.h>
13#ifdef WANT_DYNAMIC_ACCESSLIST 13#ifdef WANT_DYNAMIC_ACCESSLIST
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <errno.h> 14#include <errno.h>
15#include <sys/stat.h>
16#include <sys/types.h>
17#endif 17#endif
18 18
19/* Libowfat */ 19/* Libowfat */
20#include "byte.h" 20#include "byte.h"
21#include "scan.h" 21#include "fmt.h"
22#include "ip6.h" 22#include "ip6.h"
23#include "mmap.h" 23#include "mmap.h"
24#include "scan.h"
24 25
25/* Opentracker */ 26/* Opentracker */
26#include "trackerlogic.h"
27#include "ot_accesslist.h" 27#include "ot_accesslist.h"
28#include "ot_vector.h" 28#include "ot_vector.h"
29#include "trackerlogic.h"
29 30
30/* GLOBAL VARIABLES */ 31/* GLOBAL VARIABLES */
31#ifdef WANT_ACCESSLIST 32#ifdef WANT_ACCESSLIST
32char *g_accesslist_filename = NULL; 33char *g_accesslist_filename = NULL;
33#ifdef WANT_DYNAMIC_ACCESSLIST 34#ifdef WANT_DYNAMIC_ACCESSLIST
34char *g_accesslist_pipe_add = NULL; 35char *g_accesslist_pipe_add = NULL;
35char *g_accesslist_pipe_delete = NULL; 36char *g_accesslist_pipe_delete = NULL;
36#endif 37#endif
37static pthread_mutex_t g_accesslist_mutex; 38static pthread_mutex_t g_accesslist_mutex;
38 39
@@ -54,20 +55,18 @@ struct ot_accesslist {
54 ot_time base; 55 ot_time base;
55 ot_accesslist *next; 56 ot_accesslist *next;
56}; 57};
57static ot_accesslist * _Atomic g_accesslist = NULL; 58static ot_accesslist *_Atomic g_accesslist = NULL;
58#ifdef WANT_DYNAMIC_ACCESSLIST 59#ifdef WANT_DYNAMIC_ACCESSLIST
59static ot_accesslist * _Atomic g_accesslist_add = NULL; 60static ot_accesslist *_Atomic g_accesslist_add = NULL;
60static ot_accesslist * _Atomic g_accesslist_delete = NULL; 61static ot_accesslist *_Atomic g_accesslist_delete = NULL;
61#endif 62#endif
62 63
63/* Helpers to work on access lists */ 64/* Helpers to work on access lists */
64static int vector_compare_hash(const void *hash1, const void *hash2 ) { 65static int vector_compare_hash(const void *hash1, const void *hash2) { return memcmp(hash1, hash2, OT_HASH_COMPARE_SIZE); }
65 return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE );
66}
67 66
68static ot_accesslist * accesslist_free(ot_accesslist *accesslist) { 67static ot_accesslist *accesslist_free(ot_accesslist *accesslist) {
69 while (accesslist) { 68 while (accesslist) {
70 ot_accesslist * this_accesslist = accesslist; 69 ot_accesslist *this_accesslist = accesslist;
71 accesslist = this_accesslist->next; 70 accesslist = this_accesslist->next;
72 free(this_accesslist->list); 71 free(this_accesslist->list);
73 free(this_accesslist); 72 free(this_accesslist);
@@ -75,8 +74,8 @@ static ot_accesslist * accesslist_free(ot_accesslist *accesslist) {
75 return NULL; 74 return NULL;
76} 75}
77 76
78static ot_accesslist * accesslist_make(ot_accesslist *next, size_t size) { 77static ot_accesslist *accesslist_make(ot_accesslist *next, size_t size) {
79 ot_accesslist * accesslist_new = malloc(sizeof(ot_accesslist)); 78 ot_accesslist *accesslist_new = malloc(sizeof(ot_accesslist));
80 if (accesslist_new) { 79 if (accesslist_new) {
81 accesslist_new->list = size ? malloc(sizeof(ot_hash) * size) : NULL; 80 accesslist_new->list = size ? malloc(sizeof(ot_hash) * size) : NULL;
82 accesslist_new->size = size; 81 accesslist_new->size = size;
@@ -101,76 +100,77 @@ static void accesslist_clean(ot_accesslist *accesslist) {
101} 100}
102 101
103/* Read initial access list */ 102/* Read initial access list */
104static void accesslist_readfile( void ) { 103static void accesslist_readfile(void) {
105 ot_accesslist * accesslist_new; 104 ot_accesslist *accesslist_new;
106 ot_hash *info_hash; 105 ot_hash *info_hash;
107 const char *map, *map_end, *read_offs; 106 const char *map, *map_end, *read_offs;
108 size_t maplen; 107 size_t maplen;
109 108
110 if( ( map = mmap_read( g_accesslist_filename, &maplen ) ) == NULL ) { 109 if ((map = mmap_read(g_accesslist_filename, &maplen)) == NULL) {
111 char *wd = getcwd( NULL, 0 ); 110 char *wd = getcwd(NULL, 0);
112 fprintf( stderr, "Warning: Can't open accesslist file: %s (but will try to create it later, if necessary and possible).\nPWD: %s\n", g_accesslist_filename, wd ); 111 fprintf(stderr, "Warning: Can't open accesslist file: %s (but will try to create it later, if necessary and possible).\nPWD: %s\n", g_accesslist_filename, wd);
113 free( wd ); 112 free(wd);
114 return; 113 return;
115 } 114 }
116 115
117 /* You need at least 41 bytes to pass an info_hash, make enough room 116 /* You need at least 41 bytes to pass an info_hash, make enough room
118 for the maximum amount of them */ 117 for the maximum amount of them */
119 accesslist_new = accesslist_make(g_accesslist, maplen / 41); 118 accesslist_new = accesslist_make(g_accesslist, maplen / 41);
120 if( !accesslist_new ) { 119 if (!accesslist_new) {
121 fprintf( stderr, "Warning: Not enough memory to allocate %zd bytes for accesslist buffer. May succeed later.\n", ( maplen / 41 ) * 20 ); 120 fprintf(stderr, "Warning: Not enough memory to allocate %zd bytes for accesslist buffer. May succeed later.\n", (maplen / 41) * 20);
122 mmap_unmap( map, maplen); 121 mmap_unmap(map, maplen);
123 return; 122 return;
124 } 123 }
125 info_hash = accesslist_new->list; 124 info_hash = accesslist_new->list;
126 125
127 /* No use to scan if there's not enough room for another full info_hash */ 126 /* No use to scan if there's not enough room for another full info_hash */
128 map_end = map + maplen - 40; 127 map_end = map + maplen - 40;
129 read_offs = map; 128 read_offs = map;
130 129
131 /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" */ 130 /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" */
132 while( read_offs <= map_end ) { 131 while (read_offs <= map_end) {
133 int i; 132 int i;
134 for( i=0; i<(int)sizeof(ot_hash); ++i ) { 133 for (i = 0; i < (int)sizeof(ot_hash); ++i) {
135 int eger1 = scan_fromhex( (unsigned char)read_offs[ 2*i ] ); 134 int eger1 = scan_fromhex((unsigned char)read_offs[2 * i]);
136 int eger2 = scan_fromhex( (unsigned char)read_offs[ 1 + 2*i ] ); 135 int eger2 = scan_fromhex((unsigned char)read_offs[1 + 2 * i]);
137 if( eger1 < 0 || eger2 < 0 ) 136 if (eger1 < 0 || eger2 < 0)
138 break; 137 break;
139 (*info_hash)[i] = (uint8_t)(eger1 * 16 + eger2); 138 (*info_hash)[i] = (uint8_t)(eger1 * 16 + eger2);
140 } 139 }
141 140
142 if( i == sizeof(ot_hash) ) { 141 if (i == sizeof(ot_hash)) {
143 read_offs += 40; 142 read_offs += 40;
144 143
145 /* Append accesslist to accesslist vector */ 144 /* Append accesslist to accesslist vector */
146 if( read_offs == map_end || scan_fromhex( (unsigned char)*read_offs ) < 0 ) 145 if (read_offs == map_end || scan_fromhex((unsigned char)*read_offs) < 0)
147 ++info_hash; 146 ++info_hash;
148 } 147 }
149 148
150 /* Find start of next line */ 149 /* Find start of next line */
151 while( read_offs <= map_end && *(read_offs++) != '\n' ); 150 while (read_offs <= map_end && *(read_offs++) != '\n')
151 ;
152 } 152 }
153#ifdef _DEBUG 153#ifdef _DEBUG
154 fprintf( stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new->list) ); 154 fprintf(stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new->list));
155#endif 155#endif
156 156
157 mmap_unmap( map, maplen); 157 mmap_unmap(map, maplen);
158 158
159 qsort( accesslist_new->list, info_hash - accesslist_new->list, sizeof( *info_hash ), vector_compare_hash ); 159 qsort(accesslist_new->list, info_hash - accesslist_new->list, sizeof(*info_hash), vector_compare_hash);
160 accesslist_new->size = info_hash - accesslist_new->list; 160 accesslist_new->size = info_hash - accesslist_new->list;
161 161
162 /* Now exchange the accesslist vector in the least race condition prone way */ 162 /* Now exchange the accesslist vector in the least race condition prone way */
163 pthread_mutex_lock(&g_accesslist_mutex); 163 pthread_mutex_lock(&g_accesslist_mutex);
164 accesslist_new->next = g_accesslist; 164 accesslist_new->next = g_accesslist;
165 g_accesslist = accesslist_new; /* Only now set a new list */ 165 g_accesslist = accesslist_new; /* Only now set a new list */
166 166
167#ifdef WANT_DYNAMIC_ACCESSLIST 167#ifdef WANT_DYNAMIC_ACCESSLIST
168 /* If we have dynamic accesslists, reloading a new one will always void the add/delete lists. 168 /* If we have dynamic accesslists, reloading a new one will always void the add/delete lists.
169 Insert empty ones at the list head */ 169 Insert empty ones at the list head */
170 if (g_accesslist_add && (accesslist_new = accesslist_make(g_accesslist_add, 0)) != NULL) 170 if (g_accesslist_add && (accesslist_new = accesslist_make(g_accesslist_add, 0)) != NULL)
171 g_accesslist_add = accesslist_new; 171 g_accesslist_add = accesslist_new;
172 if (g_accesslist_delete && (accesslist_new = accesslist_make(g_accesslist_delete, 0)) != NULL) 172 if (g_accesslist_delete && (accesslist_new = accesslist_make(g_accesslist_delete, 0)) != NULL)
173 g_accesslist_delete = accesslist_new; 173 g_accesslist_delete = accesslist_new;
174#endif 174#endif
175 175
176 accesslist_clean(g_accesslist); 176 accesslist_clean(g_accesslist);
@@ -178,26 +178,26 @@ static void accesslist_readfile( void ) {
178 pthread_mutex_unlock(&g_accesslist_mutex); 178 pthread_mutex_unlock(&g_accesslist_mutex);
179} 179}
180 180
181int accesslist_hashisvalid( ot_hash hash ) { 181int accesslist_hashisvalid(ot_hash hash) {
182 /* Get working copy of current access list */ 182 /* Get working copy of current access list */
183 ot_accesslist * accesslist = g_accesslist; 183 ot_accesslist *accesslist = g_accesslist;
184#ifdef WANT_DYNAMIC_ACCESSLIST 184#ifdef WANT_DYNAMIC_ACCESSLIST
185 ot_accesslist * accesslist_add, * accesslist_delete; 185 ot_accesslist *accesslist_add, *accesslist_delete;
186#endif 186#endif
187 void * exactmatch = NULL; 187 void *exactmatch = NULL;
188 188
189 if (accesslist) 189 if (accesslist)
190 exactmatch = bsearch( hash, accesslist->list, accesslist->size, OT_HASH_COMPARE_SIZE, vector_compare_hash ); 190 exactmatch = bsearch(hash, accesslist->list, accesslist->size, OT_HASH_COMPARE_SIZE, vector_compare_hash);
191 191
192#ifdef WANT_DYNAMIC_ACCESSLIST 192#ifdef WANT_DYNAMIC_ACCESSLIST
193 /* If we had no match on the main list, scan the list of dynamically added hashes */ 193 /* If we had no match on the main list, scan the list of dynamically added hashes */
194 accesslist_add = g_accesslist_add; 194 accesslist_add = g_accesslist_add;
195 if ((exactmatch == NULL) && accesslist_add) 195 if ((exactmatch == NULL) && accesslist_add)
196 exactmatch = bsearch( hash, accesslist_add->list, accesslist_add->size, OT_HASH_COMPARE_SIZE, vector_compare_hash ); 196 exactmatch = bsearch(hash, accesslist_add->list, accesslist_add->size, OT_HASH_COMPARE_SIZE, vector_compare_hash);
197 197
198 /* If we found a matching hash on the main list, scan the list of dynamically deleted hashes */ 198 /* If we found a matching hash on the main list, scan the list of dynamically deleted hashes */
199 accesslist_delete = g_accesslist_delete; 199 accesslist_delete = g_accesslist_delete;
200 if ((exactmatch != NULL) && accesslist_delete && bsearch( hash, accesslist_add->list, accesslist_add->size, OT_HASH_COMPARE_SIZE, vector_compare_hash )) 200 if ((exactmatch != NULL) && accesslist_delete && bsearch(hash, accesslist_add->list, accesslist_add->size, OT_HASH_COMPARE_SIZE, vector_compare_hash))
201 exactmatch = NULL; 201 exactmatch = NULL;
202#endif 202#endif
203 203
@@ -208,31 +208,32 @@ int accesslist_hashisvalid( ot_hash hash ) {
208#endif 208#endif
209} 209}
210 210
211static void * accesslist_worker( void * args ) { 211static void *accesslist_worker(void *args) {
212 int sig; 212 int sig;
213 sigset_t signal_mask; 213 sigset_t signal_mask;
214 214
215 sigemptyset(&signal_mask); 215 sigemptyset(&signal_mask);
216 sigaddset(&signal_mask, SIGHUP); 216 sigaddset(&signal_mask, SIGHUP);
217 217
218 (void)args; 218 (void)args;
219 219
220 while( 1 ) { 220 while (1) {
221 if (!g_opentracker_running) 221 if (!g_opentracker_running)
222 return NULL; 222 return NULL;
223 223
224 /* Initial attempt to read accesslist */ 224 /* Initial attempt to read accesslist */
225 accesslist_readfile( ); 225 accesslist_readfile();
226 226
227 /* Wait for signals */ 227 /* Wait for signals */
228 while( sigwait (&signal_mask, &sig) != 0 && sig != SIGHUP ); 228 while (sigwait(&signal_mask, &sig) != 0 && sig != SIGHUP)
229 ;
229 } 230 }
230 return NULL; 231 return NULL;
231} 232}
232 233
233#ifdef WANT_DYNAMIC_ACCESSLIST 234#ifdef WANT_DYNAMIC_ACCESSLIST
234static pthread_t thread_adder_id, thread_deleter_id; 235static pthread_t thread_adder_id, thread_deleter_id;
235static void * accesslist_adddel_worker(char * fifoname, ot_accesslist * _Atomic * adding_to, ot_accesslist * _Atomic * removing_from) { 236static void *accesslist_adddel_worker(char *fifoname, ot_accesslist *_Atomic *adding_to, ot_accesslist *_Atomic *removing_from) {
236 struct stat st; 237 struct stat st;
237 238
238 if (!stat(fifoname, &st)) { 239 if (!stat(fifoname, &st)) {
@@ -249,9 +250,9 @@ static void * accesslist_adddel_worker(char * fifoname, ot_accesslist * _Atomic
249 } 250 }
250 251
251 while (g_opentracker_running) { 252 while (g_opentracker_running) {
252 FILE * fifo = fopen(fifoname, "r"); 253 FILE *fifo = fopen(fifoname, "r");
253 char *line = NULL; 254 char *line = NULL;
254 size_t linecap = 0; 255 size_t linecap = 0;
255 ssize_t linelen; 256 ssize_t linelen;
256 257
257 if (!fifo) { 258 if (!fifo) {
@@ -261,7 +262,7 @@ static void * accesslist_adddel_worker(char * fifoname, ot_accesslist * _Atomic
261 262
262 while ((linelen = getline(&line, &linecap, fifo)) > 0) { 263 while ((linelen = getline(&line, &linecap, fifo)) > 0) {
263 ot_hash info_hash; 264 ot_hash info_hash;
264 int i; 265 int i;
265 266
266 printf("Got line %*s", (int)linelen, line); 267 printf("Got line %*s", (int)linelen, line);
267 /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" 268 /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*"
@@ -269,15 +270,15 @@ static void * accesslist_adddel_worker(char * fifoname, ot_accesslist * _Atomic
269 if (linelen < 41) 270 if (linelen < 41)
270 continue; 271 continue;
271 272
272 for( i=0; i<(int)sizeof(ot_hash); ++i ) { 273 for (i = 0; i < (int)sizeof(ot_hash); ++i) {
273 int eger1 = scan_fromhex( (unsigned char)line[ 2*i ] ); 274 int eger1 = scan_fromhex((unsigned char)line[2 * i]);
274 int eger2 = scan_fromhex( (unsigned char)line[ 1 + 2*i ] ); 275 int eger2 = scan_fromhex((unsigned char)line[1 + 2 * i]);
275 if( eger1 < 0 || eger2 < 0 ) 276 if (eger1 < 0 || eger2 < 0)
276 break; 277 break;
277 ((uint8_t*)info_hash)[i] = (uint8_t)(eger1 * 16 + eger2); 278 ((uint8_t *)info_hash)[i] = (uint8_t)(eger1 * 16 + eger2);
278 } 279 }
279printf("parsed info_hash %20s\n", info_hash); 280 printf("parsed info_hash %20s\n", info_hash);
280 if( i != sizeof(ot_hash) ) 281 if (i != sizeof(ot_hash))
281 continue; 282 continue;
282 283
283 /* From now on we modify g_accesslist_add and g_accesslist_delete, so prevent the 284 /* From now on we modify g_accesslist_add and g_accesslist_delete, so prevent the
@@ -286,10 +287,10 @@ printf("parsed info_hash %20s\n", info_hash);
286 287
287 /* If the info hash is in the removing_from list, create a new head without that entry */ 288 /* If the info hash is in the removing_from list, create a new head without that entry */
288 if (*removing_from && (*removing_from)->list) { 289 if (*removing_from && (*removing_from)->list) {
289 ot_hash * exactmatch = bsearch( info_hash, (*removing_from)->list, (*removing_from)->size, OT_HASH_COMPARE_SIZE, vector_compare_hash ); 290 ot_hash *exactmatch = bsearch(info_hash, (*removing_from)->list, (*removing_from)->size, OT_HASH_COMPARE_SIZE, vector_compare_hash);
290 if (exactmatch) { 291 if (exactmatch) {
291 ptrdiff_t off = exactmatch - (*removing_from)->list; 292 ptrdiff_t off = exactmatch - (*removing_from)->list;
292 ot_accesslist * accesslist_new = accesslist_make(*removing_from, (*removing_from)->size - 1); 293 ot_accesslist *accesslist_new = accesslist_make(*removing_from, (*removing_from)->size - 1);
293 if (accesslist_new) { 294 if (accesslist_new) {
294 memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off); 295 memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off);
295 memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, (*removing_from)->size - off - 1); 296 memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, (*removing_from)->size - off - 1);
@@ -300,19 +301,19 @@ printf("parsed info_hash %20s\n", info_hash);
300 301
301 /* Simple case: there's no adding_to list yet, create one with one member */ 302 /* Simple case: there's no adding_to list yet, create one with one member */
302 if (!*adding_to) { 303 if (!*adding_to) {
303 ot_accesslist * accesslist_new = accesslist_make(NULL, 1); 304 ot_accesslist *accesslist_new = accesslist_make(NULL, 1);
304 if (accesslist_new) { 305 if (accesslist_new) {
305 memcpy(accesslist_new->list, info_hash, sizeof(ot_hash)); 306 memcpy(accesslist_new->list, info_hash, sizeof(ot_hash));
306 *adding_to = accesslist_new; 307 *adding_to = accesslist_new;
307 } 308 }
308 } else { 309 } else {
309 int exactmatch = 0; 310 int exactmatch = 0;
310 ot_hash * insert_point = binary_search( info_hash, (*adding_to)->list, (*adding_to)->size, OT_HASH_COMPARE_SIZE, sizeof(ot_hash), &exactmatch ); 311 ot_hash *insert_point = binary_search(info_hash, (*adding_to)->list, (*adding_to)->size, OT_HASH_COMPARE_SIZE, sizeof(ot_hash), &exactmatch);
311 312
312 /* Only if the info hash is not in the adding_to list, create a new head with that entry */ 313 /* Only if the info hash is not in the adding_to list, create a new head with that entry */
313 if (!exactmatch) { 314 if (!exactmatch) {
314 ot_accesslist * accesslist_new = accesslist_make(*adding_to, (*adding_to)->size + 1); 315 ot_accesslist *accesslist_new = accesslist_make(*adding_to, (*adding_to)->size + 1);
315 ptrdiff_t off = insert_point - (*adding_to)->list; 316 ptrdiff_t off = insert_point - (*adding_to)->list;
316 if (accesslist_new) { 317 if (accesslist_new) {
317 memcpy(accesslist_new->list, (*adding_to)->list, sizeof(ot_hash) * off); 318 memcpy(accesslist_new->list, (*adding_to)->list, sizeof(ot_hash) * off);
318 memcpy(accesslist_new->list + off, info_hash, sizeof(info_hash)); 319 memcpy(accesslist_new->list + off, info_hash, sizeof(info_hash));
@@ -330,29 +331,29 @@ printf("parsed info_hash %20s\n", info_hash);
330 return NULL; 331 return NULL;
331} 332}
332 333
333static void * accesslist_adder_worker( void * args ) { 334static void *accesslist_adder_worker(void *args) {
334 (void)args; 335 (void)args;
335 return accesslist_adddel_worker(g_accesslist_pipe_add, &g_accesslist_add, &g_accesslist_delete); 336 return accesslist_adddel_worker(g_accesslist_pipe_add, &g_accesslist_add, &g_accesslist_delete);
336} 337}
337static void * accesslist_deleter_worker( void * args ) { 338static void *accesslist_deleter_worker(void *args) {
338 (void)args; 339 (void)args;
339 return accesslist_adddel_worker(g_accesslist_pipe_delete, &g_accesslist_delete, &g_accesslist_add); 340 return accesslist_adddel_worker(g_accesslist_pipe_delete, &g_accesslist_delete, &g_accesslist_add);
340} 341}
341#endif 342#endif
342 343
343static pthread_t thread_id; 344static pthread_t thread_id;
344void accesslist_init( ) { 345void accesslist_init() {
345 pthread_mutex_init(&g_accesslist_mutex, NULL); 346 pthread_mutex_init(&g_accesslist_mutex, NULL);
346 pthread_create( &thread_id, NULL, accesslist_worker, NULL ); 347 pthread_create(&thread_id, NULL, accesslist_worker, NULL);
347#ifdef WANT_DYNAMIC_ACCESSLIST 348#ifdef WANT_DYNAMIC_ACCESSLIST
348 if (g_accesslist_pipe_add) 349 if (g_accesslist_pipe_add)
349 pthread_create( &thread_adder_id, NULL, accesslist_adder_worker, NULL ); 350 pthread_create(&thread_adder_id, NULL, accesslist_adder_worker, NULL);
350 if (g_accesslist_pipe_delete) 351 if (g_accesslist_pipe_delete)
351 pthread_create( &thread_deleter_id, NULL, accesslist_deleter_worker, NULL ); 352 pthread_create(&thread_deleter_id, NULL, accesslist_deleter_worker, NULL);
352#endif 353#endif
353} 354}
354 355
355void accesslist_deinit( void ) { 356void accesslist_deinit(void) {
356 /* Wake up sleeping worker */ 357 /* Wake up sleeping worker */
357 pthread_kill(thread_id, SIGHUP); 358 pthread_kill(thread_id, SIGHUP);
358 359
@@ -361,16 +362,16 @@ void accesslist_deinit( void ) {
361 g_accesslist = accesslist_free(g_accesslist); 362 g_accesslist = accesslist_free(g_accesslist);
362 363
363#ifdef WANT_DYNAMIC_ACCESSLIST 364#ifdef WANT_DYNAMIC_ACCESSLIST
364 g_accesslist_add = accesslist_free(g_accesslist_add); 365 g_accesslist_add = accesslist_free(g_accesslist_add);
365 g_accesslist_delete = accesslist_free(g_accesslist_delete); 366 g_accesslist_delete = accesslist_free(g_accesslist_delete);
366#endif 367#endif
367 368
368 pthread_mutex_unlock(&g_accesslist_mutex); 369 pthread_mutex_unlock(&g_accesslist_mutex);
369 pthread_cancel( thread_id ); 370 pthread_cancel(thread_id);
370 pthread_mutex_destroy(&g_accesslist_mutex); 371 pthread_mutex_destroy(&g_accesslist_mutex);
371} 372}
372 373
373void accesslist_cleanup( void ) { 374void accesslist_cleanup(void) {
374 pthread_mutex_lock(&g_accesslist_mutex); 375 pthread_mutex_lock(&g_accesslist_mutex);
375 376
376 accesslist_clean(g_accesslist); 377 accesslist_clean(g_accesslist);
@@ -383,35 +384,34 @@ void accesslist_cleanup( void ) {
383} 384}
384#endif 385#endif
385 386
386int address_in_net( const ot_ip6 address, const ot_net *net ) { 387int address_in_net(const ot_ip6 address, const ot_net *net) {
387 int bits = net->bits; 388 int bits = net->bits, checkbits = (0x7f00 >> (bits & 7));
388 int result = memcmp( address, &net->address, bits >> 3 ); 389 int result = memcmp(address, &net->address, bits >> 3);
389 if( !result && ( bits & 7 ) ) 390 if (!result && (bits & 7))
390 result = ( ( 0x7f00 >> ( bits & 7 ) ) & address[bits>>3] ) - net->address[bits>>3]; 391 result = (checkbits & address[bits >> 3]) - (checkbits & net->address[bits >> 3]);
391 return result == 0; 392 return result == 0;
392} 393}
393 394
394void *set_value_for_net( const ot_net *net, ot_vector *vector, const void *value, const size_t member_size ) { 395void *set_value_for_net(const ot_net *net, ot_vector *vector, const void *value, const size_t member_size) {
395 size_t i; 396 size_t i;
396 int exactmatch; 397 int exactmatch;
397 398
398 /* Caller must have a concept of ot_net in it's member */ 399 /* Caller must have a concept of ot_net in it's member */
399 if( member_size < sizeof(ot_net) ) 400 if (member_size < sizeof(ot_net))
400 return 0; 401 return 0;
401 402
402 /* Check each net in vector for overlap */ 403 /* Check each net in vector for overlap */
403 uint8_t *member = ((uint8_t*)vector->data); 404 uint8_t *member = ((uint8_t *)vector->data);
404 for( i=0; i<vector->size; ++i ) { 405 for (i = 0; i < vector->size; ++i) {
405 if( address_in_net( *(ot_ip6*)member, net ) || 406 if (address_in_net(*(ot_ip6 *)member, net) || address_in_net(net->address, (ot_net *)member))
406 address_in_net( net->address, (ot_net*)member ) )
407 return 0; 407 return 0;
408 member += member_size; 408 member += member_size;
409 } 409 }
410 410
411 member = vector_find_or_insert( vector, (void*)net, member_size, sizeof(ot_net), &exactmatch ); 411 member = vector_find_or_insert(vector, (void *)net, member_size, sizeof(ot_net), &exactmatch);
412 if( member ) { 412 if (member) {
413 memcpy( member, net, sizeof(ot_net)); 413 memcpy(member, net, sizeof(ot_net));
414 memcpy( member + sizeof(ot_net), value, member_size - sizeof(ot_net)); 414 memcpy(member + sizeof(ot_net), value, member_size - sizeof(ot_net));
415 } 415 }
416 416
417 return member; 417 return member;
@@ -419,43 +419,43 @@ void *set_value_for_net( const ot_net *net, ot_vector *vector, const void *value
419 419
420/* Takes a vector filled with { ot_net net, uint8_t[x] value }; 420/* Takes a vector filled with { ot_net net, uint8_t[x] value };
421 Returns value associated with the net, or NULL if not found */ 421 Returns value associated with the net, or NULL if not found */
422void *get_value_for_net( const ot_ip6 address, const ot_vector *vector, const size_t member_size ) { 422void *get_value_for_net(const ot_ip6 address, const ot_vector *vector, const size_t member_size) {
423 int exactmatch; 423 int exactmatch;
424 /* This binary search will return a pointer to the first non-containing network... */ 424 /* This binary search will return a pointer to the first non-containing network... */
425 ot_net *net = binary_search( address, vector->data, vector->size, member_size, sizeof(ot_ip6), &exactmatch ); 425 ot_net *net = binary_search(address, vector->data, vector->size, member_size, sizeof(ot_ip6), &exactmatch);
426 if( !net ) 426 if (!net)
427 return NULL; 427 return NULL;
428 /* ... so we'll need to move back one step unless we've exactly hit the first address in network */ 428 /* ... so we'll need to move back one step unless we've exactly hit the first address in network */
429 if( !exactmatch && ( (void*)net > vector->data ) ) 429 if (!exactmatch && ((void *)net > vector->data))
430 --net; 430 --net;
431 if( !address_in_net( address, net ) ) 431 if (!address_in_net(address, net))
432 return NULL; 432 return NULL;
433 return (void*)net; 433 return (void *)net;
434} 434}
435 435
436#ifdef WANT_FULLLOG_NETWORKS 436#ifdef WANT_FULLLOG_NETWORKS
437static ot_vector g_lognets_list; 437static ot_vector g_lognets_list;
438ot_log *g_logchain_first, *g_logchain_last; 438ot_log *g_logchain_first, *g_logchain_last;
439
440static pthread_mutex_t g_lognets_list_mutex = PTHREAD_MUTEX_INITIALIZER; 439static pthread_mutex_t g_lognets_list_mutex = PTHREAD_MUTEX_INITIALIZER;
441void loglist_add_network( const ot_net *net ) { 440
441void loglist_add_network(const ot_net *net) {
442 pthread_mutex_lock(&g_lognets_list_mutex); 442 pthread_mutex_lock(&g_lognets_list_mutex);
443 set_value_for_net( net, &g_lognets_list, NULL, sizeof(ot_net)); 443 set_value_for_net(net, &g_lognets_list, NULL, sizeof(ot_net));
444 pthread_mutex_unlock(&g_lognets_list_mutex); 444 pthread_mutex_unlock(&g_lognets_list_mutex);
445} 445}
446 446
447void loglist_reset( ) { 447void loglist_reset() {
448 pthread_mutex_lock(&g_lognets_list_mutex); 448 pthread_mutex_lock(&g_lognets_list_mutex);
449 free( g_lognets_list.data ); 449 free(g_lognets_list.data);
450 g_lognets_list.data = 0; 450 g_lognets_list.data = 0;
451 g_lognets_list.size = g_lognets_list.space = 0; 451 g_lognets_list.size = g_lognets_list.space = 0;
452 pthread_mutex_unlock(&g_lognets_list_mutex); 452 pthread_mutex_unlock(&g_lognets_list_mutex);
453} 453}
454 454
455int loglist_check_address( const ot_ip6 address ) { 455int loglist_check_address(const ot_ip6 address) {
456 int result; 456 int result;
457 pthread_mutex_lock(&g_lognets_list_mutex); 457 pthread_mutex_lock(&g_lognets_list_mutex);
458 result = ( NULL != get_value_for_net( address, &g_lognets_list, sizeof(ot_net)) ); 458 result = (NULL != get_value_for_net(address, &g_lognets_list, sizeof(ot_net)));
459 pthread_mutex_unlock(&g_lognets_list_mutex); 459 pthread_mutex_unlock(&g_lognets_list_mutex);
460 return result; 460 return result;
461} 461}
@@ -463,44 +463,44 @@ int loglist_check_address( const ot_ip6 address ) {
463 463
464#ifdef WANT_IP_FROM_PROXY 464#ifdef WANT_IP_FROM_PROXY
465typedef struct { 465typedef struct {
466 ot_net *proxy; 466 ot_net *proxy;
467 ot_vector networks; 467 ot_vector networks;
468} ot_proxymap; 468} ot_proxymap;
469 469
470static ot_vector g_proxies_list; 470static ot_vector g_proxies_list;
471static pthread_mutex_t g_proxies_list_mutex = PTHREAD_MUTEX_INITIALIZER; 471static pthread_mutex_t g_proxies_list_mutex = PTHREAD_MUTEX_INITIALIZER;
472 472
473int proxylist_add_network( const ot_net *proxy, const ot_net *net ) { 473int proxylist_add_network(const ot_net *proxy, const ot_net *net) {
474 ot_proxymap *map; 474 ot_proxymap *map;
475 int exactmatch, result = 1; 475 int exactmatch, result = 1;
476 pthread_mutex_lock(&g_proxies_list_mutex); 476 pthread_mutex_lock(&g_proxies_list_mutex);
477 477
478 /* If we have a direct hit, use and extend the vector there */ 478 /* If we have a direct hit, use and extend the vector there */
479 map = binary_search( proxy, g_proxies_list.data, g_proxies_list.size, sizeof(ot_proxymap), sizeof(ot_net), &exactmatch ); 479 map = binary_search(proxy, g_proxies_list.data, g_proxies_list.size, sizeof(ot_proxymap), sizeof(ot_net), &exactmatch);
480 480
481 if( !map || !exactmatch ) { 481 if (!map || !exactmatch) {
482 /* else see, if we've got overlapping networks 482 /* else see, if we've got overlapping networks
483 and get a new empty vector if not */ 483 and get a new empty vector if not */
484 ot_vector empty; 484 ot_vector empty;
485 memset( &empty, 0, sizeof( ot_vector ) ); 485 memset(&empty, 0, sizeof(ot_vector));
486 map = set_value_for_net( proxy, &g_proxies_list, &empty, sizeof(ot_proxymap)); 486 map = set_value_for_net(proxy, &g_proxies_list, &empty, sizeof(ot_proxymap));
487 } 487 }
488 488
489 if( map && set_value_for_net( net, &map->networks, NULL, sizeof(ot_net) ) ) 489 if (map && set_value_for_net(net, &map->networks, NULL, sizeof(ot_net)))
490 result = 1; 490 result = 1;
491 491
492 pthread_mutex_unlock(&g_proxies_list_mutex); 492 pthread_mutex_unlock(&g_proxies_list_mutex);
493 return result; 493 return result;
494} 494}
495 495
496int proxylist_check_proxy( const ot_ip6 proxy, const ot_ip6 address ) { 496int proxylist_check_proxy(const ot_ip6 proxy, const ot_ip6 address) {
497 int result = 0; 497 int result = 0;
498 ot_proxymap *map; 498 ot_proxymap *map;
499 499
500 pthread_mutex_lock(&g_proxies_list_mutex); 500 pthread_mutex_lock(&g_proxies_list_mutex);
501 501
502 if( ( map = get_value_for_net( proxy, &g_proxies_list, sizeof(ot_proxymap) ) ) ) 502 if ((map = get_value_for_net(proxy, &g_proxies_list, sizeof(ot_proxymap))))
503 if( !address || get_value_for_net( address, &map->networks, sizeof(ot_net) ) ) 503 if (!address || get_value_for_net(address, &map->networks, sizeof(ot_net)))
504 result = 1; 504 result = 1;
505 505
506 pthread_mutex_unlock(&g_proxies_list_mutex); 506 pthread_mutex_unlock(&g_proxies_list_mutex);
@@ -509,42 +509,53 @@ int proxylist_check_proxy( const ot_ip6 proxy, const ot_ip6 address ) {
509 509
510#endif 510#endif
511 511
512static ot_ip6 g_adminip_addresses[OT_ADMINIP_MAX]; 512static ot_net g_admin_nets[OT_ADMINIP_MAX];
513static ot_permissions g_adminip_permissions[OT_ADMINIP_MAX]; 513static ot_permissions g_admin_nets_permissions[OT_ADMINIP_MAX];
514static unsigned int g_adminip_count = 0; 514static unsigned int g_admin_nets_count = 0;
515 515
516int accesslist_blessip( ot_ip6 ip, ot_permissions permissions ) { 516int accesslist_bless_net(ot_net *net, ot_permissions permissions) {
517 if( g_adminip_count >= OT_ADMINIP_MAX ) 517 if (g_admin_nets_count >= OT_ADMINIP_MAX)
518 return -1; 518 return -1;
519 519
520 memcpy(g_adminip_addresses + g_adminip_count,ip,sizeof(ot_ip6)); 520 memcpy(g_admin_nets + g_admin_nets_count, net, sizeof(ot_net));
521 g_adminip_permissions[ g_adminip_count++ ] = permissions; 521 g_admin_nets_permissions[g_admin_nets_count++] = permissions;
522 522
523#ifdef _DEBUG 523#ifdef _DEBUG
524 { 524 {
525 char _debug[512]; 525 char _debug[512];
526 int off = snprintf( _debug, sizeof(_debug), "Blessing ip address " ); 526 int off = snprintf(_debug, sizeof(_debug), "Blessing ip net ");
527 off += fmt_ip6c(_debug+off, ip ); 527 off += fmt_ip6c(_debug + off, net->address);
528 528 if (net->bits < 128) {
529 if( permissions & OT_PERMISSION_MAY_STAT ) off += snprintf( _debug+off, 512-off, " may_fetch_stats" ); 529 _debug[off++] = '/';
530 if( permissions & OT_PERMISSION_MAY_LIVESYNC ) off += snprintf( _debug+off, 512-off, " may_sync_live" ); 530 if (ip6_isv4mapped(net->address))
531 if( permissions & OT_PERMISSION_MAY_FULLSCRAPE ) off += snprintf( _debug+off, 512-off, " may_fetch_fullscrapes" ); 531 off += fmt_long(_debug + off, net->bits - 96);
532 if( permissions & OT_PERMISSION_MAY_PROXY ) off += snprintf( _debug+off, 512-off, " may_proxy" ); 532 else
533 if( !permissions ) off += snprintf( _debug+off, sizeof(_debug)-off, " nothing\n" ); 533 off += fmt_long(_debug + off, net->bits);
534 }
535
536 if (permissions & OT_PERMISSION_MAY_STAT)
537 off += snprintf(_debug + off, 512 - off, " may_fetch_stats");
538 if (permissions & OT_PERMISSION_MAY_LIVESYNC)
539 off += snprintf(_debug + off, 512 - off, " may_sync_live");
540 if (permissions & OT_PERMISSION_MAY_FULLSCRAPE)
541 off += snprintf(_debug + off, 512 - off, " may_fetch_fullscrapes");
542 if (permissions & OT_PERMISSION_MAY_PROXY)
543 off += snprintf(_debug + off, 512 - off, " may_proxy");
544 if (!permissions)
545 off += snprintf(_debug + off, sizeof(_debug) - off, " nothing");
534 _debug[off++] = '.'; 546 _debug[off++] = '.';
535 (void)write( 2, _debug, off ); 547 _debug[off++] = '\n';
548 (void)write(2, _debug, off);
536 } 549 }
537#endif 550#endif
538 551
539 return 0; 552 return 0;
540} 553}
541 554
542int accesslist_isblessed( ot_ip6 ip, ot_permissions permissions ) { 555int accesslist_is_blessed(ot_ip6 ip, ot_permissions permissions) {
543 unsigned int i; 556 unsigned int i;
544 for( i=0; i<g_adminip_count; ++i ) 557 for (i = 0; i < g_admin_nets_count; ++i)
545 if( !memcmp( g_adminip_addresses + i, ip, sizeof(ot_ip6)) && ( g_adminip_permissions[ i ] & permissions ) ) 558 if (address_in_net(ip, g_admin_nets + i) && (g_admin_nets_permissions[i] & permissions))
546 return 1; 559 return 1;
547 return 0; 560 return 0;
548} 561}
549
550const char *g_version_accesslist_c = "$Source$: $Revision$\n";