static isc_result_t rdata_clone(isc_mem_t *mctx, dns_rdata_t *source, dns_rdata_t **targetp) { isc_result_t result; dns_rdata_t *target = NULL; isc_region_t target_region, source_region; REQUIRE(mctx != NULL); REQUIRE(source != NULL); REQUIRE(targetp != NULL && *targetp == NULL); CHECKED_MEM_GET_PTR(mctx, target); dns_rdata_init(target); dns_rdata_toregion(source, &source_region); CHECKED_MEM_GET(mctx, target_region.base, source_region.length); target_region.length = source_region.length; memcpy(target_region.base, source_region.base, source_region.length); dns_rdata_fromregion(target, source->rdclass, source->type, &target_region); *targetp = target; return ISC_R_SUCCESS; cleanup: SAFE_MEM_PUT_PTR(mctx, target); return result; }
ATF_TC_BODY(hip, tc) { unsigned char hipwire[DNS_RDATA_MAXLENGTH] = { 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x41, 0x42, 0x43, 0x44, 0x00 }; unsigned char buf[1024*1024]; isc_buffer_t source, target; dns_rdata_t rdata; dns_decompress_t dctx; isc_result_t result; size_t i; UNUSED(tc); /* * Fill the rest of input buffer with compression pointers. */ for (i = 12; i < sizeof(hipwire) - 2; i += 2) { hipwire[i] = 0xc0; hipwire[i+1] = 0x06; } isc_buffer_init(&source, hipwire, sizeof(hipwire)); isc_buffer_add(&source, sizeof(hipwire)); isc_buffer_setactive(&source, i); isc_buffer_init(&target, buf, sizeof(buf)); dns_rdata_init(&rdata); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, dns_rdatatype_hip, &source, &dctx, 0, &target); dns_decompress_invalidate(&dctx); ATF_REQUIRE_EQ(result, DNS_R_FORMERR); }
isc_result_t dns_nsec_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, dns_name_t *target, dns_ttl_t ttl) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned char data[DNS_NSEC_BUFFERSIZE]; dns_rdatalist_t rdatalist; dns_rdataset_t rdataset; dns_rdataset_init(&rdataset); dns_rdata_init(&rdata); RETERR(dns_nsec_buildrdata(db, version, node, target, data, &rdata)); rdatalist.rdclass = dns_db_class(db); rdatalist.type = dns_rdatatype_nsec; rdatalist.covers = 0; rdatalist.ttl = ttl; ISC_LIST_INIT(rdatalist.rdata); ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); RETERR(dns_rdatalist_tordataset(&rdatalist, &rdataset)); result = dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL); if (result == DNS_R_UNCHANGED) result = ISC_R_SUCCESS; RETERR(result); failure: if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); return (result); }
static isc_result_t fill_array(int *pos, dns_rdataset_t *rdataset, int size, unsigned char **rdatas, lwres_uint16_t *rdatalen) { dns_rdata_t rdata; isc_result_t result; isc_region_t r; UNUSED(size); dns_rdata_init(&rdata); for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { INSIST(*pos < size); dns_rdataset_current(rdataset, &rdata); dns_rdata_toregion(&rdata, &r); rdatas[*pos] = r.base; rdatalen[*pos] = r.length; dns_rdata_reset(&rdata); (*pos)++; } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; return (result); }
/*% * Configure an apex NS with an out-of-zone NS names for a static-stub zone. * For example, for the zone named "example.com", something like the following * RRs will be added to the zone DB: * example.com. NS ns.example.net. */ static isc_result_t configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone, dns_rdatalist_t *rdatalist, const char *zname) { const cfg_listelt_t *element; isc_mem_t *mctx = dns_zone_getmctx(zone); dns_rdata_t *rdata; isc_region_t sregion, region; isc_result_t result = ISC_R_SUCCESS; for (element = cfg_list_first(zconfig); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *obj; const char *str; dns_fixedname_t fixed_name; dns_name_t *nsname; isc_buffer_t b; obj = cfg_listelt_value(element); str = cfg_obj_asstring(obj); dns_fixedname_init(&fixed_name); nsname = dns_fixedname_name(&fixed_name); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "server-name '%s' is not a valid " "name", str); return (result); } if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "server-name '%s' must not be a " "subdomain of zone name '%s'", str, zname); return (ISC_R_FAILURE); } dns_name_toregion(nsname, &sregion); rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); if (rdata == NULL) return (ISC_R_NOMEMORY); region.length = sregion.length; region.base = (unsigned char *)(rdata + 1); memcpy(region.base, sregion.base, region.length); dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns, ®ion); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); } return (result); }
isc_result_t dns_difftuple_create(isc_mem_t *mctx, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata, dns_difftuple_t **tp) { dns_difftuple_t *t; unsigned int size; unsigned char *datap; REQUIRE(tp != NULL && *tp == NULL); /* * Create a new tuple. The variable-size wire-format name data and * rdata immediately follow the dns_difftuple_t structure * in memory. */ size = sizeof(*t) + name->length + rdata->length; t = isc_mem_allocate(mctx, size); if (t == NULL) return (ISC_R_NOMEMORY); t->mctx = NULL; isc_mem_attach(mctx, &t->mctx); t->op = op; datap = (unsigned char *)(t + 1); memmove(datap, name->ndata, name->length); dns_name_init(&t->name, NULL); dns_name_clone(name, &t->name); t->name.ndata = datap; datap += name->length; t->ttl = ttl; memmove(datap, rdata->data, rdata->length); dns_rdata_init(&t->rdata); dns_rdata_clone(rdata, &t->rdata); t->rdata.data = datap; datap += rdata->length; ISC_LINK_INIT(&t->rdata, link); ISC_LINK_INIT(t, link); t->magic = DNS_DIFFTUPLE_MAGIC; INSIST(datap == (unsigned char *)t + size); *tp = t; return (ISC_R_SUCCESS); }
static void log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) { isc_result_t result; isc_buffer_t buf; char mem[2000]; dns_rdatalist_t rdl; dns_rdataset_t rds; dns_rdata_t rd = DNS_RDATA_INIT; rdl.type = rdata->type; rdl.rdclass = rdata->rdclass; rdl.ttl = ttl; if (rdata->type == dns_rdatatype_sig || rdata->type == dns_rdatatype_rrsig) rdl.covers = dns_rdata_covers(rdata); else rdl.covers = dns_rdatatype_none; ISC_LIST_INIT(rdl.rdata); ISC_LINK_INIT(&rdl, link); dns_rdataset_init(&rds); dns_rdata_init(&rd); dns_rdata_clone(rdata, &rd); ISC_LIST_APPEND(rdl.rdata, &rd, link); RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS); isc_buffer_init(&buf, mem, sizeof(mem)); result = dns_rdataset_totext(&rds, name, ISC_FALSE, ISC_FALSE, &buf); /* * We could use xfrout_log(), but that would produce * very long lines with a repetitive prefix. */ if (result == ISC_R_SUCCESS) { /* * Get rid of final newline. */ INSIST(buf.used >= 1 && ((char *) buf.base)[buf.used - 1] == '\n'); buf.used--; isc_log_write(XFROUT_RR_LOGARGS, "%.*s", (int)isc_buffer_usedlength(&buf), (char *)isc_buffer_base(&buf)); } else { isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>"); } }
static void loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, dns_rdata_t *rdata) { isc_result_t result; dst_key_t *key = NULL; isc_buffer_t keyb; isc_region_t r; dns_rdata_init(rdata); isc_buffer_init(&keyb, key_buf, key_buf_size); result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, mctx, &key); if (result != ISC_R_SUCCESS) fatal("invalid keyfile name %s: %s", filename, isc_result_totext(result)); if (verbose > 2) { char keystr[DST_KEY_FORMATSIZE]; dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); } result = dst_key_todns(key, &keyb); if (result != ISC_R_SUCCESS) fatal("can't decode key"); isc_buffer_usedregion(&keyb, &r); dns_rdata_fromregion(rdata, dst_key_class(key), dns_rdatatype_dnskey, &r); rdclass = dst_key_class(key); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); result = dns_name_copy(dst_key_name(key), name, NULL); if (result != ISC_R_SUCCESS) fatal("can't copy name"); dst_key_free(&key); }
static isc_result_t db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, isc_stdtime_t now) { isc_result_t result; it->db = db; it->dbit = NULL; it->ver = ver; it->now = now; it->node = NULL; result = dns_db_createiterator(it->db, 0, &it->dbit); if (result != ISC_R_SUCCESS) return (result); it->rdatasetit = NULL; dns_rdata_init(&it->rdata); dns_rdataset_init(&it->rdataset); dns_fixedname_init(&it->fixedname); INSIST(! dns_rdataset_isassociated(&it->rdataset)); it->result = ISC_R_SUCCESS; return (it->result); }
/* * Sort the rdataset into an array. */ static isc_result_t rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, dns_rdata_t **rdata, int *nrdata) { isc_result_t ret; int i = 0, n; dns_rdata_t *data; n = dns_rdataset_count(set); data = isc_mem_get(mctx, n * sizeof(dns_rdata_t)); if (data == NULL) return (ISC_R_NOMEMORY); ret = dns_rdataset_first(set); if (ret != ISC_R_SUCCESS) { isc_mem_put(mctx, data, n * sizeof(dns_rdata_t)); return (ret); } /* * Put them in the array. */ do { dns_rdata_init(&data[i]); dns_rdataset_current(set, &data[i++]); } while (dns_rdataset_next(set) == ISC_R_SUCCESS); /* * Sort the array. */ qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); *rdata = data; *nrdata = n; return (ISC_R_SUCCESS); }
int main(int argc, char **argv) { char *algname = NULL, *classname = NULL; char *filename = NULL, *dir = NULL, *namestr; char *lookaside = NULL; char *endp; int ch; unsigned int dtype = DNS_DSDIGEST_SHA1; isc_boolean_t both = ISC_TRUE; isc_boolean_t usekeyset = ISC_FALSE; isc_boolean_t showall = ISC_FALSE; isc_result_t result; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataset_t rdataset; dns_rdata_t rdata; dns_rdata_init(&rdata); if (argc == 1) usage(); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("out of memory"); dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "12Aa:c:d:Ff:K:l:sv:h")) != -1) { switch (ch) { case '1': dtype = DNS_DSDIGEST_SHA1; both = ISC_FALSE; break; case '2': dtype = DNS_DSDIGEST_SHA256; both = ISC_FALSE; break; case 'A': showall = ISC_TRUE; break; case 'a': algname = isc_commandline_argument; both = ISC_FALSE; break; case 'c': classname = isc_commandline_argument; break; case 'd': fprintf(stderr, "%s: the -d option is deprecated; " "use -K\n", program); /* fall through */ case 'K': dir = isc_commandline_argument; if (strlen(dir) == 0U) fatal("directory must be non-empty string"); break; case 'f': filename = isc_commandline_argument; break; case 'l': lookaside = isc_commandline_argument; if (strlen(lookaside) == 0U) fatal("lookaside must be a non-empty string"); break; case 's': usekeyset = ISC_TRUE; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case 'F': /* Reserved for FIPS mode */ /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (algname != NULL) { if (strcasecmp(algname, "SHA1") == 0 || strcasecmp(algname, "SHA-1") == 0) dtype = DNS_DSDIGEST_SHA1; else if (strcasecmp(algname, "SHA256") == 0 || strcasecmp(algname, "SHA-256") == 0) dtype = DNS_DSDIGEST_SHA256; #ifdef HAVE_OPENSSL_GOST else if (strcasecmp(algname, "GOST") == 0) dtype = DNS_DSDIGEST_GOST; #endif else if (strcasecmp(algname, "SHA384") == 0 || strcasecmp(algname, "SHA-384") == 0) dtype = DNS_DSDIGEST_SHA384; else fatal("unknown algorithm %s", algname); } rdclass = strtoclass(classname); if (usekeyset && filename != NULL) fatal("cannot use both -s and -f"); /* When not using -f, -A is implicit */ if (filename == NULL) showall = ISC_TRUE; if (argc < isc_commandline_index + 1 && filename == NULL) fatal("the key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("could not initialize hash"); result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); setup_logging(verbose, mctx, &log); dns_rdataset_init(&rdataset); if (usekeyset || filename != NULL) { if (argc < isc_commandline_index + 1 && filename != NULL) { /* using zone name as the zone file name */ namestr = filename; } else namestr = argv[isc_commandline_index]; result = initname(namestr); if (result != ISC_R_SUCCESS) fatal("could not initialize name %s", namestr); if (usekeyset) result = loadkeyset(dir, &rdataset); else result = loadsetfromfile(filename, &rdataset); if (result != ISC_R_SUCCESS) fatal("could not load DNSKEY set: %s\n", isc_result_totext(result)); for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_init(&rdata); dns_rdataset_current(&rdataset, &rdata); if (verbose > 2) logkey(&rdata); if (both) { emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata); emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata); } else emit(dtype, showall, lookaside, &rdata); } } else { unsigned char key_buf[DST_KEY_MAXSIZE]; loadkey(argv[isc_commandline_index], key_buf, DST_KEY_MAXSIZE, &rdata); if (both) { emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata); emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata); } else emit(dtype, showall, lookaside, &rdata); } if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); fflush(stdout); if (ferror(stdout)) { fprintf(stderr, "write error\n"); return (1); } else return (0); }
int main(int argc, char *argv[]) { isc_mem_t *mctx = NULL; isc_buffer_t b; int n; dns_fixedname_t origin, name; dns_db_t *db = NULL; dns_dbiterator_t *dbiter = NULL; isc_result_t res; dns_dbnode_t *node = NULL; dns_rdataset_t rdataset; dns_rdatasetiter_t *rdatasetiter = NULL; dns_rdata_t rdata; DB *bdb; if (argc != 4) usage(*argv); REQUIRE(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); n = strlen(argv[1]); isc_buffer_init(&b, argv[1], n); isc_buffer_add(&b, n); dns_fixedname_init(&origin); REQUIRE(dns_name_fromtext(dns_fixedname_name(&origin), &b, dns_rootname, 0, NULL) == ISC_R_SUCCESS); REQUIRE(dns_db_create(mctx, "rbt", dns_fixedname_name(&origin), dns_dbtype_zone, dns_rdataclass_in, 0, NULL, &db) == ISC_R_SUCCESS); REQUIRE(dns_db_load(db, argv[2]) == ISC_R_SUCCESS); REQUIRE(dns_db_createiterator(db, 0, &dbiter) == ISC_R_SUCCESS); dns_rdataset_init(&rdataset); dns_rdata_init(&rdata); dns_fixedname_init(&name); bdb = bdb_init(argv[3]); for (res = dns_dbiterator_first(dbiter); res == ISC_R_SUCCESS; res = dns_dbiterator_next(dbiter)) { dns_dbiterator_current(dbiter, &node, dns_fixedname_name(&name)); REQUIRE(dns_db_allrdatasets(db, node, NULL, 0, &rdatasetiter) == ISC_R_SUCCESS); for (res = dns_rdatasetiter_first(rdatasetiter); res == ISC_R_SUCCESS; res = dns_rdatasetiter_next(rdatasetiter)) { dns_rdatasetiter_current(rdatasetiter, &rdataset); res = dns_rdataset_first(&rdataset); while (res == ISC_R_SUCCESS) { dns_rdataset_current(&rdataset, &rdata); REQUIRE(bdb_putrdata(bdb, dns_fixedname_name(&name), rdataset.ttl, &rdata) == ISC_R_SUCCESS); dns_rdata_reset(&rdata); res = dns_rdataset_next(&rdataset); } dns_rdataset_disassociate(&rdataset); } dns_rdatasetiter_destroy(&rdatasetiter); dns_db_detachnode(db, &node); } dns_dbiterator_destroy(&dbiter); REQUIRE(bdb_destroy(bdb) == ISC_R_SUCCESS); return 0; }
static void emit(unsigned int dtype, isc_boolean_t showall, char *lookaside, dns_rdata_t *rdata) { isc_result_t result; unsigned char buf[DNS_DS_BUFFERSIZE]; char text_buf[DST_KEY_MAXTEXTSIZE]; char name_buf[DNS_NAME_MAXWIRE]; char class_buf[10]; isc_buffer_t textb, nameb, classb; isc_region_t r; dns_rdata_t ds; dns_rdata_dnskey_t dnskey; isc_buffer_init(&textb, text_buf, sizeof(text_buf)); isc_buffer_init(&nameb, name_buf, sizeof(name_buf)); isc_buffer_init(&classb, class_buf, sizeof(class_buf)); dns_rdata_init(&ds); result = dns_rdata_tostruct(rdata, &dnskey, NULL); if (result != ISC_R_SUCCESS) fatal("can't convert DNSKEY"); if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall) return; result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds); if (result != ISC_R_SUCCESS) fatal("can't build record"); result = dns_name_totext(name, ISC_FALSE, &nameb); if (result != ISC_R_SUCCESS) fatal("can't print name"); /* Add lookaside origin, if set */ if (lookaside != NULL) { if (isc_buffer_availablelength(&nameb) < strlen(lookaside)) fatal("DLV origin '%s' is too long", lookaside); isc_buffer_putstr(&nameb, lookaside); if (lookaside[strlen(lookaside) - 1] != '.') { if (isc_buffer_availablelength(&nameb) < 1) fatal("DLV origin '%s' is too long", lookaside); isc_buffer_putstr(&nameb, "."); } } result = dns_rdata_totext(&ds, (dns_name_t *) NULL, &textb); if (result != ISC_R_SUCCESS) fatal("can't print rdata"); result = dns_rdataclass_totext(rdclass, &classb); if (result != ISC_R_SUCCESS) fatal("can't print class"); isc_buffer_usedregion(&nameb, &r); printf("%.*s ", (int)r.length, r.base); isc_buffer_usedregion(&classb, &r); printf("%.*s", (int)r.length, r.base); if (lookaside == NULL) printf(" DS "); else printf(" DLV "); isc_buffer_usedregion(&textb, &r); printf("%.*s\n", (int)r.length, r.base); }
static void update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete, dns_name_t *name) { isc_result_t result; isc_uint32_t ttl; char *word; dns_rdataclass_t rdataclass; dns_rdatatype_t rdatatype; dns_rdata_t *rdata = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdataset_t *rdataset = NULL; isc_textregion_t region; /* * Read the owner name. */ parse_name(&cmdline, name); rdata = isc_mem_get(mctx, sizeof(*rdata)); if (rdata == NULL) { fprintf(stderr, "memory allocation for rdata failed\n"); exit(1); } dns_rdata_init(rdata); /* * If this is an add, read the TTL and verify that it's in range. * If it's a delete, ignore a TTL if present (for compatibility). */ word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { if (!isdelete) { fprintf(stderr, "could not read owner ttl\n"); exit(1); } else { ttl = 0; rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } } result = isc_parse_uint32(&ttl, word, 10); if (result != ISC_R_SUCCESS) { if (isdelete) { ttl = 0; goto parseclass; } else { fprintf(stderr, "ttl '%s': %s\n", word, isc_result_totext(result)); exit(1); } } if (isdelete) ttl = 0; else if (ttl > TTL_MAX) { fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word, TTL_MAX); exit(1); } /* * Read the class or type. */ word = nsu_strsep(&cmdline, " \t\r\n"); parseclass: if (word == NULL || *word == 0) { if (isdelete) { rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } else { fprintf(stderr, "could not read class or type\n"); exit(1); } } region.base = word; region.length = strlen(word); result = dns_rdataclass_fromtext(&rdataclass, ®ion); if (result == ISC_R_SUCCESS) { /* * Now read the type. */ word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { if (isdelete) { rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } else { fprintf(stderr, "could not read type\n"); exit(1); } } region.base = word; region.length = strlen(word); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "'%s' is not a valid type: %s\n", word, isc_result_totext(result)); exit(1); } } else { rdataclass = default_rdataclass; result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "'%s' is not a valid class or type: " "%s\n", word, isc_result_totext(result)); exit(1); } } parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); if (isdelete) { if ((rdata->flags & DNS_RDATA_UPDATE) != 0) rdataclass = dns_rdataclass_any; else rdataclass = dns_rdataclass_none; } else { if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { fprintf(stderr, "could not read rdata\n"); exit(1); } } doneparsing: rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); if (rdatalist == NULL) { fprintf(stderr, "memory allocation for rdatalist failed\n"); exit(1); } dns_rdatalist_init(rdatalist); rdatalist->type = rdatatype; rdatalist->rdclass = rdataclass; rdatalist->covers = rdatatype; rdatalist->ttl = (dns_ttl_t)ttl; ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); ISC_LIST_APPEND(usedrdatalists, rdatalist, link); rdataset = isc_mem_get(mctx, sizeof(*rdataset)); if (rdataset == NULL) { fprintf(stderr, "memory allocation for rdataset failed\n"); exit(1); } dns_rdataset_init(rdataset); dns_rdatalist_tordataset(rdatalist, rdataset); ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); }
static void make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset, dns_name_t *name) { isc_result_t result; char *word; isc_textregion_t region; dns_rdataset_t *rdataset = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdataclass_t rdataclass; dns_rdatatype_t rdatatype; dns_rdata_t *rdata = NULL; /* * Read the owner name */ parse_name(&cmdline, name); /* * If this is an rrset prereq, read the class or type. */ if (isrrset) { word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read class or type\n"); exit(1); } region.base = word; region.length = strlen(word); result = dns_rdataclass_fromtext(&rdataclass, ®ion); if (result == ISC_R_SUCCESS) { /* * Now read the type. */ word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read type\n"); exit(1); } region.base = word; region.length = strlen(word); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "invalid type: %s\n", word); exit(1); } } else { rdataclass = default_rdataclass; result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "invalid type: %s\n", word); exit(1); } } } else rdatatype = dns_rdatatype_any; rdata = isc_mem_get(mctx, sizeof(*rdata)); if (rdata == NULL) { fprintf(stderr, "memory allocation for rdata failed\n"); exit(1); } dns_rdata_init(rdata); if (isrrset && ispositive) parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); else rdata->flags = DNS_RDATA_UPDATE; rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); if (rdatalist == NULL) { fprintf(stderr, "memory allocation for rdatalist failed\n"); exit(1); } dns_rdatalist_init(rdatalist); rdatalist->type = rdatatype; if (ispositive) { if (isrrset && rdata->data != NULL) rdatalist->rdclass = rdataclass; else rdatalist->rdclass = dns_rdataclass_any; } else rdatalist->rdclass = dns_rdataclass_none; rdatalist->covers = 0; rdatalist->ttl = 0; rdata->rdclass = rdatalist->rdclass; rdata->type = rdatatype; ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); ISC_LIST_APPEND(usedrdatalists, rdatalist, link); rdataset = isc_mem_get(mctx, sizeof(*rdataset)); if (rdataset == NULL) { fprintf(stderr, "memory allocation for rdataset failed\n"); exit(1); } dns_rdataset_init(rdataset); dns_rdatalist_tordataset(rdatalist, rdataset); ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); }
int main(int argc, char **argv) { char *porigin, *zonefile; dns_fixedname_t forigin, fname; dns_name_t *origin, *name; dns_db_t *db = NULL; dns_dbiterator_t *dbiter; dns_dbnode_t *node; dns_rdatasetiter_t *rdsiter; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; isc_mem_t *mctx = NULL; isc_entropy_t *ectx = NULL; isc_buffer_t b; isc_result_t result; PGresult *res; if (argc != 5) { printf("usage: %s origin file dbname dbtable\n", argv[0]); printf("Note that dbname must be an existing database.\n"); exit(1); } porigin = argv[1]; zonefile = argv[2]; dbname = argv[3]; dbtable = argv[4]; dns_result_register(); mctx = NULL; result = isc_mem_create(0, 0, &mctx); check_result(result, "isc_mem_create"); result = isc_entropy_create(mctx, &ectx); result_check (result, "isc_entropy_create"); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); check_result (result, "isc_hash_create"); isc_buffer_init(&b, porigin, strlen(porigin)); isc_buffer_add(&b, strlen(porigin)); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); result = dns_name_fromtext(origin, &b, dns_rootname, ISC_FALSE, NULL); check_result(result, "dns_name_fromtext"); db = NULL; result = dns_db_create(mctx, "rbt", origin, dns_dbtype_zone, dns_rdataclass_in, 0, NULL, &db); check_result(result, "dns_db_create"); result = dns_db_load(db, zonefile); if (result == DNS_R_SEENINCLUDE) result = ISC_R_SUCCESS; check_result(result, "dns_db_load"); printf("Connecting to '%s'\n", dbname); conn = PQsetdb(NULL, NULL, NULL, NULL, dbname); if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr, "Connection to database '%s' failed: %s\n", dbname, PQerrorMessage(conn)); closeandexit(1); } snprintf(str, sizeof(str), "DROP TABLE %s", dbtable); printf("%s\n", str); res = PQexec(conn, str); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) fprintf(stderr, "DROP TABLE command failed: %s\n", PQresultErrorMessage(res)); PQclear(res); snprintf(str, sizeof(str), "BEGIN"); printf("%s\n", str); res = PQexec(conn, str); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "BEGIN command failed: %s\n", PQresultErrorMessage(res)); PQclear(res); closeandexit(1); } PQclear(res); snprintf(str, sizeof(str), "CREATE TABLE %s " "(NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT)", dbtable); printf("%s\n", str); res = PQexec(conn, str); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "CREATE TABLE command failed: %s\n", PQresultErrorMessage(res)); PQclear(res); closeandexit(1); } PQclear(res); dbiter = NULL; result = dns_db_createiterator(db, ISC_FALSE, &dbiter); check_result(result, "dns_db_createiterator()"); result = dns_dbiterator_first(dbiter); check_result(result, "dns_dbiterator_first"); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_rdataset_init(&rdataset); dns_rdata_init(&rdata); while (result == ISC_R_SUCCESS) { node = NULL; result = dns_dbiterator_current(dbiter, &node, name); if (result == ISC_R_NOMORE) break; check_result(result, "dns_dbiterator_current"); rdsiter = NULL; result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter); check_result(result, "dns_db_allrdatasets"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, &rdataset); result = dns_rdataset_first(&rdataset); check_result(result, "dns_rdataset_first"); while (result == ISC_R_SUCCESS) { dns_rdataset_current(&rdataset, &rdata); addrdata(name, rdataset.ttl, &rdata); dns_rdata_reset(&rdata); result = dns_rdataset_next(&rdataset); } dns_rdataset_disassociate(&rdataset); result = dns_rdatasetiter_next(rdsiter); } dns_rdatasetiter_destroy(&rdsiter); dns_db_detachnode(db, &node); result = dns_dbiterator_next(dbiter); } snprintf(str, sizeof(str), "COMMIT TRANSACTION"); printf("%s\n", str); res = PQexec(conn, str); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "COMMIT command failed: %s\n", PQresultErrorMessage(res)); PQclear(res); closeandexit(1); } PQclear(res); dns_dbiterator_destroy(&dbiter); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); closeandexit(0); exit(0); }
int main(int argc, char *argv[]) { char *sql; int res; char *errmsg = NULL; char *porigin, *zonefile; dns_fixedname_t forigin, fname; dns_name_t *origin, *name; dns_db_t *db = NULL; dns_dbiterator_t *dbiter; dns_dbnode_t *node; dns_rdatasetiter_t *rdsiter; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; isc_mem_t *mctx = NULL; isc_entropy_t *ectx = NULL; isc_buffer_t b; isc_result_t result; if (argc != 5) { printf("usage: %s <zone> <zonefile> <dbfile> <dbtable>\n", argv[0]); exit(1); } porigin = argv[1]; zonefile = argv[2]; dbi.filename = argv[3]; dbi.table = argv[4]; dns_result_register(); result = isc_mem_create(0, 0, &mctx); check_result(result, "isc_mem_create"); result = isc_entropy_create(mctx, &ectx); check_result(result, "isc_entropy_create"); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); check_result(result, "isc_hash_create"); isc_buffer_init(&b, porigin, strlen(porigin)); isc_buffer_add(&b, strlen(porigin)); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); result = dns_name_fromtext(origin, &b, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); db = NULL; result = dns_db_create(mctx, "rbt", origin, dns_dbtype_zone, dns_rdataclass_in, 0, NULL, &db); check_result(result, "dns_db_create"); result = dns_db_load(db, zonefile); if (result == DNS_R_SEENINCLUDE) result = ISC_R_SUCCESS; check_result(result, "dns_db_load"); printf("Connecting to '%s'\n", dbi.filename); if ((result = db_connect(&dbi)) != ISC_R_SUCCESS) { fprintf(stderr, "Connection to database '%s' failed\n", dbi.filename); closeandexit(1); } sql = sqlite3_mprintf("DROP TABLE %q ", dbi.table); printf("%s\n", sql); res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg); sqlite3_free(sql); #if 0 if (res != SQLITE_OK) { fprintf(stderr, "DROP TABLE %s failed: %s\n", dbi.table, errmsg); } #endif #if 0 sql = sqlite3_mprintf(sql, "BEGIN TRANSACTION"); printf("%s\n", sql); res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg); sqlite3_free(sql); if (res != SQLITE_OK) { fprintf(stderr, "BEGIN TRANSACTION failed: %s\n", errmsg); closeandexit(1); } #endif sql = sqlite3_mprintf( "CREATE TABLE %q " "(NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT) ", dbi.table); printf("%s\n", sql); res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg); sqlite3_free(sql); if (res != SQLITE_OK) { fprintf(stderr, "CREATE TABLE %s failed: %s\n", dbi.table, errmsg); closeandexit(1); } dbiter = NULL; result = dns_db_createiterator(db, 0, &dbiter); check_result(result, "dns_db_createiterator()"); result = dns_dbiterator_first(dbiter); check_result(result, "dns_dbiterator_first"); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_rdataset_init(&rdataset); dns_rdata_init(&rdata); while (result == ISC_R_SUCCESS) { node = NULL; result = dns_dbiterator_current(dbiter, &node, name); if (result == ISC_R_NOMORE) break; check_result(result, "dns_dbiterator_current"); rdsiter = NULL; result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter); check_result(result, "dns_db_allrdatasets"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, &rdataset); result = dns_rdataset_first(&rdataset); check_result(result, "dns_rdataset_first"); while (result == ISC_R_SUCCESS) { dns_rdataset_current(&rdataset, &rdata); addrdata(name, rdataset.ttl, &rdata); dns_rdata_reset(&rdata); result = dns_rdataset_next(&rdataset); } dns_rdataset_disassociate(&rdataset); result = dns_rdatasetiter_next(rdsiter); } dns_rdatasetiter_destroy(&rdsiter); dns_db_detachnode(db, &node); result = dns_dbiterator_next(dbiter); } #if 0 sql = sqlite3_mprintf(sql, "COMMIT TRANSACTION "); printf("%s\n", sql); res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg); sqlite3_free(sql); if (res != SQLITE_OK) { fprintf(stderr, "COMMIT TRANSACTION failed: %s\n", errmsg); closeandexit(1); } #endif dns_dbiterator_destroy(&dbiter); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); closeandexit(0); exit(0); }
/*% * Configure an apex NS with glues for a static-stub zone. * For example, for the zone named "example.com", the following RRs will be * added to the zone DB: * example.com. NS example.com. * example.com. A 192.0.2.1 * example.com. AAAA 2001:db8::1 */ static isc_result_t configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone, dns_rdatalist_t *rdatalist_ns, dns_rdatalist_t *rdatalist_a, dns_rdatalist_t *rdatalist_aaaa) { const cfg_listelt_t *element; isc_mem_t *mctx = dns_zone_getmctx(zone); isc_region_t region, sregion; dns_rdata_t *rdata; isc_result_t result = ISC_R_SUCCESS; for (element = cfg_list_first(zconfig); element != NULL; element = cfg_list_next(element)) { const isc_sockaddr_t* sa; isc_netaddr_t na; const cfg_obj_t *address = cfg_listelt_value(element); dns_rdatalist_t *rdatalist; sa = cfg_obj_assockaddr(address); if (isc_sockaddr_getport(sa) != 0) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "port is not configurable for " "static stub server-addresses"); return (ISC_R_FAILURE); } isc_netaddr_fromsockaddr(&na, sa); if (isc_netaddr_getzone(&na) != 0) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "scoped address is not allowed " "for static stub " "server-addresses"); return (ISC_R_FAILURE); } switch (na.family) { case AF_INET: region.length = sizeof(na.type.in); rdatalist = rdatalist_a; break; default: INSIST(na.family == AF_INET6); region.length = sizeof(na.type.in6); rdatalist = rdatalist_aaaa; break; } rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length); if (rdata == NULL) return (ISC_R_NOMEMORY); region.base = (unsigned char *)(rdata + 1); memcpy(region.base, &na.type, region.length); dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_zone_getclass(zone), rdatalist->type, ®ion); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); } /* * If no address is specified (unlikely in this context, but possible), * there's nothing to do anymore. */ if (ISC_LIST_EMPTY(rdatalist_a->rdata) && ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) { return (ISC_R_SUCCESS); } /* Add to the list an apex NS with the ns name being the origin name */ dns_name_toregion(dns_zone_getorigin(zone), &sregion); rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); if (rdata == NULL) { /* * Already allocated data will be freed in the caller, so * we can simply return here. */ return (ISC_R_NOMEMORY); } region.length = sregion.length; region.base = (unsigned char *)(rdata + 1); memcpy(region.base, sregion.base, region.length); dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns, ®ion); ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link); return (result); }
/* * Arrange to send as much as we can of "stream" without blocking. * * Requires: * The stream iterator is initialized and points at an RR, * or possibly at the end of the stream (that is, the * _first method of the iterator has been called). */ static void sendstream(xfrout_ctx_t *xfr) { dns_message_t *tcpmsg = NULL; dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */ isc_result_t result; isc_region_t used; isc_region_t region; dns_rdataset_t *qrdataset; dns_name_t *msgname = NULL; dns_rdata_t *msgrdata = NULL; dns_rdatalist_t *msgrdl = NULL; dns_rdataset_t *msgrds = NULL; dns_compress_t cctx; isc_boolean_t cleanup_cctx = ISC_FALSE; isc_boolean_t is_tcp; int n_rrs; isc_buffer_clear(&xfr->buf); isc_buffer_clear(&xfr->txlenbuf); isc_buffer_clear(&xfr->txbuf); is_tcp = ISC_TF((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0); if (!is_tcp) { /* * In the UDP case, we put the response data directly into * the client message. */ msg = xfr->client->message; CHECK(dns_message_reply(msg, ISC_TRUE)); } else { /* * TCP. Build a response dns_message_t, temporarily storing * the raw, uncompressed owner names and RR data contiguously * in xfr->buf. We know that if the uncompressed data fits * in xfr->buf, the compressed data will surely fit in a TCP * message. */ CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &tcpmsg)); msg = tcpmsg; msg->id = xfr->id; msg->rcode = dns_rcode_noerror; msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA; if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0) msg->flags |= DNS_MESSAGEFLAG_RA; CHECK(dns_message_settsigkey(msg, xfr->tsigkey)); CHECK(dns_message_setquerytsig(msg, xfr->lasttsig)); if (xfr->lasttsig != NULL) isc_buffer_free(&xfr->lasttsig); /* * Add a EDNS option to the message? */ if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) { dns_rdataset_t *opt = NULL; CHECK(ns_client_addopt(xfr->client, msg, &opt)); CHECK(dns_message_setopt(msg, opt)); /* * Add to first message only. */ xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID; xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE; } /* * Account for reserved space. */ if (xfr->tsigkey != NULL) INSIST(msg->reserved != 0U); isc_buffer_add(&xfr->buf, msg->reserved); /* * Include a question section in the first message only. * BIND 8.2.1 will not recognize an IXFR if it does not * have a question section. */ if (xfr->nmsg == 0) { dns_name_t *qname = NULL; isc_region_t r; /* * Reserve space for the 12-byte message header * and 4 bytes of question. */ isc_buffer_add(&xfr->buf, 12 + 4); qrdataset = NULL; result = dns_message_gettemprdataset(msg, &qrdataset); if (result != ISC_R_SUCCESS) goto failure; dns_rdataset_makequestion(qrdataset, xfr->client->message->rdclass, xfr->qtype); result = dns_message_gettempname(msg, &qname); if (result != ISC_R_SUCCESS) goto failure; dns_name_init(qname, NULL); isc_buffer_availableregion(&xfr->buf, &r); INSIST(r.length >= xfr->qname->length); r.length = xfr->qname->length; isc_buffer_putmem(&xfr->buf, xfr->qname->ndata, xfr->qname->length); dns_name_fromregion(qname, &r); ISC_LIST_INIT(qname->list); ISC_LIST_APPEND(qname->list, qrdataset, link); dns_message_addname(msg, qname, DNS_SECTION_QUESTION); } else { /* * Reserve space for the 12-byte message header */ isc_buffer_add(&xfr->buf, 12); msg->tcp_continuation = 1; } } /* * Try to fit in as many RRs as possible, unless "one-answer" * format has been requested. */ for (n_rrs = 0; ; n_rrs++) { dns_name_t *name = NULL; isc_uint32_t ttl; dns_rdata_t *rdata = NULL; unsigned int size; isc_region_t r; msgname = NULL; msgrdata = NULL; msgrdl = NULL; msgrds = NULL; xfr->stream->methods->current(xfr->stream, &name, &ttl, &rdata); size = name->length + 10 + rdata->length; isc_buffer_availableregion(&xfr->buf, &r); if (size >= r.length) { /* * RR would not fit. If there are other RRs in the * buffer, send them now and leave this RR to the * next message. If this RR overflows the buffer * all by itself, fail. * * In theory some RRs might fit in a TCP message * when compressed even if they do not fit when * uncompressed, but surely we don't want * to send such monstrosities to an unsuspecting * slave. */ if (n_rrs == 0) { xfrout_log(xfr, ISC_LOG_WARNING, "RR too large for zone transfer " "(%d bytes)", size); /* XXX DNS_R_RRTOOLARGE? */ result = ISC_R_NOSPACE; goto failure; } break; } if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL)) log_rr(name, rdata, ttl); /* XXX */ result = dns_message_gettempname(msg, &msgname); if (result != ISC_R_SUCCESS) goto failure; dns_name_init(msgname, NULL); isc_buffer_availableregion(&xfr->buf, &r); INSIST(r.length >= name->length); r.length = name->length; isc_buffer_putmem(&xfr->buf, name->ndata, name->length); dns_name_fromregion(msgname, &r); /* Reserve space for RR header. */ isc_buffer_add(&xfr->buf, 10); result = dns_message_gettemprdata(msg, &msgrdata); if (result != ISC_R_SUCCESS) goto failure; isc_buffer_availableregion(&xfr->buf, &r); r.length = rdata->length; isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length); dns_rdata_init(msgrdata); dns_rdata_fromregion(msgrdata, rdata->rdclass, rdata->type, &r); result = dns_message_gettemprdatalist(msg, &msgrdl); if (result != ISC_R_SUCCESS) goto failure; msgrdl->type = rdata->type; msgrdl->rdclass = rdata->rdclass; msgrdl->ttl = ttl; if (rdata->type == dns_rdatatype_sig || rdata->type == dns_rdatatype_rrsig) msgrdl->covers = dns_rdata_covers(rdata); else msgrdl->covers = dns_rdatatype_none; ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link); result = dns_message_gettemprdataset(msg, &msgrds); if (result != ISC_R_SUCCESS) goto failure; result = dns_rdatalist_tordataset(msgrdl, msgrds); INSIST(result == ISC_R_SUCCESS); ISC_LIST_APPEND(msgname->list, msgrds, link); dns_message_addname(msg, msgname, DNS_SECTION_ANSWER); msgname = NULL; result = xfr->stream->methods->next(xfr->stream); if (result == ISC_R_NOMORE) { xfr->end_of_stream = ISC_TRUE; break; } CHECK(result); if (! xfr->many_answers) break; /* * At this stage, at least 1 RR has been rendered into * the message. Check if we want to clamp this message * here (TCP only). 20480 was set as an upper limit to * improve message compression. */ if ((isc_buffer_usedlength(&xfr->buf) >= 20480) && is_tcp) break; } if (is_tcp) { CHECK(dns_compress_init(&cctx, -1, xfr->mctx)); dns_compress_setsensitive(&cctx, ISC_TRUE); cleanup_cctx = ISC_TRUE; CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf)); CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0)); CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); CHECK(dns_message_renderend(msg)); dns_compress_invalidate(&cctx); cleanup_cctx = ISC_FALSE; isc_buffer_usedregion(&xfr->txbuf, &used); isc_buffer_putuint16(&xfr->txlenbuf, (isc_uint16_t)used.length); region.base = xfr->txlenbuf.base; region.length = 2 + used.length; xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending TCP message of %d bytes", used.length); CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */ ®ion, xfr->client->task, xfrout_senddone, xfr)); xfr->sends++; } else { xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response"); ns_client_send(xfr->client); xfr->stream->methods->pause(xfr->stream); xfrout_ctx_destroy(&xfr); return; } /* Advance lasttsig to be the last TSIG generated */ CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); xfr->nmsg++; failure: if (msgname != NULL) { if (msgrds != NULL) { if (dns_rdataset_isassociated(msgrds)) dns_rdataset_disassociate(msgrds); dns_message_puttemprdataset(msg, &msgrds); } if (msgrdl != NULL) { ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link); dns_message_puttemprdatalist(msg, &msgrdl); } if (msgrdata != NULL) dns_message_puttemprdata(msg, &msgrdata); dns_message_puttempname(msg, &msgname); } if (tcpmsg != NULL) dns_message_destroy(&tcpmsg); if (cleanup_cctx) dns_compress_invalidate(&cctx); /* * Make sure to release any locks held by database * iterators before returning from the event handler. */ xfr->stream->methods->pause(xfr->stream); if (result == ISC_R_SUCCESS) return; xfrout_fail(xfr, result, "sending zone data"); }
static isc_result_t addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl, isc_boolean_t optout, isc_boolean_t secure, dns_rdataset_t *addedrdataset) { isc_result_t result; isc_buffer_t buffer; isc_region_t r; dns_rdataset_t *rdataset; dns_rdatatype_t type; dns_name_t *name; dns_ttl_t ttl; dns_trust_t trust; dns_rdata_t rdata[DNS_NCACHE_RDATA]; dns_rdataset_t ncrdataset; dns_rdatalist_t ncrdatalist; unsigned char data[4096]; unsigned int next = 0; /* * Convert the authority data from 'message' into a negative cache * rdataset, and store it in 'cache' at 'node'. */ REQUIRE(message != NULL); /* * We assume that all data in the authority section has been * validated by the caller. */ /* * Initialize the list. */ dns_rdatalist_init(&ncrdatalist); ncrdatalist.rdclass = dns_db_class(cache); ncrdatalist.covers = covers; ncrdatalist.ttl = maxttl; /* * Build an ncache rdatas into buffer. */ ttl = maxttl; trust = 0xffff; isc_buffer_init(&buffer, data, sizeof(data)); if (message->counts[DNS_SECTION_AUTHORITY]) result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); else result = ISC_R_NOMORE; while (result == ISC_R_SUCCESS) { name = NULL; dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) { for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { if ((rdataset->attributes & DNS_RDATASETATTR_NCACHE) == 0) continue; type = rdataset->type; if (type == dns_rdatatype_rrsig) type = rdataset->covers; if (type == dns_rdatatype_soa || type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3) { if (ttl > rdataset->ttl) ttl = rdataset->ttl; if (trust > rdataset->trust) trust = rdataset->trust; /* * Copy the owner name to the buffer. */ dns_name_toregion(name, &r); result = isc_buffer_copyregion(&buffer, &r); if (result != ISC_R_SUCCESS) return (result); /* * Copy the type to the buffer. */ isc_buffer_availableregion(&buffer, &r); if (r.length < 3) return (ISC_R_NOSPACE); isc_buffer_putuint16(&buffer, rdataset->type); isc_buffer_putuint8(&buffer, (unsigned char)rdataset->trust); /* * Copy the rdataset into the buffer. */ result = copy_rdataset(rdataset, &buffer); if (result != ISC_R_SUCCESS) return (result); if (next >= DNS_NCACHE_RDATA) return (ISC_R_NOSPACE); dns_rdata_init(&rdata[next]); isc_buffer_remainingregion(&buffer, &r); rdata[next].data = r.base; rdata[next].length = r.length; rdata[next].rdclass = ncrdatalist.rdclass; rdata[next].type = 0; rdata[next].flags = 0; ISC_LIST_APPEND(ncrdatalist.rdata, &rdata[next], link); isc_buffer_forward(&buffer, r.length); next++; } } } result = dns_message_nextname(message, DNS_SECTION_AUTHORITY); } if (result != ISC_R_NOMORE) return (result); if (trust == 0xffff) { if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 && message->counts[DNS_SECTION_ANSWER] == 0) { /* * The response has aa set and we haven't followed * any CNAME or DNAME chains. */ trust = dns_trust_authauthority; } else trust = dns_trust_additional; ttl = 0; } INSIST(trust != 0xffff); ncrdatalist.ttl = ttl; dns_rdataset_init(&ncrdataset); RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset) == ISC_R_SUCCESS); if (!secure && trust > dns_trust_answer) trust = dns_trust_answer; ncrdataset.trust = trust; ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE; if (message->rcode == dns_rcode_nxdomain) ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN; if (optout) ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT; return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset, 0, addedrdataset)); }
int main(int argc, char *argv[]) { isc_token_t token; isc_result_t result; int quiet = 0; int c; int stats = 0; unsigned int options = 0; dns_rdatatype_t type; dns_rdataclass_t class; dns_rdatatype_t lasttype = 0; char outbuf[16*1024]; char inbuf[16*1024]; char wirebuf[16*1024]; char viabuf[16*1024]; isc_buffer_t dbuf; isc_buffer_t tbuf; isc_buffer_t wbuf; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_t last = DNS_RDATA_INIT; int need_eol = 0; int wire = 0; dns_compress_t cctx; dns_decompress_t dctx; int trunc = 0; int add = 0; int len; int zero = 0; int debug = 0; isc_region_t region; int first = 1; int raw = 0; int tostruct = 0; while ((c = isc_commandline_parse(argc, argv, "dqswtarzS")) != -1) { switch (c) { case 'd': debug = 1; quiet = 0; break; case 'q': quiet = 1; debug = 0; break; case 's': stats = 1; break; case 'w': wire = 1; break; case 't': trunc = 1; break; case 'a': add = 1; break; case 'z': zero = 1; break; case 'r': raw++; break; case 'S': tostruct++; break; } } memset(&dctx, 0, sizeof(dctx)); dctx.allowed = DNS_COMPRESS_ALL; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_lex_create(mctx, 256, &lex) == ISC_R_SUCCESS); /* * Set up to lex DNS master file. */ specials['('] = 1; specials[')'] = 1; specials['"'] = 1; isc_lex_setspecials(lex, specials); options = ISC_LEXOPT_EOL; isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); RUNTIME_CHECK(isc_lex_openstream(lex, stdin) == ISC_R_SUCCESS); dns_rdata_init(&last); while ((result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER, &token)) == ISC_R_SUCCESS) { if (debug) fprintf(stdout, "token.type = %d\n", token.type); if (need_eol) { if (token.type == isc_tokentype_eol) need_eol = 0; continue; } if (token.type == isc_tokentype_eof) break; /* * Get type. */ if (token.type == isc_tokentype_number) { type = token.value.as_ulong; isc_buffer_init(&tbuf, outbuf, sizeof(outbuf)); result = dns_rdatatype_totext(type, &tbuf); if (result != ISC_R_SUCCESS) { fprintf(stdout, "dns_rdatatype_totext " "returned %s(%d)\n", dns_result_totext(result), result); fflush(stdout); need_eol = 1; continue; } fprintf(stdout, "type = %.*s(%d)\n", (int)tbuf.used, (char*)tbuf.base, type); } else if (token.type == isc_tokentype_string) { result = dns_rdatatype_fromtext(&type, &token.value.as_textregion); if (result != ISC_R_SUCCESS) { fprintf(stdout, "dns_rdatatype_fromtext " "returned %s(%d)\n", dns_result_totext(result), result); fflush(stdout); need_eol = 1; continue; } fprintf(stdout, "type = %.*s(%d)\n", (int)token.value.as_textregion.length, token.value.as_textregion.base, type); } else continue; result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER, &token); if (result != ISC_R_SUCCESS) break; if (token.type == isc_tokentype_eol) continue; if (token.type == isc_tokentype_eof) break; if (token.type == isc_tokentype_number) { class = token.value.as_ulong; isc_buffer_init(&tbuf, outbuf, sizeof(outbuf)); result = dns_rdatatype_totext(class, &tbuf); if (result != ISC_R_SUCCESS) { fprintf(stdout, "dns_rdatatype_totext " "returned %s(%d)\n", dns_result_totext(result), result); fflush(stdout); need_eol = 1; continue; } fprintf(stdout, "class = %.*s(%d)\n", (int)tbuf.used, (char*)tbuf.base, class); } else if (token.type == isc_tokentype_string) { result = dns_rdataclass_fromtext(&class, &token.value.as_textregion); if (result != ISC_R_SUCCESS) { fprintf(stdout, "dns_rdataclass_fromtext " "returned %s(%d)\n", dns_result_totext(result), result); fflush(stdout); need_eol = 1; continue; } fprintf(stdout, "class = %.*s(%d)\n", (int)token.value.as_textregion.length, token.value.as_textregion.base, class); } else
isc_result_t dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_stdtime_t *inception, isc_stdtime_t *expire, isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) { dns_rdata_rrsig_t sig; dns_rdata_t tmpsigrdata; dns_rdata_t *rdatas; int nrdatas, i; isc_buffer_t sigbuf, envbuf; isc_region_t r; dst_context_t *ctx = NULL; isc_result_t ret; isc_buffer_t *databuf = NULL; char data[256 + 8]; isc_uint32_t flags; unsigned int sigsize; dns_fixedname_t fnewname; REQUIRE(name != NULL); REQUIRE(dns_name_countlabels(name) <= 255); REQUIRE(set != NULL); REQUIRE(key != NULL); REQUIRE(inception != NULL); REQUIRE(expire != NULL); REQUIRE(mctx != NULL); REQUIRE(sigrdata != NULL); if (*inception >= *expire) return (DNS_R_INVALIDTIME); /* * Is the key allowed to sign data? */ flags = dst_key_flags(key); if (flags & DNS_KEYTYPE_NOAUTH) return (DNS_R_KEYUNAUTHORIZED); if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) return (DNS_R_KEYUNAUTHORIZED); sig.mctx = mctx; sig.common.rdclass = set->rdclass; sig.common.rdtype = dns_rdatatype_rrsig; ISC_LINK_INIT(&sig.common, link); dns_name_init(&sig.signer, NULL); dns_name_clone(dst_key_name(key), &sig.signer); sig.covered = set->type; sig.algorithm = dst_key_alg(key); sig.labels = dns_name_countlabels(name) - 1; if (dns_name_iswildcard(name)) sig.labels--; sig.originalttl = set->ttl; sig.timesigned = *inception; sig.timeexpire = *expire; sig.keyid = dst_key_id(key); ret = dst_key_sigsize(key, &sigsize); if (ret != ISC_R_SUCCESS) return (ret); sig.siglen = sigsize; /* * The actual contents of sig.signature are not important yet, since * they're not used in digest_sig(). */ sig.signature = isc_mem_get(mctx, sig.siglen); if (sig.signature == NULL) return (ISC_R_NOMEMORY); ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18); if (ret != ISC_R_SUCCESS) goto cleanup_signature; dns_rdata_init(&tmpsigrdata); ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass, sig.common.rdtype, &sig, databuf); if (ret != ISC_R_SUCCESS) goto cleanup_databuf; ret = dst_context_create(key, mctx, &ctx); if (ret != ISC_R_SUCCESS) goto cleanup_databuf; /* * Digest the SIG rdata. */ ret = digest_sig(ctx, &tmpsigrdata, &sig); if (ret != ISC_R_SUCCESS) goto cleanup_context; dns_fixedname_init(&fnewname); RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), NULL) == ISC_R_SUCCESS); dns_name_toregion(dns_fixedname_name(&fnewname), &r); /* * Create an envelope for each rdata: <name|type|class|ttl>. */ isc_buffer_init(&envbuf, data, sizeof(data)); memcpy(data, r.base, r.length); isc_buffer_add(&envbuf, r.length); isc_buffer_putuint16(&envbuf, set->type); isc_buffer_putuint16(&envbuf, set->rdclass); isc_buffer_putuint32(&envbuf, set->ttl); ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); if (ret != ISC_R_SUCCESS) goto cleanup_context; isc_buffer_usedregion(&envbuf, &r); for (i = 0; i < nrdatas; i++) { isc_uint16_t len; isc_buffer_t lenbuf; isc_region_t lenr; /* * Skip duplicates. */ if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) continue; /* * Digest the envelope. */ ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_array; /* * Digest the length of the rdata. */ isc_buffer_init(&lenbuf, &len, sizeof(len)); INSIST(rdatas[i].length < 65536); isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); isc_buffer_usedregion(&lenbuf, &lenr); ret = dst_context_adddata(ctx, &lenr); if (ret != ISC_R_SUCCESS) goto cleanup_array; /* * Digest the rdata. */ ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); if (ret != ISC_R_SUCCESS) goto cleanup_array; } isc_buffer_init(&sigbuf, sig.signature, sig.siglen); ret = dst_context_sign(ctx, &sigbuf); if (ret != ISC_R_SUCCESS) goto cleanup_array; isc_buffer_usedregion(&sigbuf, &r); if (r.length != sig.siglen) { ret = ISC_R_NOSPACE; goto cleanup_array; } memcpy(sig.signature, r.base, sig.siglen); ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass, sig.common.rdtype, &sig, buffer); cleanup_array: isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); cleanup_context: dst_context_destroy(&ctx); cleanup_databuf: isc_buffer_free(&databuf); cleanup_signature: isc_mem_put(mctx, sig.signature, sig.siglen); return (ret); }
static isc_result_t towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, dns_compress_t *cctx, isc_buffer_t *target, dns_rdatasetorderfunc_t order, const void *order_arg, isc_boolean_t partial, unsigned int options, unsigned int *countp, void **state) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_region_t r; isc_result_t result; unsigned int i, count = 0, added, choice; isc_buffer_t savedbuffer, rdlen, rrbuffer; unsigned int headlen; isc_boolean_t question = ISC_FALSE; isc_boolean_t shuffle = ISC_FALSE; dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE]; struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE]; /* count processed auswer ips */ int answer_count = 0; int is_no_auth_answer = 0; /* tmp count for record */ int tmp_count = 0; UNUSED(state); /* * Convert 'rdataset' to wire format, compressing names as specified * in cctx, and storing the result in 'target'. */ REQUIRE(DNS_RDATASET_VALID(rdataset)); REQUIRE(countp != NULL); REQUIRE((order == NULL) == (order_arg == NULL)); REQUIRE(cctx != NULL && cctx->mctx != NULL); if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) { question = ISC_TRUE; count = 1; result = dns_rdataset_first(rdataset); INSIST(result == ISC_R_NOMORE); } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { /* * This is a negative caching rdataset. */ unsigned int ncache_opts = 0; if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0) ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC; return (dns_ncache_towire(rdataset, cctx, target, ncache_opts, countp)); } else { count = (rdataset->methods->count)(rdataset); result = dns_rdataset_first(rdataset); if (result == ISC_R_NOMORE) return (ISC_R_SUCCESS); if (result != ISC_R_SUCCESS) return (result); } /* * Do we want to shuffle this answer? */ if (!question && count > 1 && (!WANT_FIXED(rdataset) || order != NULL) && rdataset->type != dns_rdatatype_rrsig) shuffle = ISC_TRUE; if (shuffle && count > MAX_SHUFFLE) { shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled)); sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted)); if (shuffled == NULL || sorted == NULL) shuffle = ISC_FALSE; } else { shuffled = shuffled_fixed; sorted = sorted_fixed; } if (shuffle) { /* * First we get handles to all of the rdata. */ i = 0; do { INSIST(i < count); dns_rdata_init(&shuffled[i]); dns_rdataset_current(rdataset, &shuffled[i]); i++; result = dns_rdataset_next(rdataset); } while (result == ISC_R_SUCCESS); if (result != ISC_R_NOMORE) goto cleanup; INSIST(i == count); /* * Now we shuffle. */ if (WANT_FIXED(rdataset)) { /* * 'Fixed' order. */ INSIST(order != NULL); for (i = 0; i < count; i++) { sorted[i].key = (*order)(&shuffled[i], order_arg); sorted[i].rdata = &shuffled[i]; } } else if (WANT_RANDOM(rdataset)) { /* * 'Random' order. */ for (i = 0; i < count; i++) { dns_rdata_t rdata; isc_uint32_t val; isc_random_get(&val); choice = i + (val % (count - i)); rdata = shuffled[i]; shuffled[i] = shuffled[choice]; shuffled[choice] = rdata; if (order != NULL) sorted[i].key = (*order)(&shuffled[i], order_arg); else sorted[i].key = 0; /* Unused */ sorted[i].rdata = &shuffled[i]; } } else { /* * "Cyclic" order. */ isc_uint32_t val; unsigned int j; val = rdataset->count; if (val == ISC_UINT32_MAX) isc_random_get(&val); j = val % count; for (i = 0; i < count; i++) { if (order != NULL) sorted[i].key = (*order)(&shuffled[j], order_arg); else sorted[i].key = 0; /* Unused */ sorted[i].rdata = &shuffled[j]; j++; if (j == count) j = 0; /* Wrap around. */ } } /* * Sorted order. */ if (order != NULL) qsort(sorted, count, sizeof(sorted[0]), towire_compare); } savedbuffer = *target; i = 0; added = 0; // save the count here tmp_count = count; do { /* * Copy out the name, type, class, ttl. */ /* mark if is answer data. */ is_no_auth_answer = 0; /* Answer from a non-authoritative server,we set the ttl fixed as 500. */ if(rdataset->attributes == DNS_RDATASETATTR_LOADORDER && rdataset->type == dns_rdatatype_a){ /* Answer from a non-authoritative server,we set the ttl fixed as 500. */ if(rdataset->trust == dns_trust_answer ){ is_no_auth_answer = 1; } /* for all multi-ip answer,if set DNS_ANSWER_ONLY_ONE_IP flag, return only 1 ip. */ if(answer_count == 0){ answer_count ++; }else{ if( DNS_ANSWER_ONLY_ONE_IP ){ //fprintf(stderr,"DNS_ANSWER_ONLY_ONE_IP set,skip. \n"); if (shuffle) { tmp_count--; if (i == tmp_count) result = ISC_R_NOMORE; else result = ISC_R_SUCCESS; } else { result = dns_rdataset_next(rdataset); } continue; } } } rrbuffer = *target; dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); result = dns_name_towire(owner_name, cctx, target); if (result != ISC_R_SUCCESS) goto rollback; headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t); if (!question) headlen += sizeof(dns_ttl_t) + 2; /* XXX 2 for rdata len */ isc_buffer_availableregion(target, &r); if (r.length < headlen) { result = ISC_R_NOSPACE; goto rollback; } isc_buffer_putuint16(target, rdataset->type); isc_buffer_putuint16(target, rdataset->rdclass); if (!question) { if( is_no_auth_answer ){ isc_buffer_putuint32(target, DNS_DEFAULT_TTL_FOR_NO_AUTH_NAME); }else{ isc_buffer_putuint32(target, rdataset->ttl); } //fprintf(stderr,"xxxxxxxxx:trust : %d artr: %d ttl:%d cover: %d type: %d count: %d class: %d\n", rdataset->trust,rdataset->attributes,rdataset->ttl, rdataset->covers,rdataset->type, rdataset->count, rdataset->rdclass); /* * Save space for rdlen. */ rdlen = *target; isc_buffer_add(target, 2); /* * Copy out the rdata */ if (shuffle) rdata = *(sorted[i].rdata); else { dns_rdata_reset(&rdata); dns_rdataset_current(rdataset, &rdata); } result = dns_rdata_towire(&rdata, cctx, target); if (result != ISC_R_SUCCESS) goto rollback; INSIST((target->used >= rdlen.used + 2) && (target->used - rdlen.used - 2 < 65536)); isc_buffer_putuint16(&rdlen, (isc_uint16_t)(target->used - rdlen.used - 2)); added++; } if (shuffle) { i++; if (i == tmp_count) result = ISC_R_NOMORE; else result = ISC_R_SUCCESS; } else { result = dns_rdataset_next(rdataset); } } while (result == ISC_R_SUCCESS); if (result != ISC_R_NOMORE) goto rollback; *countp += tmp_count; result = ISC_R_SUCCESS; goto cleanup; rollback: if (partial && result == ISC_R_NOSPACE) { INSIST(rrbuffer.used < 65536); dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used); *countp += added; *target = rrbuffer; goto cleanup; } INSIST(savedbuffer.used < 65536); dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used); *countp = 0; *target = savedbuffer; cleanup: if (sorted != NULL && sorted != sorted_fixed) isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted)); if (shuffled != NULL && shuffled != shuffled_fixed) isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled)); return (result); }
isc_result_t dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region, unsigned int reservelen) { /* * Use &removed as a sentinal pointer for duplicate * rdata as rdata.data == NULL is valid. */ static unsigned char removed; struct xrdata *x; unsigned char *rawbuf; #if DNS_RDATASET_FIXED unsigned char *offsetbase; #endif unsigned int buflen; isc_result_t result; unsigned int nitems; unsigned int nalloc; unsigned int i; #if DNS_RDATASET_FIXED unsigned int *offsettable; #endif unsigned int length; buflen = reservelen + 2; nalloc = dns_rdataset_count(rdataset); nitems = nalloc; if (nitems == 0 && rdataset->type != 0) return (ISC_R_FAILURE); if (nalloc > 0xffff) return (ISC_R_NOSPACE); if (nalloc != 0) { x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata)); if (x == NULL) return (ISC_R_NOMEMORY); } else x = NULL; /* * Save all of the rdata members into an array. */ result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) goto free_rdatas; for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) { INSIST(result == ISC_R_SUCCESS); dns_rdata_init(&x[i].rdata); dns_rdataset_current(rdataset, &x[i].rdata); INSIST(x[i].rdata.data != &removed); #if DNS_RDATASET_FIXED x[i].order = i; #endif result = dns_rdataset_next(rdataset); } if (result != ISC_R_NOMORE) goto free_rdatas; if (i != nalloc) { /* * Somehow we iterated over fewer rdatas than * dns_rdataset_count() said there were! */ result = ISC_R_FAILURE; goto free_rdatas; } /* * Put into DNSSEC order. */ qsort(x, nalloc, sizeof(struct xrdata), compare_rdata); /* * Remove duplicates and compute the total storage required. * * If an rdata is not a duplicate, accumulate the storage size * required for the rdata. We do not store the class, type, etc, * just the rdata, so our overhead is 2 bytes for the number of * records, and 8 for each rdata, (length(2), offset(4) and order(2)) * and then the rdata itself. */ for (i = 1; i < nalloc; i++) { if (compare_rdata(&x[i-1].rdata, &x[i].rdata) == 0) { x[i-1].rdata.data = &removed; #if DNS_RDATASET_FIXED /* * Preserve the least order so A, B, A -> A, B * after duplicate removal. */ if (x[i-1].order < x[i].order) x[i].order = x[i-1].order; #endif nitems--; } else { #if DNS_RDATASET_FIXED buflen += (8 + x[i-1].rdata.length); #else buflen += (2 + x[i-1].rdata.length); #endif /* * Provide space to store the per RR meta data. */ if (rdataset->type == dns_rdatatype_rrsig) buflen++; } } /* * Don't forget the last item! */ if (nalloc != 0) { #if DNS_RDATASET_FIXED buflen += (8 + x[i-1].rdata.length); #else buflen += (2 + x[i-1].rdata.length); #endif } /* * Provide space to store the per RR meta data. */ if (rdataset->type == dns_rdatatype_rrsig) buflen++; /* * Ensure that singleton types are actually singletons. */ if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) { /* * We have a singleton type, but there's more than one * RR in the rdataset. */ result = DNS_R_SINGLETON; goto free_rdatas; } /* * Allocate the memory, set up a buffer, start copying in * data. */ rawbuf = isc_mem_get(mctx, buflen); if (rawbuf == NULL) { result = ISC_R_NOMEMORY; goto free_rdatas; } #if DNS_RDATASET_FIXED /* Allocate temporary offset table. */ offsettable = isc_mem_get(mctx, nalloc * sizeof(unsigned int)); if (offsettable == NULL) { isc_mem_put(mctx, rawbuf, buflen); result = ISC_R_NOMEMORY; goto free_rdatas; } memset(offsettable, 0, nalloc * sizeof(unsigned int)); #endif region->base = rawbuf; region->length = buflen; rawbuf += reservelen; #if DNS_RDATASET_FIXED offsetbase = rawbuf; #endif *rawbuf++ = (nitems & 0xff00) >> 8; *rawbuf++ = (nitems & 0x00ff); #if DNS_RDATASET_FIXED /* Skip load order table. Filled in later. */ rawbuf += nitems * 4; #endif for (i = 0; i < nalloc; i++) { if (x[i].rdata.data == &removed) continue; #if DNS_RDATASET_FIXED offsettable[x[i].order] = rawbuf - offsetbase; #endif length = x[i].rdata.length; if (rdataset->type == dns_rdatatype_rrsig) length++; INSIST(length <= 0xffff); *rawbuf++ = (length & 0xff00) >> 8; *rawbuf++ = (length & 0x00ff); #if DNS_RDATASET_FIXED rawbuf += 2; /* filled in later */ #endif /* * Store the per RR meta data. */ if (rdataset->type == dns_rdatatype_rrsig) { *rawbuf++ |= (x[i].rdata.flags & DNS_RDATA_OFFLINE) ? DNS_RDATASLAB_OFFLINE : 0; } memcpy(rawbuf, x[i].rdata.data, x[i].rdata.length); rawbuf += x[i].rdata.length; } #if DNS_RDATASET_FIXED fillin_offsets(offsetbase, offsettable, nalloc); isc_mem_put(mctx, offsettable, nalloc * sizeof(unsigned int)); #endif result = ISC_R_SUCCESS; free_rdatas: if (x != NULL) isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata)); return (result); }
int main (int *argc, char **argv) { isc_mem_t *mctx = NULL; isc_entropy_t *ectx = NULL; isc_result_t result; char *basedn; ldap_info *tmp; LDAPMod *base_attrs[2]; LDAPMod base; isc_buffer_t buff; char *zonefile; char fullbasedn[1024]; char *ctmp; dns_fixedname_t fixedzone, fixedname; dns_rdataset_t rdataset; char **dc_list; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatasetiter_t *riter; dns_name_t *zone, *name; dns_db_t *db = NULL; dns_dbiterator_t *dbit = NULL; dns_dbnode_t *node; extern char *optarg; extern int optind, opterr, optopt; int create_base = 0; int topt; if ((int) argc < 2) { usage (); exit (-1); } while ((topt = getopt ((int) argc, argv, "D:w:b:z:f:h:?dcv")) != -1) { switch (topt) { case 'v': printf("%s\n", VERSION); exit(0); case 'c': create_base++; break; case 'd': debug++; break; case 'D': binddn = strdup (optarg); break; case 'w': bindpw = strdup (optarg); break; case 'b': ldapbase = strdup (optarg); break; case 'z': argzone = strdup (optarg); // We wipe argzone all to hell when we parse it for the DN */ gbl_zone = strdup(argzone); break; case 'f': zonefile = strdup (optarg); break; case 'h': ldapsystem = strdup (optarg); break; case '?': default: usage (); exit (0); } } if ((argzone == NULL) || (zonefile == NULL)) { usage (); exit (-1); } if (debug) printf ("Initializing ISC Routines, parsing zone file\n"); result = isc_mem_create (0, 0, &mctx); isc_result_check (result, "isc_mem_create"); result = isc_entropy_create(mctx, &ectx); isc_result_check (result, "isc_entropy_create"); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); isc_result_check (result, "isc_hash_create"); isc_buffer_init (&buff, argzone, strlen (argzone)); isc_buffer_add (&buff, strlen (argzone)); dns_fixedname_init (&fixedzone); zone = dns_fixedname_name (&fixedzone); result = dns_name_fromtext (zone, &buff, dns_rootname, 0, NULL); isc_result_check (result, "dns_name_fromtext"); result = dns_db_create (mctx, "rbt", zone, dns_dbtype_zone, dns_rdataclass_in, 0, NULL, &db); isc_result_check (result, "dns_db_create"); result = dns_db_load (db, zonefile); isc_result_check (result, "Check Zone Syntax: dns_db_load"); result = dns_db_createiterator (db, 0, &dbit); isc_result_check (result, "dns_db_createiterator"); result = dns_dbiterator_first (dbit); isc_result_check (result, "dns_dbiterator_first"); dns_fixedname_init (&fixedname); name = dns_fixedname_name (&fixedname); dns_rdataset_init (&rdataset); dns_rdata_init (&rdata); while (result == ISC_R_SUCCESS) { node = NULL; result = dns_dbiterator_current (dbit, &node, name); if (result == ISC_R_NOMORE) break; isc_result_check (result, "dns_dbiterator_current"); riter = NULL; result = dns_db_allrdatasets (db, node, NULL, 0, &riter); isc_result_check (result, "dns_db_allrdatasets"); result = dns_rdatasetiter_first (riter); //isc_result_check(result, "dns_rdatasetiter_first"); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current (riter, &rdataset); result = dns_rdataset_first (&rdataset); isc_result_check (result, "dns_rdatasetiter_current"); while (result == ISC_R_SUCCESS) { dns_rdataset_current (&rdataset, &rdata); generate_ldap (name, &rdata, rdataset.ttl); dns_rdata_reset (&rdata); result = dns_rdataset_next (&rdataset); } dns_rdataset_disassociate (&rdataset); result = dns_rdatasetiter_next (riter); } dns_rdatasetiter_destroy (&riter); result = dns_dbiterator_next (dbit); } /* Initialize the LDAP Connection */ if (debug) printf ("Initializing LDAP Connection to %s as %s\n", ldapsystem, binddn); init_ldap_conn (); if (create_base) { if (debug) printf ("Creating base zone DN %s\n", argzone); dc_list = hostname_to_dn_list (argzone, argzone, DNS_TOP); basedn = build_dn_from_dc_list (dc_list, 0, NO_SPEC); for (ctmp = &basedn[strlen (basedn)]; ctmp >= &basedn[0]; ctmp--) { if ((*ctmp == ',') || (ctmp == &basedn[0])) { base.mod_op = LDAP_MOD_ADD; base.mod_type = "objectClass"; base.mod_values = topObjectClasses; base_attrs[0] = &base; base_attrs[1] = NULL; if (ldapbase) { if (ctmp != &basedn[0]) sprintf (fullbasedn, "%s,%s", ctmp + 1, ldapbase); else sprintf (fullbasedn, "%s,%s", ctmp, ldapbase); } else { if (ctmp != &basedn[0]) sprintf (fullbasedn, "%s", ctmp + 1); else sprintf (fullbasedn, "%s", ctmp); } result = ldap_add_s (conn, fullbasedn, base_attrs); ldap_result_check ("intial ldap_add_s", fullbasedn, result); } } } else { if (debug) printf ("Skipping zone base dn creation for %s\n", argzone); } for (tmp = ldap_info_base; tmp != NULL; tmp = tmp->next) { if (debug) printf ("Adding DN: %s\n", tmp->dn); add_ldap_values (tmp); } if (debug) printf("Operation Complete.\n"); /* Cleanup */ isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); if (zonefile) free(zonefile); return 0; }
isc_result_t dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, unsigned int reservelen, isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_rdatatype_t type, unsigned int flags, unsigned char **tslabp) { unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data; unsigned int ocount, ncount, count, olength, tlength, tcount, length; dns_rdata_t ordata = DNS_RDATA_INIT; dns_rdata_t nrdata = DNS_RDATA_INIT; isc_boolean_t added_something = ISC_FALSE; unsigned int oadded = 0; unsigned int nadded = 0; unsigned int nncount = 0; #if DNS_RDATASET_FIXED unsigned int oncount; unsigned int norder = 0; unsigned int oorder = 0; unsigned char *offsetbase; unsigned int *offsettable; #endif /* * XXX Need parameter to allow "delete rdatasets in nslab" merge, * or perhaps another merge routine for this purpose. */ REQUIRE(tslabp != NULL && *tslabp == NULL); REQUIRE(oslab != NULL && nslab != NULL); ocurrent = oslab + reservelen; ocount = *ocurrent++ * 256; ocount += *ocurrent++; #if DNS_RDATASET_FIXED ocurrent += (4 * ocount); #endif ostart = ocurrent; ncurrent = nslab + reservelen; ncount = *ncurrent++ * 256; ncount += *ncurrent++; #if DNS_RDATASET_FIXED ncurrent += (4 * ncount); #endif INSIST(ocount > 0 && ncount > 0); #if DNS_RDATASET_FIXED oncount = ncount; #endif /* * Yes, this is inefficient! */ /* * Figure out the length of the old slab's data. */ olength = 0; for (count = 0; count < ocount; count++) { length = *ocurrent++ * 256; length += *ocurrent++; #if DNS_RDATASET_FIXED olength += length + 8; ocurrent += length + 2; #else olength += length + 2; ocurrent += length; #endif } /* * Start figuring out the target length and count. */ tlength = reservelen + 2 + olength; tcount = ocount; /* * Add in the length of rdata in the new slab that aren't in * the old slab. */ do { dns_rdata_init(&nrdata); rdata_from_slab(&ncurrent, rdclass, type, &nrdata); if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)) { /* * This rdata isn't in the old slab. */ #if DNS_RDATASET_FIXED tlength += nrdata.length + 8; #else tlength += nrdata.length + 2; #endif if (type == dns_rdatatype_rrsig) tlength++; tcount++; nncount++; added_something = ISC_TRUE; } ncount--; } while (ncount > 0); ncount = nncount; if (((flags & DNS_RDATASLAB_EXACT) != 0) && (tcount != ncount + ocount)) return (DNS_R_NOTEXACT); if (!added_something && (flags & DNS_RDATASLAB_FORCE) == 0) return (DNS_R_UNCHANGED); /* * Ensure that singleton types are actually singletons. */ if (tcount > 1 && dns_rdatatype_issingleton(type)) { /* * We have a singleton type, but there's more than one * RR in the rdataset. */ return (DNS_R_SINGLETON); } if (tcount > 0xffff) return (ISC_R_NOSPACE); /* * Copy the reserved area from the new slab. */ tstart = isc_mem_get(mctx, tlength); if (tstart == NULL) return (ISC_R_NOMEMORY); memcpy(tstart, nslab, reservelen); tcurrent = tstart + reservelen; #if DNS_RDATASET_FIXED offsetbase = tcurrent; #endif /* * Write the new count. */ *tcurrent++ = (tcount & 0xff00) >> 8; *tcurrent++ = (tcount & 0x00ff); #if DNS_RDATASET_FIXED /* * Skip offset table. */ tcurrent += (tcount * 4); offsettable = isc_mem_get(mctx, (ocount + oncount) * sizeof(unsigned int)); if (offsettable == NULL) { isc_mem_put(mctx, tstart, tlength); return (ISC_R_NOMEMORY); } memset(offsettable, 0, (ocount + oncount) * sizeof(unsigned int)); #endif /* * Merge the two slabs. */ ocurrent = ostart; INSIST(ocount != 0); #if DNS_RDATASET_FIXED oorder = ocurrent[2] * 256 + ocurrent[3]; INSIST(oorder < ocount); #endif rdata_from_slab(&ocurrent, rdclass, type, &ordata); ncurrent = nslab + reservelen + 2; #if DNS_RDATASET_FIXED ncurrent += (4 * oncount); #endif if (ncount > 0) { do { dns_rdata_reset(&nrdata); #if DNS_RDATASET_FIXED norder = ncurrent[2] * 256 + ncurrent[3]; INSIST(norder < oncount); #endif rdata_from_slab(&ncurrent, rdclass, type, &nrdata); } while (rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)); } while (oadded < ocount || nadded < ncount) { isc_boolean_t fromold; if (oadded == ocount) fromold = ISC_FALSE; else if (nadded == ncount) fromold = ISC_TRUE; else fromold = ISC_TF(compare_rdata(&ordata, &nrdata) < 0); if (fromold) { #if DNS_RDATASET_FIXED offsettable[oorder] = tcurrent - offsetbase; #endif length = ordata.length; data = ordata.data; if (type == dns_rdatatype_rrsig) { length++; data--; } *tcurrent++ = (length & 0xff00) >> 8; *tcurrent++ = (length & 0x00ff); #if DNS_RDATASET_FIXED tcurrent += 2; /* fill in later */ #endif memcpy(tcurrent, data, length); tcurrent += length; oadded++; if (oadded < ocount) { dns_rdata_reset(&ordata); #if DNS_RDATASET_FIXED oorder = ocurrent[2] * 256 + ocurrent[3]; INSIST(oorder < ocount); #endif rdata_from_slab(&ocurrent, rdclass, type, &ordata); } } else { #if DNS_RDATASET_FIXED offsettable[ocount + norder] = tcurrent - offsetbase; #endif length = nrdata.length; data = nrdata.data; if (type == dns_rdatatype_rrsig) { length++; data--; } *tcurrent++ = (length & 0xff00) >> 8; *tcurrent++ = (length & 0x00ff); #if DNS_RDATASET_FIXED tcurrent += 2; /* fill in later */ #endif memcpy(tcurrent, data, length); tcurrent += length; nadded++; if (nadded < ncount) { do { dns_rdata_reset(&nrdata); #if DNS_RDATASET_FIXED norder = ncurrent[2] * 256 + ncurrent[3]; INSIST(norder < oncount); #endif rdata_from_slab(&ncurrent, rdclass, type, &nrdata); } while (rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)); } } }
ATF_TC_BODY(isdn, tc) { struct { unsigned char data[64]; size_t len; isc_boolean_t ok; } test_data[] = { { /* "" */ { 0x00 }, 1, ISC_TRUE }, { /* "\001" */ { 0x1, 0x01 }, 2, ISC_TRUE }, { /* "\001" "" */ { 0x1, 0x01, 0x00 }, 3, ISC_TRUE }, { /* "\000" "\001" */ { 0x1, 0x01, 0x01, 0x01 }, 4, ISC_TRUE }, { /* sentinal */ { 0x00 }, 0, ISC_FALSE } }; unsigned char buf1[1024]; unsigned char buf2[1024]; isc_buffer_t source, target1, target2; dns_rdata_t rdata; dns_decompress_t dctx; isc_result_t result; size_t i; dns_rdata_isdn_t isdn; UNUSED(tc); for (i = 0; test_data[i].len != 0; i++) { isc_buffer_init(&source, test_data[i].data, test_data[i].len); isc_buffer_add(&source, test_data[i].len); isc_buffer_setactive(&source, test_data[i].len); isc_buffer_init(&target1, buf1, sizeof(buf1)); dns_rdata_init(&rdata); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, dns_rdatatype_isdn, &source, &dctx, 0, &target1); dns_decompress_invalidate(&dctx); if (test_data[i].ok) ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); else ATF_REQUIRE(result != ISC_R_SUCCESS); if (result != ISC_R_SUCCESS) continue; result = dns_rdata_tostruct(&rdata, &isdn, NULL); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); isc_buffer_init(&target2, buf2, sizeof(buf2)); dns_rdata_reset(&rdata); result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in, dns_rdatatype_isdn, &isdn, &target2); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), test_data[i].len); ATF_REQUIRE_EQ(memcmp(buf2, test_data[i].data, test_data[i].len), 0); } }
isc_result_t dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx, dns_tsig_keyring_t *ring) { isc_result_t result = ISC_R_SUCCESS; dns_rdata_tkey_t tkeyin, tkeyout; isc_boolean_t freetkeyin = ISC_FALSE; dns_name_t *qname, *name, *keyname, *signer, tsigner; dns_fixedname_t fkeyname; dns_rdataset_t *tkeyset; dns_rdata_t rdata; dns_namelist_t namelist; char tkeyoutdata[512]; isc_buffer_t tkeyoutbuf; REQUIRE(msg != NULL); REQUIRE(tctx != NULL); REQUIRE(ring != NULL); ISC_LIST_INIT(namelist); /* * Interpret the question section. */ result = dns_message_firstname(msg, DNS_SECTION_QUESTION); if (result != ISC_R_SUCCESS) return (DNS_R_FORMERR); qname = NULL; dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname); /* * Look for a TKEY record that matches the question. */ tkeyset = NULL; name = NULL; result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname, dns_rdatatype_tkey, 0, &name, &tkeyset); if (result != ISC_R_SUCCESS) { /* * Try the answer section, since that's where Win2000 * puts it. */ name = NULL; if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname, dns_rdatatype_tkey, 0, &name, &tkeyset) != ISC_R_SUCCESS) { result = DNS_R_FORMERR; tkey_log("dns_tkey_processquery: couldn't find a TKEY " "matching the question"); goto failure; } } result = dns_rdataset_first(tkeyset); if (result != ISC_R_SUCCESS) { result = DNS_R_FORMERR; goto failure; } dns_rdata_init(&rdata); dns_rdataset_current(tkeyset, &rdata); RETERR(dns_rdata_tostruct(&rdata, &tkeyin, NULL)); freetkeyin = ISC_TRUE; if (tkeyin.error != dns_rcode_noerror) { result = DNS_R_FORMERR; goto failure; } /* * Before we go any farther, verify that the message was signed. * GSSAPI TKEY doesn't require a signature, the rest do. */ dns_name_init(&tsigner, NULL); result = dns_message_signer(msg, &tsigner); if (result != ISC_R_SUCCESS) { if (tkeyin.mode == DNS_TKEYMODE_GSSAPI && result == ISC_R_NOTFOUND) signer = NULL; else { tkey_log("dns_tkey_processquery: query was not " "properly signed - rejecting"); result = DNS_R_FORMERR; goto failure; } } else signer = &tsigner; tkeyout.common.rdclass = tkeyin.common.rdclass; tkeyout.common.rdtype = tkeyin.common.rdtype; ISC_LINK_INIT(&tkeyout.common, link); tkeyout.mctx = msg->mctx; dns_name_init(&tkeyout.algorithm, NULL); dns_name_clone(&tkeyin.algorithm, &tkeyout.algorithm); tkeyout.inception = tkeyout.expire = 0; tkeyout.mode = tkeyin.mode; tkeyout.error = 0; tkeyout.keylen = tkeyout.otherlen = 0; tkeyout.key = tkeyout.other = NULL; /* * A delete operation must have a fully specified key name. If this * is not a delete, we do the following: * if (qname != ".") * keyname = qname + defaultdomain * else * keyname = <random hex> + defaultdomain */ if (tkeyin.mode != DNS_TKEYMODE_DELETE) { dns_tsigkey_t *tsigkey = NULL; if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) { tkey_log("dns_tkey_processquery: tkey-domain not set"); result = DNS_R_REFUSED; goto failure; } dns_fixedname_init(&fkeyname); keyname = dns_fixedname_name(&fkeyname); if (!dns_name_equal(qname, dns_rootname)) { unsigned int n = dns_name_countlabels(qname); RUNTIME_CHECK(dns_name_copy(qname, keyname, NULL) == ISC_R_SUCCESS); dns_name_getlabelsequence(keyname, 0, n - 1, keyname); } else { static char hexdigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; unsigned char randomdata[16]; char randomtext[32]; isc_buffer_t b; unsigned int i, j; result = isc_entropy_getdata(tctx->ectx, randomdata, sizeof(randomdata), NULL, 0); if (result != ISC_R_SUCCESS) goto failure; for (i = 0, j = 0; i < sizeof(randomdata); i++) { unsigned char val = randomdata[i]; randomtext[j++] = hexdigits[val >> 4]; randomtext[j++] = hexdigits[val & 0xF]; } isc_buffer_init(&b, randomtext, sizeof(randomtext)); isc_buffer_add(&b, sizeof(randomtext)); result = dns_name_fromtext(keyname, &b, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto failure; } if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) { /* Yup. This is a hack */ result = dns_name_concatenate(keyname, dns_rootname, keyname, NULL); if (result != ISC_R_SUCCESS) goto failure; } else { result = dns_name_concatenate(keyname, tctx->domain, keyname, NULL); if (result != ISC_R_SUCCESS) goto failure; } result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring); if (result == ISC_R_SUCCESS) { tkeyout.error = dns_tsigerror_badname; dns_tsigkey_detach(&tsigkey); goto failure_with_tkey; } else if (result != ISC_R_NOTFOUND) goto failure; } else
ATF_TC_BODY(edns_client_subnet, tc) { struct { unsigned char data[64]; size_t len; isc_boolean_t ok; } test_data[] = { { /* option code with no content */ { 0x00, 0x08, 0x0, 0x00 }, 4, ISC_FALSE }, { /* Option code family 0, source 0, scope 0 */ { 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 }, 8, ISC_TRUE }, { /* Option code family 1 (ipv4), source 0, scope 0 */ { 0x00, 0x08, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00 }, 8, ISC_TRUE }, { /* Option code family 2 (ipv6) , source 0, scope 0 */ { 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00 }, 8, ISC_TRUE }, { /* extra octet */ { 0x00, 0x08, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 }, 9, ISC_FALSE }, { /* source too long for IPv4 */ { 0x00, 0x08, 0x00, 8, 0x00, 0x01, 33, 0x00, 0x00, 0x00, 0x00, 0x00 }, 12, ISC_FALSE }, { /* source too long for IPv6 */ { 0x00, 0x08, 0x00, 20, 0x00, 0x02, 129, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, 24, ISC_FALSE }, { /* scope too long for IPv4 */ { 0x00, 0x08, 0x00, 8, 0x00, 0x01, 0x00, 33, 0x00, 0x00, 0x00, 0x00 }, 12, ISC_FALSE }, { /* scope too long for IPv6 */ { 0x00, 0x08, 0x00, 20, 0x00, 0x02, 0x00, 129, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, 24, ISC_FALSE }, { /* length too short for source generic */ { 0x00, 0x08, 0x00, 5, 0x00, 0x00, 17, 0x00, 0x00, 0x00, }, 19, ISC_FALSE }, { /* length too short for source ipv4 */ { 0x00, 0x08, 0x00, 7, 0x00, 0x01, 32, 0x00, 0x00, 0x00, 0x00, 0x00 }, 11, ISC_FALSE }, { /* length too short for source ipv6 */ { 0x00, 0x08, 0x00, 19, 0x00, 0x02, 128, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, 23, ISC_FALSE }, { /* sentinal */ { 0x00 }, 0, ISC_FALSE } }; unsigned char buf[1024*1024]; isc_buffer_t source, target1; dns_rdata_t rdata; dns_decompress_t dctx; isc_result_t result; size_t i; UNUSED(tc); for (i = 0; test_data[i].len != 0; i++) { isc_buffer_init(&source, test_data[i].data, test_data[i].len); isc_buffer_add(&source, test_data[i].len); isc_buffer_setactive(&source, test_data[i].len); isc_buffer_init(&target1, buf, sizeof(buf)); dns_rdata_init(&rdata); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, dns_rdatatype_opt, &source, &dctx, 0, &target1); dns_decompress_invalidate(&dctx); if (test_data[i].ok) ATF_CHECK_EQ(result, ISC_R_SUCCESS); else ATF_CHECK(result != ISC_R_SUCCESS); } }
isc_result_t dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl, dns_ttl_t maxttl, isc_boolean_t optout, dns_rdataset_t *addedrdataset) { isc_result_t result; isc_buffer_t buffer; isc_region_t r; dns_rdataset_t *rdataset; dns_rdatatype_t type; dns_name_t *name; dns_ttl_t ttl; dns_trust_t trust; dns_rdata_t rdata[DNS_NCACHE_RDATA]; dns_rdataset_t ncrdataset; dns_rdatalist_t ncrdatalist; unsigned char data[4096]; unsigned int next = 0; /* * Convert the authority data from 'message' into a negative cache * rdataset, and store it in 'cache' at 'node'. */ REQUIRE(message != NULL); /* * We assume that all data in the authority section has been * validated by the caller. */ /* * Initialize the list. */ ncrdatalist.rdclass = dns_db_class(cache); ncrdatalist.type = 0; ncrdatalist.covers = covers; ncrdatalist.ttl = maxttl; ISC_LIST_INIT(ncrdatalist.rdata); ISC_LINK_INIT(&ncrdatalist, link); /* * Build an ncache rdatas into buffer. */ ttl = maxttl; trust = 0xffff; isc_buffer_init(&buffer, data, sizeof(data)); if (message->counts[DNS_SECTION_AUTHORITY]) result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); else result = ISC_R_NOMORE; while (result == ISC_R_SUCCESS) { name = NULL; dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) { for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { if ((rdataset->attributes & DNS_RDATASETATTR_NCACHE) == 0) continue; type = rdataset->type; if (type == dns_rdatatype_rrsig) type = rdataset->covers; if (type == dns_rdatatype_soa || type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3) { if (ttl > rdataset->ttl) ttl = rdataset->ttl; if (ttl < minttl) ttl = minttl; if (trust > rdataset->trust) trust = rdataset->trust; /* * Copy the owner name to the buffer. */ dns_name_toregion(name, &r); result = isc_buffer_copyregion(&buffer, &r); if (result != ISC_R_SUCCESS) return (result); /* * Copy the type to the buffer. */ isc_buffer_availableregion(&buffer, &r); if (r.length < 2) return (ISC_R_NOSPACE); isc_buffer_putuint16(&buffer, rdataset->type); isc_buffer_putuint8(&buffer, (unsigned char)rdataset->trust); /* * Copy the rdataset into the buffer. */ result = copy_rdataset(rdataset, &buffer); if (result != ISC_R_SUCCESS) return (result); if (next >= DNS_NCACHE_RDATA) return (ISC_R_NOSPACE); dns_rdata_init(&rdata[next]); isc_buffer_remainingregion(&buffer, &r); rdata[next].data = r.base; rdata[next].length = r.length; rdata[next].rdclass = ncrdatalist.rdclass; rdata[next].type = 0; rdata[next].flags = 0; ISC_LIST_APPEND(ncrdatalist.rdata, &rdata[next], link); isc_buffer_forward(&buffer, r.length); next++; } } } result = dns_message_nextname(message, DNS_SECTION_AUTHORITY); } if (result != ISC_R_NOMORE) return (result); if (trust == 0xffff) { /* * We didn't find any authority data from which to create a * negative cache rdataset. In particular, we have no SOA. * * We trust that the caller wants negative caching, so this * means we have a "type 3 nxdomain" or "type 3 nodata" * response (see RFC2308 for details). * * We will now build a suitable negative cache rdataset that * will cause zero bytes to be emitted when converted to * wire format. */ /* * The ownername must exist, but it doesn't matter what value * it has. We use the root name. */ dns_name_toregion(dns_rootname, &r); result = isc_buffer_copyregion(&buffer, &r); if (result != ISC_R_SUCCESS) return (result); /* * Copy the type and a zero rdata count to the buffer. */ isc_buffer_availableregion(&buffer, &r); if (r.length < 5) return (ISC_R_NOSPACE); isc_buffer_putuint16(&buffer, 0); /* type */ /* * RFC2308, section 5, says that negative answers without * SOAs should not be cached. */ ttl = 0; /* * Set trust. */ if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 && message->counts[DNS_SECTION_ANSWER] == 0) { /* * The response has aa set and we haven't followed * any CNAME or DNAME chains. */ trust = dns_trust_authauthority; } else trust = dns_trust_additional; isc_buffer_putuint8(&buffer, (unsigned char)trust); /* trust */ isc_buffer_putuint16(&buffer, 0); /* count */ /* * Now add it to the cache. */ if (next >= DNS_NCACHE_RDATA) return (ISC_R_NOSPACE); dns_rdata_init(&rdata[next]); isc_buffer_remainingregion(&buffer, &r); rdata[next].data = r.base; rdata[next].length = r.length; rdata[next].rdclass = ncrdatalist.rdclass; rdata[next].type = 0; rdata[next].flags = 0; ISC_LIST_APPEND(ncrdatalist.rdata, &rdata[next], link); } INSIST(trust != 0xffff); ncrdatalist.ttl = ttl; dns_rdataset_init(&ncrdataset); RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset) == ISC_R_SUCCESS); ncrdataset.trust = trust; if (message->rcode == dns_rcode_nxdomain) ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN; if (optout) ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT; return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset, 0, addedrdataset)); }