summaryrefslogtreecommitdiff
path: root/ot_accesslist.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_accesslist.c')
-rw-r--r--ot_accesslist.c144
1 files changed, 83 insertions, 61 deletions
diff --git a/ot_accesslist.c b/ot_accesslist.c
index f1bb885..a199fa4 100644
--- a/ot_accesslist.c
+++ b/ot_accesslist.c
@@ -10,21 +10,23 @@
10#include <stdlib.h> 10#include <stdlib.h>
11#include <string.h> 11#include <string.h>
12#include <unistd.h> 12#include <unistd.h>
13#ifdef WANT_DYNAMIC_ACCESSLIST 13#if defined(WANT_ACCESSLIST_BLACK) || defined(WANT_ACCESSLIST_WHITE)
14#include <errno.h> 14#include <fcntl.h>
15#include <stdint.h>
16#include <sys/mman.h>
15#include <sys/stat.h> 17#include <sys/stat.h>
16#include <sys/types.h> 18#include <sys/types.h>
17#endif 19#endif
20#ifdef WANT_DYNAMIC_ACCESSLIST
21#include <errno.h>
22#endif
18 23
19/* Libowfat */ 24/* Libowfat */
20#include "byte.h"
21#include "fmt.h"
22#include "ip6.h" 25#include "ip6.h"
23#include "mmap.h"
24#include "scan.h"
25 26
26/* Opentracker */ 27/* Opentracker */
27#include "ot_accesslist.h" 28#include "ot_accesslist.h"
29#include "ot_hex.h"
28#include "ot_vector.h" 30#include "ot_vector.h"
29#include "trackerlogic.h" 31#include "trackerlogic.h"
30 32
@@ -99,65 +101,94 @@ static void accesslist_clean(ot_accesslist *accesslist) {
99 } 101 }
100} 102}
101 103
102/* Read initial access list */ 104/* A hash needs forty bytes, and all but a final one are followed by at least
105 one separator, so n hashes need at least 41n - 1 bytes. (len + 1) / 41 is
106 therefore an exact upper bound on what a buffer of len bytes can hold. */
107size_t accesslist_parse_hashes(ot_hash *dest, size_t capacity, const char *buf, size_t len) {
108 const char *end = buf + len;
109 const char *offs = buf;
110 size_t count = 0;
111
112 while (count < capacity && end - offs >= 40) {
113 if (hex_tohash(dest[count], offs)) {
114 offs += 40;
115
116 if (offs == end || !hex_isdigit((unsigned char)*offs))
117 ++count;
118 }
119
120 /* Find start of next line */
121 while (offs < end && *(offs++) != '\n') {}
122 }
123
124 return count;
125}
126
127/* Map a file read only. Returns 0 and sets map and maplen on success, -1 if
128 the file cannot be opened or mapped. */
129static int accesslist_map(const char *filename, const char **map, size_t *maplen) {
130 struct stat st;
131 void *mapped;
132 int fd = open(filename, O_RDONLY);
133
134 if (fd < 0)
135 return -1;
136
137 if (fstat(fd, &st) < 0 || st.st_size < 0 || (uintmax_t)st.st_size > (uintmax_t)SIZE_MAX) {
138 close(fd);
139 return -1;
140 }
141
142 if (st.st_size == 0) {
143 close(fd);
144 *map = NULL;
145 *maplen = 0;
146 return 0;
147 }
148
149 mapped = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_SHARED, fd, 0);
150 close(fd);
151
152 if (mapped == MAP_FAILED)
153 return -1;
154
155 *map = mapped;
156 *maplen = (size_t)st.st_size;
157 return 0;
158}
159
103static void accesslist_readfile(void) { 160static void accesslist_readfile(void) {
104 ot_accesslist *accesslist_new; 161 ot_accesslist *accesslist_new;
105 ot_hash *info_hash; 162 const char *map;
106 const char *map, *map_end, *read_offs; 163 size_t maplen, capacity, found;
107 size_t maplen;
108 164
109 if ((map = mmap_read(g_accesslist_filename, &maplen)) == NULL) { 165 if (accesslist_map(g_accesslist_filename, &map, &maplen) < 0) {
110 char *wd = getcwd(NULL, 0); 166 char *wd = getcwd(NULL, 0);
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); 167 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);
112 free(wd); 168 free(wd);
113 return; 169 return;
114 } 170 }
115 171
116 /* You need at least 41 bytes to pass an info_hash, make enough room 172 /* Make room for the most info_hashes this file could possibly hold */
117 for the maximum amount of them */ 173 capacity = (maplen + 1) / 41;
118 accesslist_new = accesslist_make(g_accesslist, maplen / 41); 174 accesslist_new = accesslist_make(g_accesslist, capacity);
119 if (!accesslist_new) { 175 if (!accesslist_new) {
120 fprintf(stderr, "Warning: Not enough memory to allocate %zd bytes for accesslist buffer. May succeed later.\n", (maplen / 41) * 20); 176 fprintf(stderr, "Warning: Not enough memory to allocate %zd bytes for accesslist buffer. May succeed later.\n", capacity * sizeof(ot_hash));
121 mmap_unmap(map, maplen); 177 if (map)
178 munmap((void *)map, maplen);
122 return; 179 return;
123 } 180 }
124 info_hash = accesslist_new->list;
125 181
126 /* No use to scan if there's not enough room for another full info_hash */ 182 found = maplen ? accesslist_parse_hashes(accesslist_new->list, capacity, map, maplen) : 0;
127 map_end = map + maplen - 40;
128 read_offs = map;
129
130 /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" */
131 while (read_offs <= map_end) {
132 size_t i;
133 for (i = 0; i < sizeof(ot_hash); ++i) {
134 int eger1 = scan_fromhex((unsigned char)read_offs[2 * i]);
135 int eger2 = scan_fromhex((unsigned char)read_offs[1 + 2 * i]);
136 if (eger1 < 0 || eger2 < 0)
137 break;
138 (*info_hash)[i] = (uint8_t)(eger1 * 16 + eger2);
139 }
140
141 if (i == sizeof(ot_hash)) {
142 read_offs += 40;
143
144 /* Append accesslist to accesslist vector */
145 if (read_offs == map_end || scan_fromhex((unsigned char)*read_offs) < 0)
146 ++info_hash;
147 }
148
149 /* Find start of next line */
150 while (read_offs <= map_end && *(read_offs++) != '\n')
151 ;
152 }
153#ifdef _DEBUG 183#ifdef _DEBUG
154 fprintf(stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new->list)); 184 fprintf(stderr, "Added %zd info_hashes to accesslist\n", found);
155#endif 185#endif
156 186
157 mmap_unmap(map, maplen); 187 if (map)
188 munmap((void *)map, maplen);
158 189
159 qsort(accesslist_new->list, info_hash - accesslist_new->list, sizeof(*info_hash), vector_compare_hash); 190 qsort(accesslist_new->list, found, sizeof(ot_hash), vector_compare_hash);
160 accesslist_new->size = info_hash - accesslist_new->list; 191 accesslist_new->size = found;
161 192
162 /* Now exchange the accesslist vector in the least race condition prone way */ 193 /* Now exchange the accesslist vector in the least race condition prone way */
163 pthread_mutex_lock(&g_accesslist_mutex); 194 pthread_mutex_lock(&g_accesslist_mutex);
@@ -197,7 +228,7 @@ int accesslist_hashisvalid(ot_hash hash) {
197 228
198 /* If we found a matching hash on the main list, scan the list of dynamically deleted hashes */ 229 /* If we found a matching hash on the main list, scan the list of dynamically deleted hashes */
199 accesslist_delete = g_accesslist_delete; 230 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)) 231 if ((exactmatch != NULL) && accesslist_delete && bsearch(hash, accesslist_delete->list, accesslist_delete->size, OT_HASH_COMPARE_SIZE, vector_compare_hash))
201 exactmatch = NULL; 232 exactmatch = NULL;
202#endif 233#endif
203 234
@@ -262,7 +293,6 @@ static void *accesslist_adddel_worker(char *fifoname, ot_accesslist *_Atomic
262 293
263 while ((linelen = getline(&line, &linecap, fifo)) > 0) { 294 while ((linelen = getline(&line, &linecap, fifo)) > 0) {
264 ot_hash info_hash; 295 ot_hash info_hash;
265 size_t i;
266 296
267 printf("Got line %*s", (int)linelen, line); 297 printf("Got line %*s", (int)linelen, line);
268 /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" 298 /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*"
@@ -270,15 +300,7 @@ static void *accesslist_adddel_worker(char *fifoname, ot_accesslist *_Atomic
270 if (linelen < 41) 300 if (linelen < 41)
271 continue; 301 continue;
272 302
273 for (i = 0; i < sizeof(ot_hash); ++i) { 303 if (!hex_tohash(info_hash, line))
274 int eger1 = scan_fromhex((unsigned char)line[2 * i]);
275 int eger2 = scan_fromhex((unsigned char)line[1 + 2 * i]);
276 if (eger1 < 0 || eger2 < 0)
277 break;
278 ((uint8_t *)info_hash)[i] = (uint8_t)(eger1 * 16 + eger2);
279 }
280 printf("parsed info_hash %20s\n", info_hash);
281 if (i != sizeof(ot_hash))
282 continue; 304 continue;
283 305
284 /* From now on we modify g_accesslist_add and g_accesslist_delete, so prevent the 306 /* From now on we modify g_accesslist_add and g_accesslist_delete, so prevent the
@@ -528,9 +550,9 @@ int accesslist_bless_net(ot_net *net, ot_permissions permissions) {
528 if (net->bits < 128) { 550 if (net->bits < 128) {
529 _debug[off++] = '/'; 551 _debug[off++] = '/';
530 if (ip6_isv4mapped(net->address)) 552 if (ip6_isv4mapped(net->address))
531 off += fmt_long(_debug + off, net->bits - 96); 553 off += snprintf(_debug + off, sizeof(_debug) - off, "%d", net->bits - 96);
532 else 554 else
533 off += fmt_long(_debug + off, net->bits); 555 off += snprintf(_debug + off, sizeof(_debug) - off, "%d", net->bits);
534 } 556 }
535 557
536 if (permissions & OT_PERMISSION_MAY_STAT) 558 if (permissions & OT_PERMISSION_MAY_STAT)