uint16_t i;
for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
- ldns_rr2buffer_str(output, ldns_rr_list_rr(list, i));
+ (void) ldns_rr2buffer_str(output, ldns_rr_list_rr(list, i));
ldns_buffer_printf(output, "\n");
}
return ldns_buffer_status(output);
LDNS_STATUS_INVALID_IP6,
LDNS_STATUS_INVALID_STR,
LDNS_STATUS_INVALID_B64,
- LDNS_STATUS_INVALID_HEX
+ LDNS_STATUS_INVALID_HEX,
+ LDNS_STATUS_NETWORK_ERROR,
+ LDNS_STATUS_ADDRESS_ERROR
};
typedef enum ldns_enum_status ldns_status;
bool _defnames;
/** \brief if true apply the search list */
bool _dnsrch;
+
+ /** keep some things for axfr */
+ int _socket;
+ int _axfr_soa_count;
+ /* when axfring we get complete packets from the server
+ but we want to give the caller 1 rr at a time, so
+ keep the current pkt */
+ ldns_pkt *_cur_axfr_pkt;
+ uint16_t _axfr_i;
};
typedef struct ldns_struct_resolver ldns_resolver;
void ldns_resolver_set_usevc(ldns_resolver *, bool);
void ldns_resolver_set_dnsrch(ldns_resolver *, bool);
+/**
+ * Prepares the resolver for an axfr query
+ * The query is sent and the answers can be read with ldns_axfr_next
+ */
+ldns_status ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class);
+ldns_rr *ldns_axfr_next(ldns_resolver *resolver);
+
#endif /* !_LDNS_RESOLVER_H */
int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2);
void ldns_rr_list_sort(ldns_rr_list *);
+ldns_rr *ldns_rr_clone(ldns_rr *rr);
#endif /* _LDNS_RR_H */
ldns_resolver_set_port(r, LDNS_PORT);
ldns_resolver_set_domain(r, NULL);
ldns_resolver_set_defnames(r, false);
+
+ r->_socket = 0;
+ r->_axfr_soa_count = 0;
+ r->_axfr_i = 0;
+ r->_cur_axfr_pkt = NULL;
return r;
}
{
return NULL;
}
+
+/*
+ * Start an axfr, send the query and keep the connection open
+ */
+ldns_status
+ldns_axfr_start(ldns_resolver *resolver,
+ ldns_rdf *domain,
+ ldns_rr_class class)
+{
+ ldns_pkt *query;
+ ldns_buffer *query_wire;
+
+ struct sockaddr_storage *ns;
+ struct sockaddr_in *ns4;
+ struct sockaddr_in6 *ns6;
+ socklen_t ns_len = 0;
+ ldns_status status;
+
+ if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
+ return LDNS_STATUS_ERR;
+ }
+
+ /* Create the query */
+ query = ldns_pkt_query_new(ldns_rdf_clone(domain),
+ LDNS_RR_TYPE_AXFR,
+ class,
+ 0);
+
+
+ if (!query) {
+ return LDNS_STATUS_ADDRESS_ERROR;
+ }
+ /* For AXFR, we have to make the connection ourselves */
+ ns = ldns_rdf2native_sockaddr_storage(resolver->_nameservers[0]);
+
+ /* Determine the address size.
+ * This is a nice one for a convenience funtion
+ */
+ switch(ns->ss_family) {
+ case AF_INET:
+ ns4 = (struct sockaddr_in*) ns;
+ ns4->sin_port = htons(53);
+ ns_len = (socklen_t)sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ ns6 = (struct sockaddr_in6*) ns;
+ ns6->sin6_port = htons(53);
+ ns_len = (socklen_t)sizeof(struct sockaddr_in6);
+ break;
+ default:
+ printf("unkown inet family\n");
+ return -1;
+ }
+
+ resolver->_socket = ldns_tcp_connect(ns, ns_len);
+ if (resolver->_socket == 0) {
+ ldns_pkt_free(query);
+ return LDNS_STATUS_NETWORK_ERROR;
+ }
+
+ /* Convert the query to a buffer
+ * Is this necessary?
+ */
+ query_wire = ldns_buffer_new(MAX_PACKETLEN);
+ status = ldns_pkt2buffer_wire(query_wire, query);
+ if (status != LDNS_STATUS_OK) {
+ ldns_pkt_free(query);
+ return status;
+ }
+
+ /* Send the query */
+ if (ldns_tcp_send_query(query_wire, resolver->_socket, ns, ns_len) == 0) {
+ ldns_pkt_free(query);
+ ldns_buffer_free(query_wire);
+ return LDNS_STATUS_NETWORK_ERROR;
+ }
+
+ ldns_pkt_free(query);
+ ldns_buffer_free(query_wire);
+
+ /*
+ * The AXFR is done once the second SOA record is sent
+ */
+ resolver->_axfr_soa_count = 0;
+
+ return LDNS_STATUS_OK;
+}
+
+ldns_rr *
+ldns_axfr_next(ldns_resolver *resolver)
+{
+ ldns_rr *cur_rr;
+
+ /* check if start() has been called */
+ if (!resolver || resolver->_socket == 0) {
+ return NULL;
+ }
+
+ if (resolver->_cur_axfr_pkt) {
+ if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
+ ldns_pkt_free(resolver->_cur_axfr_pkt);
+ resolver->_cur_axfr_pkt = NULL;
+ return ldns_axfr_next(resolver);
+ }
+ cur_rr = ldns_rr_clone(ldns_rr_list_rr(ldns_pkt_answer(resolver->_cur_axfr_pkt), resolver->_axfr_i));
+ resolver->_axfr_i++;
+ if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
+ resolver->_axfr_soa_count++;
+ if (resolver->_axfr_soa_count >= 2) {
+ close(resolver->_socket);
+ resolver->_socket = 0;
+ ldns_pkt_free(resolver->_cur_axfr_pkt);
+ }
+ }
+ return cur_rr;
+ } else {
+ resolver->_cur_axfr_pkt = ldns_tcp_read_packet(resolver->_socket);
+
+ resolver->_axfr_i = 0;
+ return ldns_axfr_next(resolver);
+
+ if (!resolver->_cur_axfr_pkt) {
+ fprintf(stderr, "[ldns_axfr_next] error reading packet\n");
+ return NULL;
+ }
+
+ if (ldns_pkt_rcode(resolver->_cur_axfr_pkt) != 0) {
+ fprintf(stderr, "Got error code\n");
+ close(resolver->_socket);
+ resolver->_socket = 0;
+ ldns_pkt_free(resolver->_cur_axfr_pkt);
+ resolver->_cur_axfr_pkt = NULL;
+ return NULL;
+ }
+
+ }
+
+}
+
return 0;
}
+ldns_rr *
+ldns_rr_clone(ldns_rr *rr)
+{
+ uint16_t i;
+
+ ldns_rr *new_rr = ldns_rr_new();
+ ldns_rr_set_owner(new_rr, ldns_rdf_clone(ldns_rr_owner(rr)));
+ ldns_rr_set_ttl(new_rr, ldns_rr_ttl(rr));
+ ldns_rr_set_type(new_rr, ldns_rr_get_type(rr));
+ ldns_rr_set_class(new_rr, ldns_rr_get_class(rr));
+
+ for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+ ldns_rr_push_rdf(new_rr, ldns_rdf_clone(ldns_rr_rdf(rr, i)));
+ }
+
+ return new_rr;
+}
+
static int
qsort_rr_compare(const void *a, const void *b)
{
main(int argc, char **argv)
{
ldns_rdf *nameserver;
-
- ldns_pkt *query;
- ldns_buffer *query_wire;
+ ldns_rdf *domain;
- ldns_pkt *pkt;
- int soa_count;
- int connection;
-
- struct sockaddr_storage *ns;
- struct sockaddr_in *ns4;
- struct sockaddr_in6 *ns6;
- int ns_len = 0;
+ ldns_resolver *resolver;
+ ldns_rr *rr = NULL;
char *server_ip = NULL;
char *name = NULL;
-
- ldns_rr_list *rr_list;
- ldns_rr *cur_rr;
char *rr_str;
- uint16_t i;
/* Get the domain and the nameserver from the command line */
if (argc < 3) {
printf("Bad server ip\n");
return -1;
}
-
- /* Create the query */
- query = ldns_pkt_query_new_frm_str(name,
- LDNS_RR_TYPE_AXFR,
- LDNS_RR_CLASS_IN,
- 0);
-
- /* For AXFR, we have to make the connection ourselves */
- ns = ldns_rdf2native_sockaddr_storage(nameserver);
-
- ldns_rdf_free(nameserver);
-
- /* Determine the address size.
- * This is a nice one for a convenience funtion
- */
- switch(ns->ss_family) {
- case AF_INET:
- ns4 = (struct sockaddr_in*) ns;
- ns4->sin_port = htons(53);
- ns_len = (socklen_t)sizeof(struct sockaddr_in);
- break;
- case AF_INET6:
- ns6 = (struct sockaddr_in6*) ns;
- ns6->sin6_port = htons(53);
- ns_len = (socklen_t)sizeof(struct sockaddr_in6);
- break;
- default:
- printf("unkown inet family\n");
- return -1;
- }
-
- connection = ldns_tcp_connect(ns, ns_len);
- if (connection == 0) {
- return -1;
- }
- /* Convert the query to a buffer
- * Is this necessary?
- */
- query_wire = ldns_buffer_new(MAX_PACKETLEN);
- if (ldns_pkt2buffer_wire(query_wire, query) != LDNS_STATUS_OK) {
- printf("Unable to create wire data for query\n");
- return -1;
+ resolver = ldns_resolver_new();
+ ldns_resolver_set_usevc(resolver, true);
+ ldns_resolver_push_nameserver(resolver, nameserver);
+
+ domain = ldns_rdf_new_frm_str(name, LDNS_RDF_TYPE_DNAME);
+ if (!domain) {
+ printf("Bad domain\n");
}
- /* Send the query */
- ldns_tcp_send_query(query_wire, connection, ns, ns_len);
+ ldns_axfr_start(resolver, domain, LDNS_RR_CLASS_IN);
- ldns_pkt_free(query);
- ldns_buffer_free(query_wire);
-
- /* Print all the resource records we receive.
- * The AXFR is done once the second SOA record is sent
- */
- soa_count = 0;
- while (soa_count < 2) {
- pkt = ldns_tcp_read_packet(connection);
-
- if (!pkt) {
- printf("error reading packet\n");
- } else {
- rr_list = ldns_pkt_answer(pkt);
-
- /* Counting the number of certain types of rrs might
- * be another good convenience function */
- for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
- cur_rr = ldns_rr_list_rr(rr_list, i);
- if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
- soa_count++;
- }
- rr_str = ldns_rr2str(cur_rr);
- printf("%s\n", rr_str);
- FREE(rr_str);
- }
- ldns_pkt_free(pkt);
- }
+ while ((rr = ldns_axfr_next(resolver))) {
+ rr_str = ldns_rr2str(rr);
+ printf("%s\n", rr_str);
+ ldns_rr_free(rr);
+ FREE(rr_str);
}
- /* Don't forget to close the connection */
- close(connection);
-
+
+ ldns_rdf_free(nameserver);
+ ldns_rdf_free(domain);
+ ldns_resolver_free(resolver);
+
return 0;
}