map: default to fnmatch matching for dns patterns. support regex via leading /
authorFelix Fietkau <nbd@nbd.name>
Mon, 8 Nov 2021 20:59:22 +0000 (21:59 +0100)
committerFelix Fietkau <nbd@nbd.name>
Mon, 8 Nov 2021 21:01:20 +0000 (22:01 +0100)
Simplifies writing DNS matching rules

Signed-off-by: Felix Fietkau <nbd@nbd.name>
README
map.c
qosify.h

diff --git a/README b/README
index 98b407f8975c7ae94993f791b0a8c2d1cfca30c6..6a8034fb9fbb829ca30dac2f13162201e8e3efc2 100644 (file)
--- a/README
+++ b/README
@@ -99,7 +99,9 @@ match is one of:
        IPv4 address, e.g. 1.1.1.1
 - <ipv6addr>
        IPv6 address, e.g. ff01::1
-- dns:<regex>
+- dns:<pattern>
+       fnmatch() pattern supporting * and ? as wildcard characters
+- dns:/<regex>
        POSIX.2 extended regular expression for matching hostnames
        Only works, if dns lookups are passed to qosify via the add_dns_host ubus call.
 
diff --git a/map.c b/map.c
index afca0f5234d47a24b8bc6ef1741aaffe393af605..52f4337a3142aa158d25c7542e0f4d9f35a2073a 100644 (file)
--- a/map.c
+++ b/map.c
@@ -9,6 +9,7 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <time.h>
+#include <fnmatch.h>
 
 #include <libubox/uloop.h>
 
@@ -225,6 +226,7 @@ __qosify_map_alloc_entry(struct qosify_map_data *data)
 {
        struct qosify_map_entry *e;
        char *pattern;
+       char *c;
 
        if (data->id < CL_MAP_DNS) {
                e = calloc(1, sizeof(*e));
@@ -236,8 +238,13 @@ __qosify_map_alloc_entry(struct qosify_map_data *data)
        e = calloc_a(sizeof(*e), &pattern, strlen(data->addr.dns.pattern) + 1);
        strcpy(pattern, data->addr.dns.pattern);
        e->data.addr.dns.pattern = pattern;
-       if (regcomp(&e->data.addr.dns.regex, pattern,
-                   REG_EXTENDED | REG_ICASE | REG_NOSUB)) {
+
+       for (c = pattern; *c; c++)
+               *c = tolower(*c);
+
+       if (pattern[0] == '/' &&
+           regcomp(&e->data.addr.dns.regex, pattern + 1,
+                   REG_EXTENDED | REG_NOSUB)) {
                free(e);
                return NULL;
        }
@@ -622,7 +629,7 @@ void qosify_map_gc(void)
 }
 
 
-int qosify_map_add_dns_host(const char *host, const char *addr, const char *type, int ttl)
+int qosify_map_add_dns_host(char *host, const char *addr, const char *type, int ttl)
 {
        struct qosify_map_data data = {
                .id = CL_MAP_DNS,
@@ -630,6 +637,7 @@ int qosify_map_add_dns_host(const char *host, const char *addr, const char *type
        };
        struct qosify_map_entry *e;
        int prev_timeout = qosify_map_timeout;
+       char *c;
 
        e = avl_find_ge_element(&map_data, &data, e, avl);
        if (!e)
@@ -647,14 +655,22 @@ int qosify_map_add_dns_host(const char *host, const char *addr, const char *type
        if (qosify_map_fill_ip(&data, addr))
                return -1;
 
+       for (c = host; *c; c++)
+               *c = tolower(*c);
+
        avl_for_element_to_last(&map_data, e, e, avl) {
                regex_t *regex = &e->data.addr.dns.regex;
 
                if (e->data.id != CL_MAP_DNS)
                        return 0;
 
-               if (regexec(regex, host, 0, NULL, 0) != 0)
-                       continue;
+               if (e->data.addr.dns.pattern[0] == '/') {
+                       if (regexec(regex, host, 0, NULL, 0) != 0)
+                               continue;
+               } else {
+                       if (fnmatch(e->data.addr.dns.pattern, host, 0))
+                               continue;
+               }
 
                if (ttl)
                        qosify_map_timeout = ttl;
index 16d481324904c4898cee87d9f5cf307da2377260..76cf87c7962806a226d751b7e8b8c1da42e8e543 100644 (file)
--- a/qosify.h
+++ b/qosify.h
@@ -80,7 +80,7 @@ void qosify_map_dump(struct blob_buf *b);
 void qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val);
 void qosify_map_reset_config(void);
 void qosify_map_update_config(void);
-int qosify_map_add_dns_host(const char *host, const char *addr, const char *type, int ttl);
+int qosify_map_add_dns_host(char *host, const char *addr, const char *type, int ttl);
 
 int qosify_iface_init(void);
 void qosify_iface_config_update(struct blob_attr *ifaces, struct blob_attr *devs);