]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
added rr_clone
authorJelte Jansen <jeltejan@NLnetLabs.nl>
Thu, 24 Feb 2005 14:33:57 +0000 (14:33 +0000)
committerJelte Jansen <jeltejan@NLnetLabs.nl>
Thu, 24 Feb 2005 14:33:57 +0000 (14:33 +0000)
added axfr_start() and axfr_next()

host2str.c
ldns/error.h
ldns/resolver.h
ldns/rr.h
resolver.c
rr.c
run-test11.c

index 8b49249537e24f546ee40bbecfddc0612f25bc1b..88dff489b48d2c29d402c65677ab97df4d2302bb 100644 (file)
@@ -819,7 +819,7 @@ ldns_rr_list2buffer_str(ldns_buffer *output, ldns_rr_list *list)
        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);
index 20d45abce36ab529350fb89a48f07e7056e2f4f5..07d0fefdf4e80eba2a5a284a1f30b3243d2de5f4 100644 (file)
@@ -31,7 +31,9 @@ enum ldns_enum_status
        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;
 
index b51395759a0f28d0f727204b156a15b7ef5c5e95..8f86a4154ff6b29e88106394117d7f308845d6e0 100644 (file)
@@ -60,6 +60,15 @@ struct ldns_struct_resolver
        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;
 
@@ -97,4 +106,11 @@ void ldns_resolver_set_defnames(ldns_resolver *, bool);
 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 */
index d4df551d827a9c4ec62f600d852fde7b0f58397f..c892d90b9b1ee513586e7a4e1e51ddc7eb0037c8 100644 (file)
--- a/ldns/rr.h
+++ b/ldns/rr.h
@@ -269,6 +269,7 @@ size_t ldns_rr_uncompressed_size(const ldns_rr *);
 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 */
index e48986cb3ec79287b2a31198c0d0b723f45e5d14..63553fb2d74b8b070ca6f9761ce13a49e5fa1e5a 100644 (file)
@@ -247,6 +247,11 @@ ldns_resolver_new(void)
        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;
 }
 
@@ -373,3 +378,142 @@ ldns_resolver_bgsend()
 {
        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;
+               }
+               
+       }
+       
+}
+
diff --git a/rr.c b/rr.c
index 3ec8b013ac1e7efc0f26500eddeca3dbfb1ccaa2..21eeb048aad750a52ae2191135543e6dbe38679e 100644 (file)
--- a/rr.c
+++ b/rr.c
@@ -614,6 +614,24 @@ ldns_get_class_by_name(const char *name)
        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)
 {
index 06bbbe8b1c1f260442a5bd2bda0e5a7640c8cf0a..fb96306a661032fd6f27698ccb5ecfb142e666cc 100644 (file)
@@ -23,26 +23,14 @@ int
 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) {
@@ -57,86 +45,29 @@ main(int argc, char **argv)
                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;
 }