static knot_dname_t *synth_ptrname(const char *addr_str, synth_template_t *tpl) { /* PTR right-hand value is [prefix][address][zone] */ char ptrname[KNOT_DNAME_MAXLEN] = {'\0'}; int prefix_len = strlen(tpl->prefix); int addr_len = strlen(addr_str); int zone_len = strlen(tpl->zone); /* Check required space (zone requires extra leading dot). */ if (prefix_len + addr_len + zone_len + 1 >= KNOT_DNAME_MAXLEN) { return NULL; } /* Write prefix string. */ memcpy(ptrname, tpl->prefix, prefix_len); int written = prefix_len; /* Write address with substituted separator to '-'. */ char sep = str_separator(tpl->subnet.ss.ss_family); memcpy(ptrname + written, addr_str, addr_len); str_subst(ptrname + written, addr_len, sep, '-'); written += addr_len; /* Write zone name. */ ptrname[written] = '.'; written += 1; memcpy(ptrname + written, tpl->zone, zone_len); /* Convert to domain name. */ return knot_dname_from_str(ptrname); }
static int rosedb_get(struct cache *cache, MDB_txn *txn, int argc, char *argv[]) { knot_dname_t key[KNOT_DNAME_MAXLEN] = { '\0' }; knot_dname_from_str(key, argv[0], sizeof(key)); knot_dname_to_lower(key); char type_str[16] = { '\0' }; struct iter it; int ret = cache_query_fetch(txn, cache->dbi, &it, key); while (ret == 0) { struct entry entry; cache_iter_val(&it, &entry); knot_rdata_t *rd = knot_rdataset_at(&entry.data.rrs, 0); knot_rrtype_to_string(entry.data.type, type_str, sizeof(type_str)); printf("%s\t%s\tTTL=%u\tRDLEN=%u\t%s\t%s\n", argv[0], type_str, knot_rdata_ttl(rd), knot_rdata_rdlen(rd), entry.threat_code, entry.syslog_ip); if (cache_iter_next(&it) != 0) { break; } } cache_iter_free(&it); return ret; }
static int rosedb_del(struct cache *cache, MDB_txn *txn, int argc, char *argv[]) { printf("DEL %s\n", argv[0]); knot_dname_t key[KNOT_DNAME_MAXLEN] = { '\0' }; knot_dname_from_str(key, argv[0], sizeof(key)); knot_dname_to_lower(key); int ret = cache_remove(txn, cache->dbi, key); if (ret != 0) { fprintf(stderr, "%s\n", mdb_strerror(ret)); } return ret; }
static int wrk_resolve(lua_State *L) { struct worker_ctx *worker = wrk_luaget(L); if (!worker) { return 0; } /* Create query packet */ knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_EDNS_MAX_UDP_PAYLOAD, NULL); if (!pkt) { lua_pushstring(L, strerror(ENOMEM)); lua_error(L); } uint8_t dname[KNOT_DNAME_MAXLEN]; knot_dname_from_str(dname, lua_tostring(L, 1), sizeof(dname)); /* Check class and type */ uint16_t rrtype = lua_tointeger(L, 2); if (!lua_isnumber(L, 2)) { lua_pushstring(L, "invalid RR type"); lua_error(L); } uint16_t rrclass = lua_tointeger(L, 3); if (!lua_isnumber(L, 3)) { /* Default class is IN */ rrclass = KNOT_CLASS_IN; } knot_pkt_put_question(pkt, dname, rrclass, rrtype); knot_wire_set_rd(pkt->wire); /* Add OPT RR */ pkt->opt_rr = knot_rrset_copy(worker->engine->resolver.opt_rr, NULL); if (!pkt->opt_rr) { return kr_error(ENOMEM); } /* Add completion callback */ int ret = 0; unsigned options = lua_tointeger(L, 4); if (lua_isfunction(L, 5)) { /* Store callback in registry */ lua_pushvalue(L, 5); int cb = luaL_ref(L, LUA_REGISTRYINDEX); ret = worker_resolve(worker, pkt, options, resolve_callback, (void *) (intptr_t)cb); } else { ret = worker_resolve(worker, pkt, options, NULL, NULL); } knot_rrset_free(&pkt->opt_rr, NULL); knot_pkt_free(&pkt); lua_pushboolean(L, ret == 0); return 1; }
/** Enable/disable trust anchor. */ static int l_trustanchor(lua_State *L) { struct engine *engine = engine_luaget(L); const char *anchor = lua_tostring(L, 1); bool enable = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : true; if (!anchor || strlen(anchor) == 0) { return 0; } /* If disabling, parse the owner string only. */ if (!enable) { knot_dname_t *owner = knot_dname_from_str(NULL, anchor, KNOT_DNAME_MAXLEN); if (!owner) { lua_pushstring(L, "invalid trust anchor owner"); lua_error(L); } lua_pushboolean(L, kr_ta_del(&engine->resolver.trust_anchors, owner) == 0); free(owner); return 1; } /* Parse the record */ zs_scanner_t *zs = malloc(sizeof(*zs)); if (!zs || zs_init(zs, ".", 1, 0) != 0) { free(zs); lua_pushstring(L, "not enough memory"); lua_error(L); } int ok = zs_set_input_string(zs, anchor, strlen(anchor)) == 0 && zs_parse_all(zs) == 0; /* Add it to TA set and cleanup */ if (ok) { ok = kr_ta_add(&engine->resolver.trust_anchors, zs->r_owner, zs->r_type, zs->r_ttl, zs->r_data, zs->r_data_length) == 0; } zs_deinit(zs); free(zs); /* Report errors */ if (!ok) { lua_pushstring(L, "failed to process trust anchor RR"); lua_error(L); } lua_pushboolean(L, true); return 1; }
/** * Retrieve address hint for given name. * * Input: name * Output: { address1, address2, ... } */ static char* hint_get(void *env, struct kr_module *module, const char *args) { struct kr_zonecut *hints = module->data; knot_dname_t key[KNOT_DNAME_MAXLEN]; pack_t *pack = NULL; if (knot_dname_from_str(key, args, sizeof(key))) { pack = kr_zonecut_find(hints, key); } if (!pack || pack->len == 0) { return NULL; } char *result = NULL; JsonNode *root = pack_addrs(pack); if (root) { result = json_encode(root); json_delete(root); } return result; }
static int yp_dname_to_bin( TXT_BIN_PARAMS) { knot_dname_t *dname = knot_dname_from_str(bin, txt, *bin_len); if (dname == NULL) { return KNOT_EINVAL; } int ret = knot_dname_wire_check(bin, bin + *bin_len, NULL); if (ret <= 0) { return KNOT_EINVAL; } *bin_len = ret; ret = knot_dname_to_lower(bin); if (ret != KNOT_EOK) { return KNOT_EINVAL; } return KNOT_EOK; }
static int add_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); } /* Parse address string */ struct sockaddr_storage ss; if (parse_addr_str(&ss, addr) != 0) { return kr_error(EINVAL); } /* Build rdata */ size_t addr_len = 0; uint8_t *raw_addr = sockaddr_raw(&ss, &addr_len); knot_rdata_t rdata[knot_rdata_array_size(addr_len)]; knot_rdata_init(rdata, addr_len, raw_addr, 0); return kr_zonecut_add(hints, key, rdata); }
static int rosedb_add(struct cache *cache, MDB_txn *txn, int argc, char *argv[]) { printf("ADD %s\t%s\t%s\t%s\t%s\t%s\n", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); knot_dname_t key[KNOT_DNAME_MAXLEN] = { '\0' }; knot_dname_from_str(key, argv[0], sizeof(key)); knot_dname_to_lower(key); struct entry entry; int ret = parse_rdata(&entry, argv[0], argv[1], argv[3], atoi(argv[2]), cache->pool); entry.threat_code = argv[4]; entry.syslog_ip = argv[5]; if (ret != 0) { fprintf(stderr, "PARSE: %s\n", knot_strerror(ret)); return ret; } ret = cache_insert(txn, cache->dbi, key, &entry); if (ret != 0) { fprintf(stderr, "%s\n", mdb_strerror(ret)); } return ret; }
int main(int argc, char *argv[]) { plan(10); /* Prepare query. */ knot_pkt_t *query = knot_pkt_new(NULL, 512, NULL); if (query == NULL) { return KNOT_ERROR; /* Fatal */ } knot_dname_t *qname = knot_dname_from_str("beef."); int ret = knot_pkt_put_question(query, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A); knot_dname_free(&qname, NULL); if (ret != KNOT_EOK) { knot_pkt_free(&query); return KNOT_ERROR; /* Fatal */ } /* Prepare response */ uint8_t rbuf[65535]; size_t rlen = sizeof(rbuf); memcpy(rbuf, query->wire, query->size); knot_wire_flags_set_qr(rbuf); rrl_req_t rq; rq.w = rbuf; rq.len = rlen; rq.query = query; rq.flags = 0; /* 1. create rrl table */ rrl_table_t *rrl = rrl_create(RRL_SIZE); ok(rrl != NULL, "rrl: create"); /* 2. set rate limit */ uint32_t rate = 10; rrl_setrate(rrl, rate); is_int(rate, rrl_rate(rrl), "rrl: setrate"); /* 3. setlocks */ ret = rrl_setlocks(rrl, RRL_LOCKS); is_int(KNOT_EOK, ret, "rrl: setlocks"); /* 4. N unlimited requests. */ conf_zone_t *zone_conf = malloc(sizeof(conf_zone_t)); conf_init_zone(zone_conf); zone_conf->name = strdup("rrl."); zone_t *zone = zone_new(zone_conf); struct sockaddr_storage addr; struct sockaddr_storage addr6; sockaddr_set(&addr, AF_INET, "1.2.3.4", 0); sockaddr_set(&addr6, AF_INET6, "1122:3344:5566:7788::aabb", 0); ret = 0; for (unsigned i = 0; i < rate; ++i) { if (rrl_query(rrl, &addr, &rq, zone) != KNOT_EOK || rrl_query(rrl, &addr6, &rq, zone) != KNOT_EOK) { ret = KNOT_ELIMIT; break; } } is_int(0, ret, "rrl: unlimited IPv4/v6 requests"); #ifdef ENABLE_TIMED_TESTS /* 5. limited request */ ret = rrl_query(rrl, &addr, &rq, zone); is_int(0, ret, "rrl: throttled IPv4 request"); /* 6. limited IPv6 request */ ret = rrl_query(rrl, &addr6, &rq, zone); is_int(0, ret, "rrl: throttled IPv6 request"); #else skip_block(2, "Timed tests not enabled"); #endif /* 7. invalid values. */ ret = 0; rrl_create(0); // NULL ret += rrl_setrate(0, 0); // 0 ret += rrl_rate(0); // 0 ret += rrl_setlocks(0,0); // -1 ret += rrl_query(0, 0, 0, 0); // -1 ret += rrl_query(rrl, 0, 0, 0); // -1 ret += rrl_query(rrl, (void*)0x1, 0, 0); // -1 ret += rrl_destroy(0); // -1 is_int(-488, ret, "rrl: not crashed while executing functions on NULL context"); #ifdef ENABLE_TIMED_TESTS /* 8. hopscotch test */ struct runnable_data rd = { 1, rrl, &addr, &rq, zone }; rrl_hopscotch(&rd); ok(rd.passed, "rrl: hashtable is ~ consistent"); /* 9. reseed */ is_int(0, rrl_reseed(rrl), "rrl: reseed"); /* 10. hopscotch after reseed. */ rrl_hopscotch(&rd); ok(rd.passed, "rrl: hashtable is ~ consistent"); #else skip_block(3, "Timed tests not enabled"); #endif zone_free(&zone); knot_pkt_free(&query); rrl_destroy(rrl); return 0; }
int synth_record_load(struct query_plan *plan, struct query_module *self) { /* Parse first token. */ char *saveptr = NULL; char *token = strtok_r(self->param, " ", &saveptr); if (token == NULL) { return KNOT_EFEWDATA; } /* Create synthesis template. */ struct synth_template *tpl = mm_alloc(self->mm, sizeof(struct synth_template)); if (tpl == NULL) { return KNOT_ENOMEM; } /* Save in query module, it takes ownership from now on. */ self->ctx = tpl; /* Supported types: reverse, forward */ if (strcmp(token, "reverse") == 0) { tpl->type = SYNTH_REVERSE; } else if (strcmp(token, "forward") == 0) { tpl->type = SYNTH_FORWARD; } else { MODULE_ERR("invalid type '%s'.\n", token); return KNOT_ENOTSUP; } /* Parse format string. */ tpl->prefix = strtok_r(NULL, " ", &saveptr); if (strchr(tpl->prefix, '.') != NULL) { MODULE_ERR("dots '.' are not allowed in the prefix.\n"); return KNOT_EMALF; } /* Parse zone if generating reverse record. */ if (tpl->type == SYNTH_REVERSE) { tpl->zone = strtok_r(NULL, " ", &saveptr); knot_dname_t *check_name = knot_dname_from_str(tpl->zone); if (check_name == NULL) { MODULE_ERR("invalid zone '%s'.\n", tpl->zone); return KNOT_EMALF; } knot_dname_free(&check_name, NULL); } /* Parse TTL. */ tpl->ttl = strtol(strtok_r(NULL, " ", &saveptr), NULL, 10); /* Parse address. */ token = strtok_r(NULL, " ", &saveptr); char *subnet = strchr(token, '/'); if (subnet) { subnet[0] = '\0'; tpl->subnet.prefix = strtol(subnet + 1, NULL, 10); } /* Estimate family. */ int family = AF_INET; int prefix_max = IPV4_PREFIXLEN; if (strchr(token, ':') != NULL) { family = AF_INET6; prefix_max = IPV6_PREFIXLEN; } /* Check subnet. */ if (tpl->subnet.prefix > prefix_max) { MODULE_ERR("invalid address prefix '%s'.\n", subnet); return KNOT_EMALF; } int ret = sockaddr_set(&tpl->subnet.ss, family, token, 0); if (ret != KNOT_EOK) { MODULE_ERR("invalid address '%s'.\n", token); return KNOT_EMALF; } return query_plan_step(plan, QPLAN_ANSWER, solve_synth_record, tpl); }
/*! * \brief Entry point of 'knsec3hash'. */ int main(int argc, char *argv[]) { bool enable_idn = true; struct option options[] = { { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { NULL } }; #ifdef LIBIDN // Set up localization. if (setlocale(LC_CTYPE, "") == NULL) { enable_idn = false; } #endif int opt = 0; int li = 0; while ((opt = getopt_long(argc, argv, "hV", options, &li)) != -1) { switch(opt) { case 'V': printf("%s, version %s\n", PROGRAM_NAME, PACKAGE_VERSION); return 0; case 'h': usage(stdout); return 0; default: usage(stderr); return 1; } } // knsec3hash <salt> <algorithm> <iterations> <domain> if (argc != 5) { usage(stderr); return 1; } atexit(knot_crypto_cleanup); int exit_code = 1; knot_nsec3_params_t nsec3_params = { 0 }; knot_dname_t *dname = NULL; uint8_t *digest = NULL; size_t digest_size = 0; uint8_t *b32_digest = NULL; int32_t b32_length = 0; int result = 0; if (!parse_nsec3_params(&nsec3_params, argv[1], argv[2], argv[3])) { goto fail; } if (enable_idn) { char *ascii_name = name_from_idn(argv[4]); if (ascii_name == NULL) { fprintf(stderr, "Cannot transform IDN domain name.\n"); goto fail; } dname = knot_dname_from_str(ascii_name); free(ascii_name); } else { dname = knot_dname_from_str(argv[4]); } if (dname == NULL) { fprintf(stderr, "Cannot parse domain name.\n"); goto fail; } result = knot_nsec3_hash(&nsec3_params, dname, knot_dname_size(dname), &digest, &digest_size); if (result != KNOT_EOK) { fprintf(stderr, "Cannot compute hash: %s\n", knot_strerror(result)); goto fail; } b32_length = base32hex_encode_alloc(digest, digest_size, &b32_digest); if (b32_length < 0) { fprintf(stderr, "Cannot encode computed hash: %s\n", knot_strerror(b32_length)); goto fail; } exit_code = 0; printf("%.*s (salt=%s, hash=%d, iterations=%d)\n", b32_length, b32_digest, argv[1], nsec3_params.algorithm, nsec3_params.iterations); fail: knot_nsec3param_free(&nsec3_params); knot_dname_free(&dname, NULL); free(digest); free(b32_digest); return exit_code; }