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;
return e;
}
-static void __qosify_map_set_entry(struct qosify_map_data *data)
+void __qosify_map_set_entry(struct qosify_map_data *data)
{
int fd = qosify_map_fds[data->id];
struct qosify_map_entry *e;
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;
switch (id) {
case CL_MAP_DNS:
data.addr.dns.pattern = str;
+ if (str[-2] == 'c')
+ data.addr.dns.only_cname = 1;
break;
case CL_MAP_TCP_PORTS:
case CL_MAP_UDP_PORTS:
if (!strncmp(key, "dns:", 4))
qosify_map_set_entry(CL_MAP_DNS, true, key + 4, dscp);
+ if (!strncmp(key, "dns_q:", 6) || !strncmp(key, "dns_c:", 6))
+ qosify_map_set_entry(CL_MAP_DNS, true, key + 6, dscp);
if (!strncmp(key, "tcp:", 4))
qosify_map_set_entry(CL_MAP_TCP_PORTS, true, key + 4, dscp);
else if (!strncmp(key, "udp:", 4))
{
struct qosify_map_entry *e;
+ map_dns_seq = 0;
avl_for_each_element(&map_data, e, avl)
e->data.file = false;
}
uloop_timeout_set(&qosify_map_timer, timeout * 1000);
}
-
-int qosify_map_add_dns_host(char *host, const char *addr, const char *type, int ttl)
+int qosify_map_lookup_dns_entry(char *host, bool cname, uint8_t *dscp, uint32_t *seq)
{
struct qosify_map_data data = {
.id = CL_MAP_DNS,
.addr.dns.pattern = "",
};
struct qosify_map_entry *e;
- int prev_timeout = qosify_map_timeout;
+ bool ret = -1;
char *c;
e = avl_find_ge_element(&map_data, &data, e, avl);
if (!e)
- return 0;
-
- memset(&data, 0, sizeof(data));
- data.user = true;
- if (!strcmp(type, "A"))
- data.id = CL_MAP_IPV4_ADDR;
- else if (!strcmp(type, "AAAA"))
- data.id = CL_MAP_IPV6_ADDR;
- else
- return 0;
-
- if (qosify_map_fill_ip(&data, addr))
return -1;
for (c = host; *c; c++)
regex_t *regex = &e->data.addr.dns.regex;
if (e->data.id != CL_MAP_DNS)
- return 0;
+ break;
+
+ if (!cname && e->data.addr.dns.only_cname)
+ continue;
if (e->data.addr.dns.pattern[0] == '/') {
if (regexec(regex, host, 0, NULL, 0) != 0)
continue;
}
- if (ttl)
- qosify_map_timeout = ttl;
- data.dscp = e->data.dscp;
- __qosify_map_set_entry(&data);
- qosify_map_timeout = prev_timeout;
+ if (*dscp == 0xff || e->data.addr.dns.seq < *seq) {
+ *dscp = e->data.dscp;
+ *seq = e->data.addr.dns.seq;
+ }
+ ret = 0;
}
+ return ret;
+}
+
+
+int qosify_map_add_dns_host(char *host, const char *addr, const char *type, int ttl)
+{
+ struct qosify_map_data data = {
+ .dscp = 0xff
+ };
+ int prev_timeout = qosify_map_timeout;
+ uint32_t lookup_seq = 0;
+
+ if (qosify_map_lookup_dns_entry(host, false, &data.dscp, &lookup_seq))
+ return 0;
+
+ data.user = true;
+ if (!strcmp(type, "A"))
+ data.id = CL_MAP_IPV4_ADDR;
+ else if (!strcmp(type, "AAAA"))
+ data.id = CL_MAP_IPV6_ADDR;
+ else
+ return 0;
+
+ if (qosify_map_fill_ip(&data, addr))
+ return -1;
+
+ if (ttl)
+ qosify_map_timeout = ttl;
+ __qosify_map_set_entry(&data);
+ qosify_map_timeout = prev_timeout;
+
return 0;
}