Skip to content
Snippets Groups Projects
Commit 40aa2592 authored by Vladimír Čunát's avatar Vladimír Čunát
Browse files

Merge !82: hints: allow removing hints and listing all of them

See commits for details.
parents f3505a68 ccba5cd3
Branches
Tags
1 merge request!82hints: allow removing hints
...@@ -267,6 +267,21 @@ int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd ...@@ -267,6 +267,21 @@ int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd
return ret; return ret;
} }
int kr_zonecut_del_all(struct kr_zonecut *cut, const knot_dname_t *ns)
{
if (!cut || !ns) {
return kr_error(EINVAL);
}
/* Find the address list; then free and remove it. */
pack_t *pack = kr_zonecut_find(cut, ns);
if (pack == NULL) {
return kr_error(ENOENT);
}
free_addr_set((const char *)ns, pack, cut->pool);
return map_del(&cut->nsset, (const char *)ns);
}
pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns) pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns)
{ {
if (!cut || !ns) { if (!cut || !ns) {
......
...@@ -32,7 +32,7 @@ struct kr_zonecut { ...@@ -32,7 +32,7 @@ struct kr_zonecut {
knot_rrset_t* key; /**< Zone cut DNSKEY. */ knot_rrset_t* key; /**< Zone cut DNSKEY. */
knot_rrset_t* trust_anchor; /**< Current trust anchor. */ knot_rrset_t* trust_anchor; /**< Current trust anchor. */
struct kr_zonecut *parent; /**< Parent zone cut. */ struct kr_zonecut *parent; /**< Parent zone cut. */
map_t nsset; /**< Map of nameserver => address_set. */ map_t nsset; /**< Map of nameserver => address_set. */
knot_mm_t *pool; /**< Memory pool. */ knot_mm_t *pool; /**< Memory pool. */
}; };
...@@ -104,6 +104,15 @@ int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd ...@@ -104,6 +104,15 @@ int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd
KR_EXPORT KR_EXPORT
int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rdata_t *rdata); int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rdata_t *rdata);
/**
* Delete all addresses associated with the given name.
* @param cut
* @param ns name server name
* @return 0 or error code
*/
KR_EXPORT
int kr_zonecut_del_all(struct kr_zonecut *cut, const knot_dname_t *ns);
/** /**
* Find nameserver address list in the zone cut. * Find nameserver address list in the zone cut.
* *
......
...@@ -30,7 +30,7 @@ Properties ...@@ -30,7 +30,7 @@ Properties
:param string path: path to hosts file, default: ``"/etc/hosts"`` :param string path: path to hosts file, default: ``"/etc/hosts"``
:return: ``{ result: bool }`` :return: ``{ result: bool }``
Load specified hosts file. Load specified hosts file.
.. function:: hints.get(hostname) .. function:: hints.get(hostname)
...@@ -39,24 +39,32 @@ Properties ...@@ -39,24 +39,32 @@ Properties
:return: ``{ result: [address1, address2, ...] }`` :return: ``{ result: [address1, address2, ...] }``
Return list of address record matching given name. Return list of address record matching given name.
If no hostname is specified, all hints are returned in the table format used by ``hints.root()``.
.. function:: hints.set(pair) .. function:: hints.set(pair)
:param string pair: ``hostname address`` i.e. ``"localhost 127.0.0.1"`` :param string pair: ``hostname address`` i.e. ``"localhost 127.0.0.1"``
:return: ``{ result: bool }`` :return: ``{ result: bool }``
Set hostname - address pair hint. Add a hostname - address pair hint.
.. function:: hints.del(pair)
:param string pair: ``hostname address`` i.e. ``"localhost 127.0.0.1"``, or just ``hostname``
:return: ``{ result: bool }``
Remove a hostname - address pair hint. If address is omitted, all addresses for the given name are deleted.
.. function:: hints.root() .. function:: hints.root()
:return: ``{ ['a.root-servers.net'] = { '1.2.3.4', '5.6.7.8', ...}, ... }`` :return: ``{ ['a.root-servers.net.'] = { '1.2.3.4', '5.6.7.8', ...}, ... }``
.. tip:: If no parameters are passed, returns current root hints set. .. tip:: If no parameters are passed, returns current root hints set.
.. function:: hints.root(root_hints) .. function:: hints.root(root_hints)
:param table root_hints: new set of root hints i.e. ``{['name'] = 'addr', ...}`` :param table root_hints: new set of root hints i.e. ``{['name'] = 'addr', ...}``
:return: ``{ ['a.root-servers.net'] = { '1.2.3.4', '5.6.7.8', ...}, ... }`` :return: ``{ ['a.root-servers.net.'] = { '1.2.3.4', '5.6.7.8', ...}, ... }``
Replace current root hints and return the current table of root hints. Replace current root hints and return the current table of root hints.
...@@ -76,4 +84,4 @@ Properties ...@@ -76,4 +84,4 @@ Properties
} }
.. tip:: A good rule of thumb is to select only a few fastest root hints. The server learns RTT and NS quality over time, and thus tries all servers available. You can help it by preselecting the candidates. .. tip:: A good rule of thumb is to select only a few fastest root hints. The server learns RTT and NS quality over time, and thus tries all servers available. You can help it by preselecting the candidates.
\ No newline at end of file
...@@ -216,6 +216,22 @@ static int parse_addr_str(struct sockaddr_storage *sa, const char *addr) ...@@ -216,6 +216,22 @@ static int parse_addr_str(struct sockaddr_storage *sa, const char *addr)
return 0; return 0;
} }
/** @warning _NOT_ thread-safe; returns a pointer to static data! */
static const knot_rdata_t * addr2rdata(const char *addr) {
/* Parse address string */
struct sockaddr_storage ss;
if (parse_addr_str(&ss, addr) != 0) {
return NULL;
}
/* Build RDATA */
static knot_rdata_t rdata_arr[RDATA_ARR_MAX];
size_t addr_len = kr_inaddr_len((struct sockaddr *)&ss);
const uint8_t *raw_addr = (const uint8_t *)kr_inaddr((struct sockaddr *)&ss);
knot_rdata_init(rdata_arr, addr_len, raw_addr, 0);
return rdata_arr;
}
static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr) static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr)
{ {
/* Build key */ /* Build key */
...@@ -223,20 +239,34 @@ static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr ...@@ -223,20 +239,34 @@ static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr
if (!knot_dname_from_str(key, name, sizeof(key))) { if (!knot_dname_from_str(key, name, sizeof(key))) {
return kr_error(EINVAL); return kr_error(EINVAL);
} }
const knot_rdata_t *rdata = addr2rdata(addr);
if (!rdata) {
return kr_error(EINVAL);
}
/* Parse address string */ return kr_zonecut_add(hints, key, rdata);
struct sockaddr_storage ss; }
if (parse_addr_str(&ss, addr) != 0) {
/** For a given name, remove either one address or all of them (if == NULL). */
static int del_pair(struct kr_zonecut *hints, const char *name, const char *addr)
{
/* Build key */
knot_dname_t key[KNOT_DNAME_MAXLEN];
if (!knot_dname_from_str(key, name, sizeof(key))) {
return kr_error(EINVAL); return kr_error(EINVAL);
} }
/* Build RDATA */ if (addr) {
size_t addr_len = kr_inaddr_len((struct sockaddr *)&ss); /* Remove the pair. */
const uint8_t *raw_addr = (const uint8_t *)kr_inaddr((struct sockaddr *)&ss); const knot_rdata_t *rdata = addr2rdata(addr);
/* @warning _NOT_ thread-safe */ if (!rdata) {
static knot_rdata_t rdata_arr[RDATA_ARR_MAX]; return kr_error(EINVAL);
knot_rdata_init(rdata_arr, addr_len, raw_addr, 0); }
return kr_zonecut_add(hints, key, rdata_arr); return kr_zonecut_del(hints, key, rdata);
} else {
/* Remove the whole name. */
return kr_zonecut_del_all(hints, key);
}
} }
static int load_map(struct kr_zonecut *hints, FILE *fp) static int load_map(struct kr_zonecut *hints, FILE *fp)
...@@ -327,6 +357,25 @@ static char* hint_set(void *env, struct kr_module *module, const char *args) ...@@ -327,6 +357,25 @@ static char* hint_set(void *env, struct kr_module *module, const char *args)
return result; return result;
} }
static char* hint_del(void *env, struct kr_module *module, const char *args)
{
struct kr_zonecut *hints = module->data;
auto_free char *args_copy = strdup(args);
int ret = -1;
char *addr = strchr(args_copy, ' ');
if (addr) {
*addr = '\0';
++addr;
}
ret = del_pair(hints, args_copy, addr);
char *result = NULL;
if (-1 == asprintf(&result, "{ \"result\": %s }", ret == 0 ? "true" : "false"))
result = NULL;
return result;
}
/** @internal Pack address list into JSON array. */ /** @internal Pack address list into JSON array. */
static JsonNode *pack_addrs(pack_t *pack) static JsonNode *pack_addrs(pack_t *pack)
{ {
...@@ -345,8 +394,9 @@ static JsonNode *pack_addrs(pack_t *pack) ...@@ -345,8 +394,9 @@ static JsonNode *pack_addrs(pack_t *pack)
return root; return root;
} }
static char* pack_hints(struct kr_zonecut *hints);
/** /**
* Retrieve address hint for given name. * Retrieve address hints, either for given name or for all names.
* *
* Input: name * Input: name
* Output: { address1, address2, ... } * Output: { address1, address2, ... }
...@@ -354,6 +404,11 @@ static JsonNode *pack_addrs(pack_t *pack) ...@@ -354,6 +404,11 @@ static JsonNode *pack_addrs(pack_t *pack)
static char* hint_get(void *env, struct kr_module *module, const char *args) static char* hint_get(void *env, struct kr_module *module, const char *args)
{ {
struct kr_zonecut *hints = module->data; struct kr_zonecut *hints = module->data;
if (!args) {
return pack_hints(hints);
}
knot_dname_t key[KNOT_DNAME_MAXLEN]; knot_dname_t key[KNOT_DNAME_MAXLEN];
pack_t *pack = NULL; pack_t *pack = NULL;
if (knot_dname_from_str(key, args, sizeof(key))) { if (knot_dname_from_str(key, args, sizeof(key))) {
...@@ -386,6 +441,17 @@ static int pack_hint(const char *k, void *v, void *baton) ...@@ -386,6 +441,17 @@ static int pack_hint(const char *k, void *v, void *baton)
return kr_ok(); return kr_ok();
} }
/** @internal Pack all hints into serialized JSON. */
static char* pack_hints(struct kr_zonecut *hints) {
char *result = NULL;
JsonNode *root_node = json_mkobject();
if (map_walk(&hints->nsset, pack_hint, root_node) == 0) {
result = json_encode(root_node);
}
json_delete(root_node);
return result;
}
static void unpack_hint(struct kr_zonecut *root_hints, JsonNode *table, const char *name) static void unpack_hint(struct kr_zonecut *root_hints, JsonNode *table, const char *name)
{ {
JsonNode *node = NULL; JsonNode *node = NULL;
...@@ -418,13 +484,7 @@ static char* hint_root(void *env, struct kr_module *module, const char *args) ...@@ -418,13 +484,7 @@ static char* hint_root(void *env, struct kr_module *module, const char *args)
json_delete(root_node); json_delete(root_node);
} }
/* Return current root hints */ /* Return current root hints */
char *result = NULL; return pack_hints(root_hints);
JsonNode *root_node = json_mkobject();
if (map_walk(&root_hints->nsset, pack_hint, root_node) == 0) {
result = json_encode(root_node);
}
json_delete(root_node);
return result;
} }
/* /*
...@@ -471,6 +531,7 @@ struct kr_prop *hints_props(void) ...@@ -471,6 +531,7 @@ struct kr_prop *hints_props(void)
{ {
static struct kr_prop prop_list[] = { static struct kr_prop prop_list[] = {
{ &hint_set, "set", "Set {name, address} hint.", }, { &hint_set, "set", "Set {name, address} hint.", },
{ &hint_del, "del", "Delete one {name, address} hint or all addresses for the name.", },
{ &hint_get, "get", "Retrieve hint for given name.", }, { &hint_get, "get", "Retrieve hint for given name.", },
{ &hint_root, "root", "Replace root hints set (empty value to return current list).", }, { &hint_root, "root", "Replace root hints set (empty value to return current list).", },
{ NULL, NULL, NULL } { NULL, NULL, NULL }
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment