From 9773ffa70f1fb9c24eea9508e600cffd5abdadbc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 6 Mar 2022 22:32:59 +0100 Subject: [PATCH] map: process dns patterns in the order in which they were defined Signed-off-by: Felix Fietkau --- dns.c | 29 ++++++++++++++++++----------- map.c | 15 ++++++++++++--- qosify.h | 3 ++- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/dns.c b/dns.c index 1706238..5d10c6d 100644 --- a/dns.c +++ b/dns.c @@ -74,6 +74,7 @@ struct dns_answer { struct cname_entry { struct avl_node node; + uint32_t seq; uint8_t dscp; uint8_t age; }; @@ -123,7 +124,7 @@ proto_is_vlan(uint16_t proto) } static void -cname_cache_set(const char *name, uint8_t dscp) +cname_cache_set(const char *name, uint8_t dscp, uint32_t seq) { struct cname_entry *e; @@ -138,10 +139,11 @@ cname_cache_set(const char *name, uint8_t dscp) e->age = 0; e->dscp = dscp; + e->seq = seq; } static int -cname_cache_get(const char *name, uint8_t *dscp) +cname_cache_get(const char *name, uint8_t *dscp, uint32_t *seq) { struct cname_entry *e; @@ -149,12 +151,16 @@ cname_cache_get(const char *name, uint8_t *dscp) if (!e) return -1; - *dscp = e->dscp; + if (*dscp == 0xff || e->seq < *seq) { + *dscp = e->dscp; + *seq = e->seq; + } + return 0; } static int -dns_parse_question(struct packet *pkt, const void *hdr, uint8_t *dscp) +dns_parse_question(struct packet *pkt, const void *hdr, uint8_t *dscp, uint32_t *seq) { char qname[MAX_NAME_LEN]; @@ -162,14 +168,14 @@ dns_parse_question(struct packet *pkt, const void *hdr, uint8_t *dscp) !pkt_pull(pkt, sizeof(struct dns_question))) return -1; - cname_cache_get(qname, dscp); - qosify_map_lookup_dns_entry(qname, dscp); + cname_cache_get(qname, dscp, seq); + qosify_map_lookup_dns_entry(qname, dscp, seq); return 0; } static int -dns_parse_answer(struct packet *pkt, void *hdr, uint8_t *dscp) +dns_parse_answer(struct packet *pkt, void *hdr, uint8_t *dscp, uint32_t *seq) { struct qosify_map_data data = {}; char cname[MAX_NAME_LEN]; @@ -196,8 +202,8 @@ dns_parse_answer(struct packet *pkt, void *hdr, uint8_t *dscp) cname, sizeof(cname)) < 0) return -1; - qosify_map_lookup_dns_entry(cname, dscp); - cname_cache_set(cname, *dscp); + qosify_map_lookup_dns_entry(cname, dscp, seq); + cname_cache_set(cname, *dscp, *seq); return 0; case TYPE_A: @@ -227,6 +233,7 @@ static void qosify_dns_data_cb(struct packet *pkt) { struct dns_header *h; + uint32_t lookup_seq = 0; uint8_t dscp = 0xff; int i; @@ -241,11 +248,11 @@ qosify_dns_data_cb(struct packet *pkt) if (h->questions != cpu_to_be16(1)) return; - if (dns_parse_question(pkt, h, &dscp)) + if (dns_parse_question(pkt, h, &dscp, &lookup_seq)) return; for (i = 0; i < be16_to_cpu(h->answers); i++) - if (dns_parse_answer(pkt, h, &dscp)) + if (dns_parse_answer(pkt, h, &dscp, &lookup_seq)) return; } diff --git a/map.c b/map.c index 436de60..e413020 100644 --- a/map.c +++ b/map.c @@ -31,6 +31,7 @@ int qosify_map_timeout; int qosify_active_timeout; struct qosify_config config; struct qosify_flow_config flow_config; +static uint32_t map_dns_seq; struct qosify_map_file { struct list_head list; @@ -332,6 +333,9 @@ void __qosify_map_set_entry(struct qosify_map_data *data) bpf_map_update_elem(fd, &data->addr, &val, BPF_ANY); } + if (data->id == CL_MAP_DNS) + e->data.addr.dns.seq = ++map_dns_seq; + if (add) { if (qosify_map_timeout == ~0 || file) { e->timeout = ~0; @@ -599,6 +603,7 @@ static void qosify_map_reset_file_entries(void) { struct qosify_map_entry *e; + map_dns_seq = 0; avl_for_each_element(&map_data, e, avl) e->data.file = false; } @@ -710,7 +715,7 @@ void qosify_map_gc(void) uloop_timeout_set(&qosify_map_timer, timeout * 1000); } -int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp) +int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp, uint32_t *seq) { struct qosify_map_data data = { .id = CL_MAP_DNS, @@ -741,7 +746,10 @@ int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp) continue; } - *dscp = e->data.dscp; + if (*dscp == 0xff || e->data.addr.dns.seq < *seq) { + *dscp = e->data.dscp; + *seq = e->data.addr.dns.seq; + } ret = 0; } @@ -753,8 +761,9 @@ int qosify_map_add_dns_host(char *host, const char *addr, const char *type, int { struct qosify_map_data data = {}; int prev_timeout = qosify_map_timeout; + uint32_t lookup_seq = 0; - if (qosify_map_lookup_dns_entry(host, &data.dscp)) + if (qosify_map_lookup_dns_entry(host, &data.dscp, &lookup_seq)) return 0; data.user = true; diff --git a/qosify.h b/qosify.h index 4654385..7a598e3 100644 --- a/qosify.h +++ b/qosify.h @@ -51,6 +51,7 @@ struct qosify_map_data { struct in_addr ip; struct in6_addr ip6; struct { + uint32_t seq; const char *pattern; regex_t regex; } dns; @@ -89,7 +90,7 @@ 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); void qosify_map_set_classes(struct blob_attr *val); -int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp); +int qosify_map_lookup_dns_entry(char *host, uint8_t *dscp, uint32_t *seq); int qosify_map_add_dns_host(char *host, const char *addr, const char *type, int ttl); int map_parse_flow_config(struct qosify_flow_config *cfg, struct blob_attr *attr, bool reset); -- 2.30.2