diff options
Diffstat (limited to 'ot_accesslist.c')
| -rw-r--r-- | ot_accesslist.c | 144 |
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. */ | ||
| 107 | size_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. */ | ||
| 129 | static 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 | |||
| 103 | static void accesslist_readfile(void) { | 160 | static 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) |
