SOA parser added
authorMarko Kreen <markokr@gmail.com>
Fri, 15 Jun 2012 11:29:03 +0000 (13:29 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 15 Jun 2012 11:32:48 +0000 (13:32 +0200)
I need to do SOA queries, so here is a parser for them.

- ares_soa_reply: new struct
- ares_malloc_data/ares_free_soa: ARES_DATATYPE_SOA_REPLY
- ares_parse_soa_reply: actual function

Makefile.inc
ares.h
ares_data.c
ares_data.h
ares_free_data.3
ares_parse_soa_reply.3 [new file with mode: 0644]
ares_parse_soa_reply.c [new file with mode: 0644]

index def54cbc91a0508a7be2b23f9be65ea53c21e444..ec0cba4b84c30903d7bb3bc689f30d802680d558 100644 (file)
@@ -28,6 +28,7 @@ CSOURCES = ares__close_sockets.c      \
   ares_parse_naptr_reply.c             \
   ares_parse_ns_reply.c                        \
   ares_parse_ptr_reply.c               \
+  ares_parse_soa_reply.c               \
   ares_parse_srv_reply.c               \
   ares_parse_txt_reply.c               \
   ares_platform.c                      \
@@ -97,6 +98,7 @@ MANPAGES = ares_cancel.3              \
   ares_parse_naptr_reply.3             \
   ares_parse_ns_reply.3                        \
   ares_parse_ptr_reply.3               \
+  ares_parse_soa_reply.3               \
   ares_parse_srv_reply.3               \
   ares_parse_txt_reply.3               \
   ares_process.3                       \
@@ -136,6 +138,7 @@ HTMLPAGES = ares_cancel.html                \
   ares_parse_mx_reply.html             \
   ares_parse_ns_reply.html             \
   ares_parse_ptr_reply.html            \
+  ares_parse_soa_reply.html            \
   ares_parse_srv_reply.html            \
   ares_parse_txt_reply.html            \
   ares_process.html                    \
@@ -175,6 +178,7 @@ PDFPAGES = ares_cancel.pdf          \
   ares_parse_mx_reply.pdf              \
   ares_parse_ns_reply.pdf              \
   ares_parse_ptr_reply.pdf             \
+  ares_parse_soa_reply.pdf             \
   ares_parse_srv_reply.pdf             \
   ares_parse_txt_reply.pdf             \
   ares_process.pdf                     \
diff --git a/ares.h b/ares.h
index a4a119e132ced5fa2181bc7d0fdedfa032d1b047..c5e40695f18aa1b1ab955fab25defb762ca903f3 100644 (file)
--- a/ares.h
+++ b/ares.h
@@ -476,6 +476,16 @@ struct ares_naptr_reply {
   unsigned short           preference;
 };
 
+struct ares_soa_reply {
+  char        *nsname;
+  char        *hostmaster;
+  unsigned int serial;
+  unsigned int refresh;
+  unsigned int retry;
+  unsigned int expire;
+  unsigned int minttl;
+};
+
 /*
 ** Parse the buffer, starting at *abuf and of length alen bytes, previously
 ** obtained from an ares_search call.  Put the results in *host, if nonnull.
@@ -523,10 +533,16 @@ CARES_EXTERN int ares_parse_naptr_reply(const unsigned char* abuf,
                                         int alen,
                                         struct ares_naptr_reply** naptr_out);
 
+CARES_EXTERN int ares_parse_soa_reply(const unsigned char* abuf,
+                                     int alen,
+                                     struct ares_soa_reply** soa_out);
+
 CARES_EXTERN void ares_free_string(void *str);
 
 CARES_EXTERN void ares_free_hostent(struct hostent *host);
 
+CARES_EXTERN void ares_free_soa(struct ares_soa_reply *soa);
+
 CARES_EXTERN void ares_free_data(void *dataptr);
 
 CARES_EXTERN const char *ares_strerror(int code);
index 0e43ddd4d1b4b7ab712448dee4de12835650195b..7c0465073fc74ff7b25fa760b63067f7409ee185 100644 (file)
@@ -106,6 +106,13 @@ void ares_free_data(void *dataptr)
           free(ptr->data.naptr_reply.replacement);
         break;
 
+      case ARES_DATATYPE_SOA_REPLY:
+        if (ptr->data.soa_reply.nsname)
+          free(ptr->data.soa_reply.nsname);
+        if (ptr->data.soa_reply.hostmaster)
+          free(ptr->data.soa_reply.hostmaster);
+       break;
+
       default:
         return;
     }
@@ -172,6 +179,16 @@ void *ares_malloc_data(ares_datatype type)
         ptr->data.naptr_reply.preference = 0;
         break;
 
+      case ARES_DATATYPE_SOA_REPLY:
+        ptr->data.soa_reply.nsname = NULL;
+        ptr->data.soa_reply.hostmaster = NULL;
+        ptr->data.soa_reply.serial = 0;
+        ptr->data.soa_reply.refresh = 0;
+        ptr->data.soa_reply.retry = 0;
+        ptr->data.soa_reply.expire = 0;
+        ptr->data.soa_reply.minttl = 0;
+       break;
+
       default:
         free(ptr);
         return NULL;
index a6acd2032fce03a6dfd586de96a13fb1200f52c0..fbfc496909a170f196c26194f0773416e34e4bfd 100644 (file)
@@ -21,6 +21,7 @@ typedef enum {
   ARES_DATATYPE_ADDR_NODE,    /* struct ares_addr_node - introduced in 1.7.1 */
   ARES_DATATYPE_MX_REPLY,    /* struct ares_mx_reply   - introduced in 1.7.2 */
   ARES_DATATYPE_NAPTR_REPLY,/* struct ares_naptr_reply - introduced in 1.7.6 */
+  ARES_DATATYPE_SOA_REPLY,    /* struct ares_soa_reply - introduced in 1.x.x */
 #if 0
   ARES_DATATYPE_ADDR6TTL,     /* struct ares_addrttl   */
   ARES_DATATYPE_ADDRTTL,      /* struct ares_addr6ttl  */
@@ -59,6 +60,7 @@ struct ares_data {
     struct ares_addr_node   addr_node;
     struct ares_mx_reply    mx_reply;
     struct ares_naptr_reply naptr_reply;
+    struct ares_soa_reply soa_reply;
   } data;
 };
 
index c6cadd572f309be2db2ce432c41aafb2c69d6795..f8a65b93a8eb8819ebb19028514b1e62abd96894 100644 (file)
@@ -55,6 +55,11 @@ When used to free the data returned by ares_parse_txt_reply(3) this
 will free the whole linked list of ares_txt_reply structures returned
 by ares_parse_txt_reply(3), along with any additional storage
 associated with those structures.
+.TP
+.B ares_parse_soa_reply(3)
+When used to free the data returned by ares_parse_soa_reply(3) this
+will free the ares_soa_reply structure, along with any additional storage
+associated with those structure.
 .SH RETURN VALUE
 The ares_free_data() function does not return a value.
 .SH AVAILABILITY
@@ -63,7 +68,8 @@ This function was first introduced in c-ares version 1.7.0.
 .BR ares_get_servers(3),
 .BR ares_parse_srv_reply(3),
 .BR ares_parse_mx_reply(3),
-.BR ares_parse_txt_reply(3)
+.BR ares_parse_txt_reply(3),
+.BR ares_parse_soa_reply(3)
 .SH AUTHOR
 Yang Tse
 .PP
diff --git a/ares_parse_soa_reply.3 b/ares_parse_soa_reply.3
new file mode 100644 (file)
index 0000000..1c4456f
--- /dev/null
@@ -0,0 +1,80 @@
+.\"
+.\" Copyright 1998 by the Massachusetts Institute of Technology.
+.\"
+.\" Permission to use, copy, modify, and distribute this
+.\" software and its documentation for any purpose and without
+.\" fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright
+.\" notice and this permission notice appear in supporting
+.\" documentation, and that the name of M.I.T. not be used in
+.\" advertising or publicity pertaining to distribution of the
+.\" software without specific, written prior permission.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is"
+.\" without express or implied warranty.
+.\"
+.TH ARES_PARSE_SOA_REPLY 3 "29 May 2012"
+.SH NAME
+ares_parse_soa_reply \- Parse a reply to a DNS query of type SOA
+.SH SYNOPSIS
+.nf
+.B #include <ares.h>
+.PP
+.B int ares_parse_soa_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
+.B                             struct ares_soa_reply** \fIsoa_out\fP);
+.fi
+.SH DESCRIPTION
+The
+.B ares_parse_soa_reply
+function parses the response to a query of type SOA into a
+.IR struct\ ares_soa_reply .
+The parameters
+.I abuf
+and
+.I alen
+give the contents of the response.  The result is stored in allocated
+memory and a pointer to it stored into the variable pointed to by
+.IR soa_out .
+It is the caller's responsibility to free the resulting
+.IR soa_out
+structure when it is no longer needed using the function
+.B ares_free_data
+.PP
+The structure 
+.I ares_soa_reply
+contains the following fields:
+.sp
+.in +4n
+.nf
+struct ares_soa_reply {
+       char *nsname;
+       char *hostmaster;
+       unsigned int serial;
+       unsigned int refresh;
+       unsigned int retry;
+       unsigned int expire;
+       unsigned int minttl;
+};
+.fi
+.in
+.PP
+.SH RETURN VALUES
+.B ares_parse_soa_reply
+can return any of the following values:
+.TP 15
+.B ARES_SUCCESS
+The response was successfully parsed.
+.TP 15
+.B ARES_EBADRESP
+The response was malformatted.
+.TP 15
+.B ARES_ENODATA
+The response did not contain an answer to the query.
+.TP 15
+.B ARES_ENOMEM
+Memory was exhausted.
+.SH AVAILABILITY
+This function was first introduced in c-ares version 1.9.0.
+.SH SEE ALSO
+.BR ares_query (3)
+.BR ares_free_data (3)
diff --git a/ares_parse_soa_reply.c b/ares_parse_soa_reply.c
new file mode 100644 (file)
index 0000000..b811954
--- /dev/null
@@ -0,0 +1,135 @@
+
+/* Copyright 1998 by the Massachusetts Institute of Technology.
+ * Copyright (C) 2012 Marko Kreen <markokr@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ */
+
+#include "ares_setup.h"
+
+#ifdef HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#  include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#  include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#  include <arpa/inet.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+#  include <arpa/nameser.h>
+#else
+#  include "nameser.h"
+#endif
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#  include <arpa/nameser_compat.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "ares.h"
+#include "ares_dns.h"
+#include "ares_data.h"
+#include "ares_private.h"
+
+int
+ares_parse_soa_reply(const unsigned char *abuf, int alen,
+                    struct ares_soa_reply **soa_out)
+{
+  const unsigned char *aptr;
+  long len;
+  char *qname = NULL, *rr_name = NULL;
+  struct ares_soa_reply *soa = NULL;
+  int qdcount, ancount;
+  int status;
+
+  if (alen < HFIXEDSZ)
+    return ARES_EBADRESP;
+
+  /* parse message header */
+  qdcount = DNS_HEADER_QDCOUNT(abuf);
+  ancount = DNS_HEADER_ANCOUNT(abuf);
+  if (qdcount != 1 || ancount != 1)
+    return ARES_EBADRESP;
+  aptr = abuf + HFIXEDSZ;
+
+  /* query name */
+  status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len);
+  if (status != ARES_SUCCESS)
+    goto failed_stat;
+  aptr += len;
+
+  /* skip qtype & qclass */
+  if (aptr + QFIXEDSZ > abuf + alen)
+    goto failed;
+  aptr += QFIXEDSZ;
+
+  /* rr_name */
+  status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len);
+  if (status != ARES_SUCCESS)
+    goto failed_stat;
+  aptr += len;
+
+  /* skip rr_type, rr_class, rr_ttl, rr_rdlen */
+  if (aptr + RRFIXEDSZ > abuf + alen)
+    goto failed;
+  aptr += RRFIXEDSZ;
+
+  /* allocate result struct */
+  soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY);
+  if (!soa)
+    return ARES_ENOMEM;
+
+  /* nsname */
+  status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname, &len);
+  if (status != ARES_SUCCESS)
+    goto failed_stat;
+  aptr += len;
+
+  /* hostmaster */
+  status = ares__expand_name_for_response(aptr, abuf, alen, &soa->hostmaster, &len);
+  if (status != ARES_SUCCESS)
+    goto failed_stat;
+  aptr += len;
+
+  /* integer fields */
+  if (aptr + 5 * 4 > abuf + alen)
+    goto failed;
+  soa->serial = DNS__32BIT(aptr + 0 * 4);
+  soa->refresh = DNS__32BIT(aptr + 1 * 4);
+  soa->retry = DNS__32BIT(aptr + 2 * 4);
+  soa->expire = DNS__32BIT(aptr + 3 * 4);
+  soa->minttl = DNS__32BIT(aptr + 4 * 4);
+
+  free(qname);
+  free(rr_name);
+
+  *soa_out = soa;
+
+  return ARES_SUCCESS;
+
+failed:
+  status = ARES_EBADRESP;
+
+failed_stat:
+  ares_free_data(soa);
+  if (qname)
+    free(qname);
+  if (rr_name)
+    free(rr_name);
+  return status;
+}
+