summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau2021-11-03 11:27:11 +0000
committerFelix Fietkau2021-11-03 11:27:30 +0000
commit411432ec853b3a7d4efee04ce6ba2f6c067a67a6 (patch)
tree9588232b9b38f189013a05395aa8ba70d792edf2
parent2ca7352543da24cf8cc5c7c1ea20f8c2e75ca8b9 (diff)
downloadqosify-411432ec853b3a7d4efee04ce6ba2f6c067a67a6.tar.gz
map: add support for adding dns regex patterns
This will be used for hostname based dscp mark rules Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--map.c56
-rw-r--r--qosify.h6
2 files changed, 54 insertions, 8 deletions
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 <stdbool.h>
+#include <regex.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
@@ -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;
};