patch from richard
sort multiple DNS records using a key
This commit is contained in:
parent
64d5123da7
commit
107323352d
4 changed files with 79 additions and 22 deletions
|
@ -172,7 +172,8 @@ int dns_dname_encode(struct mbuf *mb, const char *name,
|
||||||
int dns_dname_decode(struct mbuf *mb, char **name, size_t start);
|
int dns_dname_decode(struct mbuf *mb, char **name, size_t start);
|
||||||
int dns_cstr_encode(struct mbuf *mb, const char *str);
|
int dns_cstr_encode(struct mbuf *mb, const char *str);
|
||||||
int dns_cstr_decode(struct mbuf *mb, char **str);
|
int dns_cstr_decode(struct mbuf *mb, char **str);
|
||||||
void dns_rrlist_sort(struct list *rrl, uint16_t type);
|
void dns_rrlist_sort(struct list *rrl, uint16_t type, size_t key);
|
||||||
|
void dns_rrlist_sort_addr(struct list *rrl, size_t key);
|
||||||
struct dnsrr *dns_rrlist_apply(struct list *rrl, const char *name,
|
struct dnsrr *dns_rrlist_apply(struct list *rrl, const char *name,
|
||||||
uint16_t type, uint16_t dnsclass,
|
uint16_t type, uint16_t dnsclass,
|
||||||
bool recurse, dns_rrlist_h *rrlh, void *arg);
|
bool recurse, dns_rrlist_h *rrlh, void *arg);
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Creytiv.com
|
* Copyright (C) 2010 Creytiv.com
|
||||||
*/
|
*/
|
||||||
|
#include <string.h>
|
||||||
#include <re_types.h>
|
#include <re_types.h>
|
||||||
#include <re_list.h>
|
#include <re_list.h>
|
||||||
|
#include <re_hash.h>
|
||||||
#include <re_mbuf.h>
|
#include <re_mbuf.h>
|
||||||
#include <re_fmt.h>
|
#include <re_fmt.h>
|
||||||
#include <re_dns.h>
|
#include <re_dns.h>
|
||||||
|
@ -15,31 +17,56 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct sort {
|
||||||
|
uint16_t type;
|
||||||
|
uint32_t key;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t sidx(const struct dnsrr *rr, uint32_t key)
|
||||||
|
{
|
||||||
|
uint32_t addr[4];
|
||||||
|
|
||||||
|
switch (rr->type) {
|
||||||
|
|
||||||
|
case DNS_TYPE_A:
|
||||||
|
return rr->rdata.a.addr ^ key;
|
||||||
|
|
||||||
|
case DNS_TYPE_AAAA:
|
||||||
|
memcpy(addr, rr->rdata.aaaa.addr, 16);
|
||||||
|
|
||||||
|
return addr[0] ^ addr[1] ^ addr[2] ^ addr[3] ^ key;
|
||||||
|
|
||||||
|
case DNS_TYPE_SRV:
|
||||||
|
return ((hash_fast_str(rr->rdata.srv.target) & 0xfff) ^ key) +
|
||||||
|
rr->rdata.srv.weight;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool std_sort_handler(struct le *le1, struct le *le2, void *arg)
|
static bool std_sort_handler(struct le *le1, struct le *le2, void *arg)
|
||||||
{
|
{
|
||||||
struct dnsrr *rr1 = le1->data;
|
struct dnsrr *rr1 = le1->data;
|
||||||
struct dnsrr *rr2 = le2->data;
|
struct dnsrr *rr2 = le2->data;
|
||||||
const uint16_t type = *(uint16_t *)arg;
|
struct sort *sort = arg;
|
||||||
|
|
||||||
if (type != rr1->type)
|
if (sort->type != rr1->type)
|
||||||
return type != rr2->type;
|
return sort->type != rr2->type;
|
||||||
|
|
||||||
if (type != rr2->type)
|
if (sort->type != rr2->type)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
switch (type) {
|
switch (sort->type) {
|
||||||
|
|
||||||
case DNS_TYPE_MX:
|
case DNS_TYPE_MX:
|
||||||
return rr1->rdata.mx.pref <= rr2->rdata.mx.pref;
|
return rr1->rdata.mx.pref <= rr2->rdata.mx.pref;
|
||||||
|
|
||||||
case DNS_TYPE_SRV:
|
case DNS_TYPE_SRV:
|
||||||
if (rr1->rdata.srv.pri == rr2->rdata.srv.pri) {
|
if (rr1->rdata.srv.pri == rr2->rdata.srv.pri)
|
||||||
|
return sidx(rr1, sort->key) >= sidx(rr2, sort->key);
|
||||||
if (rr1->rdata.srv.weight)
|
|
||||||
return 0 != rr2->rdata.srv.weight;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rr1->rdata.srv.pri < rr2->rdata.srv.pri;
|
return rr1->rdata.srv.pri < rr2->rdata.srv.pri;
|
||||||
|
|
||||||
|
@ -57,16 +84,42 @@ static bool std_sort_handler(struct le *le1, struct le *le2, void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool addr_sort_handler(struct le *le1, struct le *le2, void *arg)
|
||||||
|
{
|
||||||
|
struct dnsrr *rr1 = le1->data;
|
||||||
|
struct dnsrr *rr2 = le2->data;
|
||||||
|
struct sort *sort = arg;
|
||||||
|
|
||||||
|
return sidx(rr1, sort->key) >= sidx(rr2, sort->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort a list of DNS Resource Records
|
* Sort a list of DNS Resource Records
|
||||||
*
|
*
|
||||||
* @param rrl DNS Resource Record list
|
* @param rrl DNS Resource Record list
|
||||||
* @param type DNS Record type
|
* @param type DNS Record type
|
||||||
|
* @param key Sort key
|
||||||
*/
|
*/
|
||||||
void dns_rrlist_sort(struct list *rrl, uint16_t type)
|
void dns_rrlist_sort(struct list *rrl, uint16_t type, size_t key)
|
||||||
{
|
{
|
||||||
list_sort(rrl, std_sort_handler, &type);
|
struct sort sort = {type, (uint32_t)key>>5};
|
||||||
/* todo add SRV postprocessing for weighted load balancing. */
|
|
||||||
|
list_sort(rrl, std_sort_handler, &sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort a list of A/AAAA DNS Resource Records
|
||||||
|
*
|
||||||
|
* @param rrl DNS Resource Record list
|
||||||
|
* @param key Sort key
|
||||||
|
*/
|
||||||
|
void dns_rrlist_sort_addr(struct list *rrl, size_t key)
|
||||||
|
{
|
||||||
|
struct sort sort = {0, (uint32_t)key>>5};
|
||||||
|
|
||||||
|
list_sort(rrl, addr_sort_handler, &sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -227,6 +227,7 @@ static int request_next(struct sip_request *req)
|
||||||
list_unlink(&rr->le);
|
list_unlink(&rr->le);
|
||||||
|
|
||||||
if (req->addrl.head) {
|
if (req->addrl.head) {
|
||||||
|
dns_rrlist_sort_addr(&req->addrl, (size_t)req->arg);
|
||||||
mem_deref(rr);
|
mem_deref(rr);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
@ -392,7 +393,7 @@ static void naptr_handler(int err, const struct dnshdr *hdr, struct list *ansl,
|
||||||
(void)hdr;
|
(void)hdr;
|
||||||
(void)authl;
|
(void)authl;
|
||||||
|
|
||||||
dns_rrlist_sort(ansl, DNS_TYPE_NAPTR);
|
dns_rrlist_sort(ansl, DNS_TYPE_NAPTR, (size_t)req->arg);
|
||||||
|
|
||||||
rr = dns_rrlist_apply(ansl, NULL, DNS_TYPE_NAPTR, DNS_CLASS_IN, false,
|
rr = dns_rrlist_apply(ansl, NULL, DNS_TYPE_NAPTR, DNS_CLASS_IN, false,
|
||||||
rr_naptr_handler, req);
|
rr_naptr_handler, req);
|
||||||
|
@ -410,8 +411,6 @@ static void naptr_handler(int err, const struct dnshdr *hdr, struct list *ansl,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dns_rrlist_sort(addl, DNS_TYPE_SRV);
|
|
||||||
|
|
||||||
dns_rrlist_apply(addl, rr->rdata.naptr.replace, DNS_TYPE_SRV,
|
dns_rrlist_apply(addl, rr->rdata.naptr.replace, DNS_TYPE_SRV,
|
||||||
DNS_CLASS_IN, true, rr_append_handler, &req->srvl);
|
DNS_CLASS_IN, true, rr_append_handler, &req->srvl);
|
||||||
|
|
||||||
|
@ -425,6 +424,8 @@ static void naptr_handler(int err, const struct dnshdr *hdr, struct list *ansl,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dns_rrlist_sort(&req->srvl, DNS_TYPE_SRV, (size_t)req->arg);
|
||||||
|
|
||||||
dns_rrlist_apply(addl, NULL, DNS_QTYPE_ANY, DNS_CLASS_IN, false,
|
dns_rrlist_apply(addl, NULL, DNS_QTYPE_ANY, DNS_CLASS_IN, false,
|
||||||
rr_cache_handler, req);
|
rr_cache_handler, req);
|
||||||
|
|
||||||
|
@ -447,8 +448,6 @@ static void srv_handler(int err, const struct dnshdr *hdr, struct list *ansl,
|
||||||
(void)hdr;
|
(void)hdr;
|
||||||
(void)authl;
|
(void)authl;
|
||||||
|
|
||||||
dns_rrlist_sort(ansl, DNS_TYPE_SRV);
|
|
||||||
|
|
||||||
dns_rrlist_apply(ansl, NULL, DNS_TYPE_SRV, DNS_CLASS_IN, false,
|
dns_rrlist_apply(ansl, NULL, DNS_TYPE_SRV, DNS_CLASS_IN, false,
|
||||||
rr_append_handler, &req->srvl);
|
rr_append_handler, &req->srvl);
|
||||||
|
|
||||||
|
@ -479,6 +478,8 @@ static void srv_handler(int err, const struct dnshdr *hdr, struct list *ansl,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dns_rrlist_sort(&req->srvl, DNS_TYPE_SRV, (size_t)req->arg);
|
||||||
|
|
||||||
dns_rrlist_apply(addl, NULL, DNS_QTYPE_ANY, DNS_CLASS_IN, false,
|
dns_rrlist_apply(addl, NULL, DNS_QTYPE_ANY, DNS_CLASS_IN, false,
|
||||||
rr_cache_handler, req);
|
rr_cache_handler, req);
|
||||||
|
|
||||||
|
@ -514,6 +515,8 @@ static void addr_handler(int err, const struct dnshdr *hdr, struct list *ansl,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dns_rrlist_sort_addr(&req->addrl, (size_t)req->arg);
|
||||||
|
|
||||||
err = request_next(req);
|
err = request_next(req);
|
||||||
if (err)
|
if (err)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -138,7 +138,7 @@ static void srv_handler(int err, const struct dnshdr *hdr, struct list *ansl,
|
||||||
(void)hdr;
|
(void)hdr;
|
||||||
(void)authl;
|
(void)authl;
|
||||||
|
|
||||||
dns_rrlist_sort(ansl, DNS_TYPE_SRV);
|
dns_rrlist_sort(ansl, DNS_TYPE_SRV, (size_t)dns->arg);
|
||||||
|
|
||||||
/* Find SRV answers */
|
/* Find SRV answers */
|
||||||
rr = dns_rrlist_find(ansl, NULL, DNS_TYPE_SRV, DNS_CLASS_IN, false);
|
rr = dns_rrlist_find(ansl, NULL, DNS_TYPE_SRV, DNS_CLASS_IN, false);
|
||||||
|
|
Loading…
Add table
Reference in a new issue