:param string path: path to hosts file, default: ``"/etc/hosts"``
:return: ``{ result: bool }``
-
+
Load specified hosts file.
.. function:: hints.get(hostname)
:param string pair: ``hostname address`` i.e. ``"localhost 127.0.0.1"``
: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()
}
.. 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
+
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)
{
/* Build key */
if (!knot_dname_from_str(key, name, sizeof(key))) {
return kr_error(EINVAL);
}
+ const knot_rdata_t *rdata = addr2rdata(addr);
+ if (!rdata) {
+ return kr_error(EINVAL);
+ }
- /* Parse address string */
- struct sockaddr_storage ss;
- if (parse_addr_str(&ss, addr) != 0) {
+ return kr_zonecut_add(hints, key, rdata);
+}
+
+/** 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);
}
- /* Build RDATA */
- size_t addr_len = kr_inaddr_len((struct sockaddr *)&ss);
- const uint8_t *raw_addr = (const uint8_t *)kr_inaddr((struct sockaddr *)&ss);
- /* @warning _NOT_ thread-safe */
- static knot_rdata_t rdata_arr[RDATA_ARR_MAX];
- knot_rdata_init(rdata_arr, addr_len, raw_addr, 0);
- return kr_zonecut_add(hints, key, rdata_arr);
+ if (addr) {
+ /* Remove the pair. */
+ const knot_rdata_t *rdata = addr2rdata(addr);
+ if (!rdata) {
+ return kr_error(EINVAL);
+ }
+ 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)
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. */
static JsonNode *pack_addrs(pack_t *pack)
{
{
static struct kr_prop prop_list[] = {
{ &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_root, "root", "Replace root hints set (empty value to return current list).", },
{ NULL, NULL, NULL }