From: Felix Fietkau Date: Wed, 3 Nov 2021 11:27:11 +0000 (+0100) Subject: map: add support for adding dns regex patterns X-Git-Url: http://git.openwrt.org/project/luci.git;master?a=commitdiff_plain;h=411432ec853b3a7d4efee04ce6ba2f6c067a67a6;p=project%2Fqosify.git map: add support for adding dns regex patterns This will be used for hostname based dscp mark rules Signed-off-by: Felix Fietkau --- diff --git a/map.c b/map.c index 2eacfcd..7f8c20d 100644 --- a/map.c +++ b/map.c @@ -38,6 +38,7 @@ static const struct { [CL_MAP_IPV4_ADDR] = { "ipv4_map", "ipv4_addr" }, [CL_MAP_IPV6_ADDR] = { "ipv6_map", "ipv6_addr" }, [CL_MAP_CONFIG] = { "config", "config" }, + [CL_MAP_DNS] = { "dns", "dns" }, }; static const struct { @@ -169,7 +170,7 @@ int qosify_map_init(void) { int i; - for (i = 0; i < ARRAY_SIZE(qosify_map_fds); i++) { + for (i = 0; i < CL_MAP_DNS; i++) { qosify_map_fds[i] = qosify_map_get_fd(i); if (qosify_map_fds[i] < 0) return -1; @@ -210,9 +211,37 @@ static int qosify_map_entry_cmp(const void *k1, const void *k2, void *ptr) if (d1->id != d2->id) return d2->id - d1->id; + if (d1->id == CL_MAP_DNS) + return strcmp(d1->addr.dns.pattern, d2->addr.dns.pattern); + return memcmp(&d1->addr, &d2->addr, sizeof(d1->addr)); } +static struct qosify_map_entry * +__qosify_map_alloc_entry(struct qosify_map_data *data) +{ + struct qosify_map_entry *e; + char *pattern; + + if (data->id < CL_MAP_DNS) { + e = calloc(1, sizeof(*e)); + memcpy(&e->data.addr, &data->addr, sizeof(e->data.addr)); + + return e; + } + + 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)) { + free(e); + return NULL; + } + + return e; +} + static void __qosify_map_set_entry(struct qosify_map_data *data) { int fd = qosify_map_fds[data->id]; @@ -227,10 +256,12 @@ static void __qosify_map_set_entry(struct qosify_map_data *data) if (!add) return; - e = calloc(1, sizeof(*e)); + e = __qosify_map_alloc_entry(data); + if (!e) + return; + e->avl.key = &e->data; e->data.id = data->id; - memcpy(&e->data.addr, &data->addr, sizeof(e->data.addr)); avl_insert(&map_data, &e->avl); } else { prev_dscp = e->data.dscp; @@ -250,7 +281,7 @@ static void __qosify_map_set_entry(struct qosify_map_data *data) e->data.dscp = e->data.file_dscp; } - if (e->data.dscp != prev_dscp) + if (e->data.dscp != prev_dscp && data->id < CL_MAP_DNS) bpf_map_update_elem(fd, &data->addr, &e->data.dscp, BPF_ANY); if (add) { @@ -320,6 +351,9 @@ int qosify_map_set_entry(enum qosify_map_id id, bool file, const char *str, uint }; switch (id) { + case CL_MAP_DNS: + data.addr.dns.pattern = str; + break; case CL_MAP_TCP_PORTS: case CL_MAP_UDP_PORTS: return qosify_map_set_port(&data, str); @@ -401,6 +435,8 @@ qosify_map_parse_line(char *str) if (dscp < 0) return; + if (!strncmp(key, "dns:", 4)) + qosify_map_set_entry(CL_MAP_DNS, true, key + 4, dscp); if (!strncmp(key, "tcp:", 4)) qosify_map_set_entry(CL_MAP_TCP_PORTS, true, key + 4, dscp); else if (!strncmp(key, "udp:", 4)) @@ -511,7 +547,8 @@ static void qosify_map_free_entry(struct qosify_map_entry *e) int fd = qosify_map_fds[e->data.id]; avl_delete(&map_data, &e->avl); - bpf_map_delete_elem(fd, &e->data.addr); + if (e->data.id < CL_MAP_DNS) + bpf_map_delete_elem(fd, &e->data.addr); free(e); } @@ -583,22 +620,25 @@ void qosify_map_dump(struct blob_buf *b) blobmsg_add_string(b, "type", qosify_map_info[e->data.id].type_name); - buf = blobmsg_alloc_string_buffer(b, "value", buf_len); switch (e->data.id) { case CL_MAP_TCP_PORTS: case CL_MAP_UDP_PORTS: - snprintf(buf, buf_len, "%d", ntohs(e->data.addr.port)); + blobmsg_printf(b, "addr", "%d", ntohs(e->data.addr.port)); break; case CL_MAP_IPV4_ADDR: case CL_MAP_IPV6_ADDR: + buf = blobmsg_alloc_string_buffer(b, "addr", buf_len); af = e->data.id == CL_MAP_IPV6_ADDR ? AF_INET6 : AF_INET; inet_ntop(af, &e->data.addr, buf, buf_len); + blobmsg_add_string_buffer(b); + break; + case CL_MAP_DNS: + blobmsg_add_string(b, "addr", e->data.addr.dns.pattern); break; default: *buf = 0; break; } - blobmsg_add_string_buffer(b); blobmsg_close_table(b, c); } blobmsg_close_array(b, a); diff --git a/qosify.h b/qosify.h index e6934ad..285543a 100644 --- a/qosify.h +++ b/qosify.h @@ -6,6 +6,7 @@ #define __QOS_CLASSIFY_H #include +#include #include #include @@ -29,6 +30,7 @@ enum qosify_map_id { CL_MAP_IPV4_ADDR, CL_MAP_IPV6_ADDR, CL_MAP_CONFIG, + CL_MAP_DNS, __CL_MAP_MAX, }; @@ -45,6 +47,10 @@ struct qosify_map_data { uint32_t port; struct in_addr ip; struct in6_addr ip6; + struct { + const char *pattern; + regex_t regex; + } dns; } addr; };