summaryrefslogtreecommitdiff
path: root/src/caches/shibari_whitelist_read.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/caches/shibari_whitelist_read.c')
-rw-r--r--src/caches/shibari_whitelist_read.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/caches/shibari_whitelist_read.c b/src/caches/shibari_whitelist_read.c
new file mode 100644
index 0000000..58dd2a0
--- /dev/null
+++ b/src/caches/shibari_whitelist_read.c
@@ -0,0 +1,58 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include <skalibs/uint16.h>
+#include <skalibs/uint32.h>
+#include <skalibs/diuint32.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/direntry.h>
+#include <skalibs/ip46.h>
+
+#include "shibari-internal.h"
+
+static int shibari_whitelist_add4 (genalloc *g, char const *ip4, uint16_t mask)
+{
+ diuint32 d = { .right = ((uint32_t)1 << mask) - 1 } ;
+ uint32_unpack_big(ip4, &d.left) ;
+ d.left &= d.right ;
+ return genalloc_append(diuint32, g, &d) ;
+}
+
+int shibari_whitelist_read (char const *path, genalloc *ip4, genalloc *ip6)
+{
+ DIR *dir = opendir(path) ;
+ if (!dir) return 0 ;
+ genalloc_setlen(diuint32, ip4, 0) ;
+ genalloc_setlen(shibari_ip6_t, ip6, 0) ;
+ for (;;)
+ {
+ direntry *d ;
+ size_t pos ;
+ ip46_t ip ;
+ uint16_t mask ;
+ errno = 0 ;
+ d = readdir(dir) ;
+ if (!d) break ;
+ if (d->d_name[0] == '.' && (!d->d_name[1] || (d->d_name[1] == '.' && !d->d_name[2]))) continue ;
+ pos = ip46_scan(d->d_name, &ip) ;
+ if (!pos) continue ;
+ if (d->d_name[pos] && d->d_name[pos] != '_') continue ;
+ if (!d->d_name[pos]) mask = ip46_is6(&ip) ? 128 : 32 ;
+ else
+ {
+ if (!uint160_scan(d->d_name + pos + 1, &mask)) continue ;
+ if (mask > (ip46_is6(&ip) ? 128 : 32)) continue ;
+ }
+ if (!(ip46_is6(&ip) ? shibari_whitelist_add6(ip6, ip.ip, mask) : shibari_whitelist_add4(ip4, ip.ip, mask))) goto err ;
+ }
+ if (errno) goto err ;
+ dir_close(dir) ;
+ return 1 ;
+
+ err:
+ dir_close(dir) ;
+ return 0 ;
+}