Exemple #1
0
/** setup qinfo and edns */
static int
setup_qinfo_edns(struct libworker* w, struct ctx_query* q, 
	struct query_info* qinfo, struct edns_data* edns)
{
	ldns_rdf* rdf;
	qinfo->qtype = (uint16_t)q->res->qtype;
	qinfo->qclass = (uint16_t)q->res->qclass;
	rdf = ldns_dname_new_frm_str(q->res->qname);
	if(!rdf) {
		return 0;
	}
#ifdef UNBOUND_ALLOC_LITE
	qinfo->qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf));
	qinfo->qname_len = ldns_rdf_size(rdf);
	ldns_rdf_deep_free(rdf);
	rdf = 0;
#else
	qinfo->qname = ldns_rdf_data(rdf);
	qinfo->qname_len = ldns_rdf_size(rdf);
#endif
	edns->edns_present = 1;
	edns->ext_rcode = 0;
	edns->edns_version = 0;
	edns->bits = EDNS_DO;
	if(ldns_buffer_capacity(w->back->udp_buff) < 65535)
		edns->udp_size = (uint16_t)ldns_buffer_capacity(
			w->back->udp_buff);
	else	edns->udp_size = 65535;
	ldns_rdf_free(rdf);
	return 1;
}
Exemple #2
0
/**
 * Add new RR. It converts ldns RR to wire format.
 * @param anchors: anchor storage.
 * @param buffer: parsing buffer.
 * @param rr: the rr (allocated by caller).
 * @return NULL on error, else the trust anchor.
 */
static struct trust_anchor*
anchor_store_new_rr(struct val_anchors* anchors, ldns_buffer* buffer, 
	ldns_rr* rr)
{
	struct trust_anchor* ta;
	ldns_rdf* owner = ldns_rr_owner(rr);
	ldns_status status;
	ldns_buffer_clear(buffer);
	ldns_buffer_skip(buffer, 2); /* skip rdatalen */
	status = ldns_rr_rdata2buffer_wire(buffer, rr);
	if(status != LDNS_STATUS_OK) {
		log_err("error converting trustanchor to wireformat: %s", 
			ldns_get_errorstr_by_id(status));
		return NULL;
	}
	ldns_buffer_flip(buffer);
	ldns_buffer_write_u16_at(buffer, 0, ldns_buffer_limit(buffer) - 2);

	if(!(ta=anchor_store_new_key(anchors, ldns_rdf_data(owner), 
		ldns_rr_get_type(rr), ldns_rr_get_class(rr),
		ldns_buffer_begin(buffer), ldns_buffer_limit(buffer)))) {
		return NULL;
	}
	log_nametypeclass(VERB_QUERY, "adding trusted key",
		ldns_rdf_data(owner), 
		ldns_rr_get_type(rr), ldns_rr_get_class(rr));
	return ta;
}
/**
 * Publish the NSEC3 parameters as indicated by the signer configuration.
 *
 */
ods_status
zone_publish_nsec3param(zone_type* zone)
{
    rrset_type* rrset = NULL;
    rr_type* n3prr = NULL;
    ldns_rr* rr = NULL;
    ods_status status = ODS_STATUS_OK;

    if (!zone || !zone->name || !zone->db || !zone->signconf) {
        return ODS_STATUS_ASSERT_ERR;
    }
    if (!zone->signconf->nsec3params) {
        /* NSEC */
        ods_log_assert(zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC);
        return ODS_STATUS_OK;
    }

    if (!zone->signconf->nsec3params->rr) {
        rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
        if (!rr) {
            ods_log_error("[%s] unable to publish nsec3params for zone %s: "
                "error creating rr (%s)", zone_str, zone->name,
                ods_status2str(status));
            return ODS_STATUS_MALLOC_ERR;
        }
        ldns_rr_set_class(rr, zone->klass);
        ldns_rr_set_ttl(rr, 0);
        ldns_rr_set_owner(rr, ldns_rdf_clone(zone->apex));
        ldns_nsec3_add_param_rdfs(rr,
            zone->signconf->nsec3params->algorithm, 0,
            zone->signconf->nsec3params->iterations,
            zone->signconf->nsec3params->salt_len,
            zone->signconf->nsec3params->salt_data);
        /**
         * Always set bit 7 of the flags to zero,
         * according to rfc5155 section 11
         */
        ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(rr, 1)), 7, 0);
        zone->signconf->nsec3params->rr = rr;
    }
    ods_log_assert(zone->signconf->nsec3params->rr);
    status = zone_add_rr(zone, zone->signconf->nsec3params->rr, 0);
    if (status == ODS_STATUS_UNCHANGED) {
        /* rr already exists, adjust pointer */
        rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_NSEC3PARAMS);
        ods_log_assert(rrset);
        n3prr = rrset_lookup_rr(rrset, zone->signconf->nsec3params->rr);
        ods_log_assert(n3prr);
        if (n3prr->rr != zone->signconf->nsec3params->rr) {
            ldns_rr_free(zone->signconf->nsec3params->rr);
        }
        zone->signconf->nsec3params->rr = n3prr->rr;
        status = ODS_STATUS_OK;
    } else if (status != ODS_STATUS_OK) {
        ods_log_error("[%s] unable to publish nsec3params for zone %s: "
            "error adding nsec3params (%s)", zone_str,
            zone->name, ods_status2str(status));
    }
    return status;
}
Exemple #4
0
ldns_status
ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
{
	if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
		ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
	}
	return ldns_buffer_status(buffer);
}
Exemple #5
0
ldns_status
ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
{
	if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) {
		ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
	}
	return ldns_buffer_status(buffer);
}
Exemple #6
0
/* put this here tmp. for debugging */
void
xprintf_rdf(ldns_rdf *rd)
{
	/* assume printable string */
	fprintf(stderr, "size\t:%u\n", (unsigned int)ldns_rdf_size(rd));
	fprintf(stderr, "type\t:%u\n", (unsigned int)ldns_rdf_get_type(rd));
	fprintf(stderr, "data\t:[%.*s]\n", (int)ldns_rdf_size(rd), 
			(char*)ldns_rdf_data(rd));
}
Exemple #7
0
/** add hint to delegation hints */
static int
ah(struct delegpt* dp, const char* sv, const char* ip)
{
	struct sockaddr_storage addr;
	socklen_t addrlen;
	ldns_rdf* rdf = ldns_dname_new_frm_str(sv);
	if(!rdf) {
		log_err("could not parse %s", sv);
		return 0;
	}
	if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0) ||
	   !extstrtoaddr(ip, &addr, &addrlen) ||
	   !delegpt_add_target_mlc(dp, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
		&addr, addrlen, 0, 0)) {
		ldns_rdf_deep_free(rdf);
		return 0;
	}
	ldns_rdf_deep_free(rdf);
	return 1;
}
Exemple #8
0
size_t 
ldns_rr_dnskey_key_size(const ldns_rr *key) 
{
	if (!key || !ldns_rr_dnskey_key(key) 
			|| !ldns_rr_dnskey_algorithm(key)) {
		return 0;
	}
	return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)),
	                                   ldns_rdf_size(ldns_rr_dnskey_key(key)),
	                                   ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key))
	                                  );
}
Exemple #9
0
/* Returns whether the last label in the name is a root label (a empty label).
 * Note that it is not enough to just test the last character to be 0,
 * because it may be part of the last label itself.
 */
static bool
ldns_dname_last_label_is_root_label(const ldns_rdf* dname)
{
	size_t src_pos;
	size_t len = 0;

	for (src_pos = 0; src_pos < ldns_rdf_size(dname); src_pos += len + 1) {
		len = ldns_rdf_data(dname)[src_pos];
	}
	assert(src_pos == ldns_rdf_size(dname));

	return src_pos > 0 && len == 0;
}
Exemple #10
0
/* code from rdata.c */
static struct sockaddr_storage *
ldns_rdf2native_sockaddr_storage_port(
		const ldns_rdf *rd, uint16_t port, size_t *size)
{
        struct sockaddr_storage *data;
        struct sockaddr_in  *data_in;
        struct sockaddr_in6 *data_in6;

        data = LDNS_MALLOC(struct sockaddr_storage);
        if (!data) {
                return NULL;
        }
	/* zero the structure for portability */
	memset(data, 0, sizeof(struct sockaddr_storage));

        switch(ldns_rdf_get_type(rd)) {
                case LDNS_RDF_TYPE_A:
#ifndef S_SPLINT_S
                        data->ss_family = AF_INET;
#endif
                        data_in = (struct sockaddr_in*) data;
                        data_in->sin_port = (in_port_t)htons(port);
                        memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
                        *size = sizeof(struct sockaddr_in);
                        return data;
                case LDNS_RDF_TYPE_AAAA:
#ifndef S_SPLINT_S
                        data->ss_family = AF_INET6;
#endif
                        data_in6 = (struct sockaddr_in6*) data;
                        data_in6->sin6_port = (in_port_t)htons(port);
                        memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
                        *size = sizeof(struct sockaddr_in6);
                        return data;
                default:
                        LDNS_FREE(data);
                        return NULL;
        }
}
Exemple #11
0
/**
 * Insert insecure anchor
 * @param anchors: anchor storage.
 * @param str: the domain name.
 * @return NULL on error, Else last trust anchor point
 */
static struct trust_anchor*
anchor_insert_insecure(struct val_anchors* anchors, const char* str)
{
	struct trust_anchor* ta;
	ldns_rdf* nm = ldns_dname_new_frm_str(str);
	if(!nm) {
		log_err("parse error in domain name '%s'", str);
		return NULL;
	}
	ta = anchor_store_new_key(anchors, ldns_rdf_data(nm), LDNS_RR_TYPE_DS,
		LDNS_RR_CLASS_IN, NULL, 0);
	ldns_rdf_deep_free(nm);
	return ta;
}
/** process nsec3 params and perform hashing */
static void
process_nsec3(int argc, char* argv[])
{
	char line[10240];
	ldns_rdf* salt;
	ldns_rdf* in, *out;
	ldns_status status;
	status = ldns_str2rdf_nsec3_salt(&salt, argv[5]);
	if(status != LDNS_STATUS_OK)
		fatal_exit("Could not parse salt %s: %s", argv[5],
			ldns_get_errorstr_by_id(status));
	log_assert(argc == 6);
	while(fgets(line, (int)sizeof(line), stdin)) {
		if(strlen(line) > 0)
			line[strlen(line)-1] = 0; /* remove trailing newline */
		if(line[0]==0)
			continue;
		status = ldns_str2rdf_dname(&in, line);
		if(status != LDNS_STATUS_OK)
			fatal_exit("Could not parse name %s: %s", line,
				ldns_get_errorstr_by_id(status));
		ldns_rdf_print(stdout, in);
		printf(" -> ");
		/* arg 3 is flags, unused */
		out = ldns_nsec3_hash_name(in, (uint8_t)atoi(argv[2]), 
			(uint16_t)atoi(argv[4]),
			ldns_rdf_data(salt)[0], ldns_rdf_data(salt)+1);
		if(!out)
			fatal_exit("Could not hash %s", line);
		ldns_rdf_print(stdout, out);
		printf("\n");
		ldns_rdf_deep_free(in);
		ldns_rdf_deep_free(out);
	}
	ldns_rdf_deep_free(salt);
}
Exemple #13
0
ldns_status
ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
{
	size_t i;
	uint8_t *rdf_data;

	if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) {
		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
			rdf_data = ldns_rdf_data(rdf);
			for (i = 0; i < ldns_rdf_size(rdf); i++) {
				ldns_buffer_write_u8(buffer,
								 LDNS_DNAME_NORMALIZE(rdf_data[i]));
			}
		}
	} else {
		/* direct copy for all other types */
		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
			ldns_buffer_write(buffer,
						   ldns_rdf_data(rdf),
						   ldns_rdf_size(rdf));
		}
	}
	return ldns_buffer_status(buffer);
}
Exemple #14
0
getdns_return_t
getdns_convert_fqdn_to_dns_name(
    const char *fqdn_as_string, struct getdns_bindata **dns_name_wire_fmt)
{
    ldns_rdf *rdf;
    if (ldns_str2rdf_dname(&rdf, fqdn_as_string) != LDNS_STATUS_OK)
        return GETDNS_RETURN_GENERIC_ERROR;;
    *dns_name_wire_fmt = malloc(sizeof(struct getdns_bindata));
    if (*dns_name_wire_fmt) {
        (*dns_name_wire_fmt)->size = ldns_rdf_size(rdf);
        (*dns_name_wire_fmt)->data = ldns_rdf_data(rdf);
    }
    ldns_rdf_free(rdf);
    return *dns_name_wire_fmt ? GETDNS_RETURN_GOOD
           : GETDNS_RETURN_MEMORY_ERROR;
}
Exemple #15
0
/** Match q edns data to p raw edns data */
static int
match_ednsdata(ldns_pkt* q, struct reply_packet* p)
{
	size_t qdlen, pdlen;
	uint8_t *qd, *pd;
	if(!ldns_pkt_edns(q) || !ldns_pkt_edns_data(q)) {
		verbose(3, "No EDNS data\n");
		return 0;
	}
	qdlen = ldns_rdf_size(ldns_pkt_edns_data(q));
	pdlen = ldns_buffer_limit(p->raw_ednsdata);
	qd = ldns_rdf_data(ldns_pkt_edns_data(q));
	pd = ldns_buffer_begin(p->raw_ednsdata);
	if( qdlen == pdlen && 0 == memcmp(qd, pd, qdlen) ) return 1;
	verbose(3, "EDNS data does not match.\n");
	verbose_hex(3, qd, qdlen, "q:");
	verbose_hex(3, pd, pdlen, "p:");
	return 0;
}
Exemple #16
0
/** make NULL entries for stubs */
static int
make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
{
	struct config_stub* s;
	for(s = cfg->stubs; s; s = s->next) {
		ldns_rdf* rdf = ldns_dname_new_frm_str(s->name);
		if(!rdf) {
			log_err("cannot parse stub name '%s'", s->name);
			return 0;
		}
		if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN,
				ldns_rdf_data(rdf))) {
			ldns_rdf_deep_free(rdf);
			log_err("out of memory");
			return 0;
		}
		ldns_rdf_deep_free(rdf);
	}
	return 1;
}
Exemple #17
0
ldns_status
ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
		uint16_t port, ldns_dane_transport transport)
{
	char buf[LDNS_MAX_DOMAINLEN];
	size_t s;

	assert(tlsa_owner != NULL);
	assert(name != NULL);
	assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME);

	s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port);
	buf[0] = (char)(s - 1);

	switch(transport) {
	case LDNS_DANE_TRANSPORT_TCP:
		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp");
		break;
	
	case LDNS_DANE_TRANSPORT_UDP:
		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp");
		break;

	case LDNS_DANE_TRANSPORT_SCTP:
		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp");
		break;
	
	default:
		return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT;
	}
	if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) {
		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
	}
	memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name));
	*tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
			s + ldns_rdf_size(name), buf);
	if (*tlsa_owner == NULL) {
		return LDNS_STATUS_MEM_ERR;
	}
	return LDNS_STATUS_OK;
}
Exemple #18
0
/** parse commandline argument domain name */
static int
parse_arg_name(SSL* ssl, char* str, uint8_t** res, size_t* len, int* labs)
{
	ldns_rdf* rdf;
	*res = NULL;
	*len = 0;
	*labs = 0;
	rdf = ldns_dname_new_frm_str(str);
	if(!rdf) {
		ssl_printf(ssl, "error cannot parse name %s\n", str);
		return 0;
	}
	*res = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf));
	ldns_rdf_deep_free(rdf);
	if(!*res) {
		ssl_printf(ssl, "error out of memory\n");
		return 0;
	}
	*labs = dname_count_size_labels(*res, len);
	return 1;
}
Exemple #19
0
/** set stub host names */
static int 
read_stubs_host(struct config_stub* s, struct delegpt* dp)
{
	struct config_strlist* p;
	ldns_rdf* rdf;
	for(p = s->hosts; p; p = p->next) {
		log_assert(p->str);
		rdf = ldns_dname_new_frm_str(p->str);
		if(!rdf) {
			log_err("cannot parse stub %s nameserver name: '%s'", 
				s->name, p->str);
			return 0;
		}
		if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) {
			ldns_rdf_deep_free(rdf);
			log_err("out of memory");
			return 0;
		}
		ldns_rdf_deep_free(rdf);
	}
	return 1;
}
Exemple #20
0
/** set stub name */
static struct delegpt* 
read_stubs_name(struct config_stub* s)
{
	struct delegpt* dp;
	ldns_rdf* rdf;
	if(!s->name) {
		log_err("stub zone without a name");
		return NULL;
	}
	rdf = ldns_dname_new_frm_str(s->name);
	if(!rdf) {
		log_err("cannot parse stub zone name %s", s->name);
		return NULL;
	}
	if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) {
		ldns_rdf_deep_free(rdf);
		log_err("out of memory");
		return NULL;
	}
	ldns_rdf_deep_free(rdf);
	return dp;
}
Exemple #21
0
/** read root hints from file */
static int 
read_root_hints(struct iter_hints* hints, char* fname)
{
	int lineno = 0;
	uint32_t default_ttl = 0;
	ldns_rdf* origin = NULL;
	ldns_rdf* prev_rr = NULL;
	struct delegpt* dp;
	ldns_rr* rr = NULL;
	ldns_status status;
	uint16_t c = LDNS_RR_CLASS_IN;
	FILE* f = fopen(fname, "r");
	if(!f) {
		log_err("could not read root hints %s: %s",
			fname, strerror(errno));
		return 0;
	}
	dp = delegpt_create_mlc(NULL);
	if(!dp) {
		log_err("out of memory reading root hints");
		fclose(f);
		return 0;
	}
	verbose(VERB_QUERY, "Reading root hints from %s", fname);
	dp->has_parent_side_NS = 1;
	while(!feof(f)) {
		status = ldns_rr_new_frm_fp_l(&rr, f, 
			&default_ttl, &origin, &prev_rr, &lineno);
		if(status == LDNS_STATUS_SYNTAX_EMPTY ||
			status == LDNS_STATUS_SYNTAX_TTL ||
			status == LDNS_STATUS_SYNTAX_ORIGIN)
			continue;
		if(status != LDNS_STATUS_OK) {
			log_err("reading root hints %s %d: %s", fname,
				lineno, ldns_get_errorstr_by_id(status));
			goto stop_read;
		}
		if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) {
			if(!delegpt_add_ns_mlc(dp,
				ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) {
				log_err("out of memory reading root hints");
				goto stop_read;
			}
			c = ldns_rr_get_class(rr);
			if(!dp->name) {
				if(!delegpt_set_name_mlc(dp,
					ldns_rdf_data(ldns_rr_owner(rr)))){
					log_err("out of memory.");
					goto stop_read;
				}
			}
		} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A) {
			struct sockaddr_in sa;
			socklen_t len = (socklen_t)sizeof(sa);
			memset(&sa, 0, len);
			sa.sin_family = AF_INET;
			sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
			memmove(&sa.sin_addr, 
				ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE);
			if(!delegpt_add_target_mlc(dp,
					ldns_rdf_data(ldns_rr_owner(rr)),
					ldns_rdf_size(ldns_rr_owner(rr)),
					(struct sockaddr_storage*)&sa, len, 
					0, 0)) {
				log_err("out of memory reading root hints");
				goto stop_read;
			}
		} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
			struct sockaddr_in6 sa;
			socklen_t len = (socklen_t)sizeof(sa);
			memset(&sa, 0, len);
			sa.sin6_family = AF_INET6;
			sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
			memmove(&sa.sin6_addr, 
				ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE);
			if(!delegpt_add_target_mlc(dp,
					ldns_rdf_data(ldns_rr_owner(rr)),
					ldns_rdf_size(ldns_rr_owner(rr)),
					(struct sockaddr_storage*)&sa, len,
					0, 0)) {
				log_err("out of memory reading root hints");
				goto stop_read;
			}
		} else {
			log_warn("root hints %s:%d skipping type %d",
				fname, lineno, ldns_rr_get_type(rr));
		}

		ldns_rr_free(rr);
	}

	if (origin)
		ldns_rdf_deep_free(origin);
	if (prev_rr)
		ldns_rdf_deep_free(prev_rr);
	fclose(f);
	if(!dp->name) {
		log_warn("root hints %s: no NS content", fname);
		delegpt_free_mlc(dp);
		return 1;
	}
	if(!hints_insert(hints, c, dp, 0)) {
		return 0;
	}
	delegpt_log(VERB_QUERY, dp);
	return 1;

stop_read:
	if (origin)
		ldns_rdf_deep_free(origin);
	if (prev_rr)
		ldns_rdf_deep_free(prev_rr);
	delegpt_free_mlc(dp);
	fclose(f);
	return 0;
}
Exemple #22
0
ldns_status
ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
					   ldns_rr_list *new_rrs,
					   ldns_key_list *key_list,
					   int (*func)(ldns_rr *, void *),
					   void *arg,
					   uint8_t algorithm,
					   uint8_t flags,
					   uint16_t iterations,
					   uint8_t salt_length,
					   uint8_t *salt)
{
	ldns_rr *nsec3, *nsec3params;
	ldns_status result = LDNS_STATUS_OK;

	/* zone is already sorted */
	ldns_dnssec_zone_mark_glue(zone);

	/* TODO if there are already nsec3s presents and their
	 * parameters are the same as these, we don't have to recreate
	 */
	if (zone->names) {
		/* add empty nonterminals */
		ldns_dnssec_zone_add_empty_nonterminals(zone);

		nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
		if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
			/* no need to recreate */
		} else {
			if (!ldns_dnssec_zone_find_rrset(zone,
									   zone->soa->name,
									   LDNS_RR_TYPE_NSEC3PARAMS)) {
				/* create and add the nsec3params rr */
				nsec3params =
					ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
				ldns_rr_set_owner(nsec3params,
							   ldns_rdf_clone(zone->soa->name));
				ldns_nsec3_add_param_rdfs(nsec3params,
									 algorithm,
									 flags,
									 iterations,
									 salt_length,
									 salt);
				/* always set bit 7 of the flags to zero, according to
				 * rfc5155 section 11 */
				ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params, 1)), 7, 0);
				ldns_dnssec_zone_add_rr(zone, nsec3params);
				ldns_rr_list_push_rr(new_rrs, nsec3params);
			}
			result = ldns_dnssec_zone_create_nsec3s(zone,
											new_rrs,
											algorithm,
											flags,
											iterations,
											salt_length,
											salt);
			if (result != LDNS_STATUS_OK) {
				return result;
			}
		}

		result = ldns_dnssec_zone_create_rrsigs(zone,
										new_rrs,
										key_list,
										func,
										arg);
	}
	
	return result;
}
int
getrrsetbyname(const char *hostname, unsigned int rdclass,
	       unsigned int rdtype, unsigned int flags,
	       struct rrsetinfo **res)
{
	int result;
	unsigned int i, j, index_ans, index_sig;
	struct rrsetinfo *rrset = NULL;
	struct rdatainfo *rdata;
	size_t len;
	ldns_resolver *ldns_res;
	ldns_rdf *domain = NULL;
	ldns_pkt *pkt = NULL;
	ldns_rr_list *rrsigs = NULL, *rrdata = NULL;
	ldns_status err;
	ldns_rr *rr;

	/* check for invalid class and type */
	if (rdclass > 0xffff || rdtype > 0xffff) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* don't allow queries of class or type ANY */
	if (rdclass == 0xff || rdtype == 0xff) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* don't allow flags yet, unimplemented */
	if (flags) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* Initialize resolver from resolv.conf */
	domain = ldns_dname_new_frm_str(hostname);
	if ((err = ldns_resolver_new_frm_file(&ldns_res, NULL)) != \
	    LDNS_STATUS_OK) {
		result = ERRSET_FAIL;
		goto fail;
	}

#ifdef LDNS_DEBUG
	ldns_resolver_set_debug(ldns_res, true);
#endif /* LDNS_DEBUG */

	ldns_resolver_set_dnssec(ldns_res, true); /* Use DNSSEC */

	/* make query */
	pkt = ldns_resolver_query(ldns_res, domain, rdtype, rdclass, LDNS_RD);

	/*** TODO: finer errcodes -- see original **/
	if (!pkt || ldns_pkt_ancount(pkt) < 1) {
		result = ERRSET_FAIL;
		goto fail;
	}

	/* initialize rrset */
	rrset = calloc(1, sizeof(struct rrsetinfo));
	if (rrset == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}

	rrdata = ldns_pkt_rr_list_by_type(pkt, rdtype, LDNS_SECTION_ANSWER);
	rrset->rri_nrdatas = ldns_rr_list_rr_count(rrdata);
	if (!rrset->rri_nrdatas) {
		result = ERRSET_NODATA;
		goto fail;
	}

	/* copy name from answer section */
	len = ldns_rdf_size(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0)));
	if ((rrset->rri_name = malloc(len)) == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}
	memcpy(rrset->rri_name,
	    ldns_rdf_data(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))), len);

	rrset->rri_rdclass = ldns_rr_get_class(ldns_rr_list_rr(rrdata, 0));
	rrset->rri_rdtype = ldns_rr_get_type(ldns_rr_list_rr(rrdata, 0));
	rrset->rri_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrdata, 0));

	debug2("ldns: got %u answers from DNS", rrset->rri_nrdatas);

	/* Check for authenticated data */
	if (ldns_pkt_ad(pkt)) {
		rrset->rri_flags |= RRSET_VALIDATED;
	} else { /* AD is not set, try autonomous validation */
		ldns_rr_list * trusted_keys = ldns_rr_list_new();

		debug2("ldns: trying to validate RRset");
		/* Get eventual sigs */
		rrsigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG,
		    LDNS_SECTION_ANSWER);

		rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs);
		debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS",
		       rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG);

		if ((err = ldns_verify_trusted(ldns_res, rrdata, rrsigs,
		     trusted_keys)) == LDNS_STATUS_OK) {
			rrset->rri_flags |= RRSET_VALIDATED;
			debug2("ldns: RRset is signed with a valid key");
		} else {
			debug2("ldns: RRset validation failed: %s",
			    ldns_get_errorstr_by_id(err));
		}

		ldns_rr_list_deep_free(trusted_keys);
	}

	/* allocate memory for answers */
	rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
	   sizeof(struct rdatainfo));

	if (rrset->rri_rdatas == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}

	/* allocate memory for signatures */
	if (rrset->rri_nsigs > 0) {
		rrset->rri_sigs = calloc(rrset->rri_nsigs,
		    sizeof(struct rdatainfo));

		if (rrset->rri_sigs == NULL) {
			result = ERRSET_NOMEMORY;
			goto fail;
		}
	}

	/* copy answers & signatures */
	for (i=0, index_ans=0, index_sig=0; i< pkt->_header->_ancount; i++) {
		rdata = NULL;
		rr = ldns_rr_list_rr(ldns_pkt_answer(pkt), i);

		if (ldns_rr_get_class(rr) == rrset->rri_rdclass &&
		    ldns_rr_get_type(rr) == rrset->rri_rdtype) {
			rdata = &rrset->rri_rdatas[index_ans++];
		}

		if (rr->_rr_class == rrset->rri_rdclass &&
		    rr->_rr_type == LDNS_RR_TYPE_RRSIG &&
		    rrset->rri_sigs) {
			rdata = &rrset->rri_sigs[index_sig++];
		}

		if (rdata) {
			size_t rdata_offset = 0;

			rdata->rdi_length = 0;
			for (j=0; j< rr->_rd_count; j++) {
				rdata->rdi_length +=
				    ldns_rdf_size(ldns_rr_rdf(rr, j));
			}

			rdata->rdi_data = malloc(rdata->rdi_length);
			if (rdata->rdi_data == NULL) {
				result = ERRSET_NOMEMORY;
				goto fail;
			}

			/* Re-create the raw DNS RDATA */
			for (j=0; j< rr->_rd_count; j++) {
				len = ldns_rdf_size(ldns_rr_rdf(rr, j));
				memcpy(rdata->rdi_data + rdata_offset,
				       ldns_rdf_data(ldns_rr_rdf(rr, j)), len);
				rdata_offset += len;
			}
		}
	}

	*res = rrset;
	result = ERRSET_SUCCESS;

fail:
	/* freerrset(rrset); */
	ldns_rdf_deep_free(domain);
	ldns_pkt_free(pkt);
	ldns_rr_list_deep_free(rrsigs);
	ldns_rr_list_deep_free(rrdata);
	ldns_resolver_deep_free(ldns_res);

	return result;
}
int
main(int argc, char *argv[])
{
	FILE *keyfp;
	char *keyname;
	ldns_rr *k;
	uint16_t flags;
	char *program = argv[0];
	int nofile = 0;
	ldns_rdf *origin = NULL;
	ldns_status result;

	argv++, argc--;
	while (argc && argv[0][0] == '-') {
		if (strcmp(argv[0], "-n") == 0) {
			nofile=1;
		}
		else {
			usage(stderr, program);
			exit(EXIT_FAILURE);
		}
		argv++, argc--;
	}

	if (argc != 1) {
		usage(stderr, program);
		exit(EXIT_FAILURE);
	}
	keyname = strdup(argv[0]);

	keyfp = fopen(keyname, "r");
	if (!keyfp) {
		fprintf(stderr, "Failed to open public key file %s: %s\n", keyname,
				strerror(errno));
		exit(EXIT_FAILURE);
	}

	result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL);
	/* what does this while loop do? */
	while (result == LDNS_STATUS_SYNTAX_ORIGIN) {
		result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL);
	}
	if (result != LDNS_STATUS_OK) {
		fprintf(stderr, "Could not read public key from file %s: %s\n", keyname, ldns_get_errorstr_by_id(result));
		exit(EXIT_FAILURE);
	}
	fclose(keyfp);

	flags = ldns_read_uint16(ldns_rdf_data(ldns_rr_dnskey_flags(k)));
	flags |= LDNS_KEY_REVOKE_KEY;

	if (!ldns_rr_dnskey_set_flags(k,
		ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, flags)))
	{
		fprintf(stderr, "Revocation failed\n");
		exit(EXIT_FAILURE);
	}

	/* print the public key RR to .key */

	if (nofile)
		ldns_rr_print(stdout,k);
	else {
		keyfp = fopen(keyname, "w");
		if (!keyfp) {
			fprintf(stderr, "Unable to open %s: %s\n", keyname,
				strerror(errno));
			exit(EXIT_FAILURE);
		} else {
			ldns_rr_print(keyfp, k);
			fclose(keyfp);
			fprintf(stdout, "DNSKEY revoked\n");
		}
	}

	free(keyname);
	ldns_rr_free(k);

        exit(EXIT_SUCCESS);
}