summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Kreen <markokr@gmail.com>2012-06-15 13:29:03 +0200
committerDaniel Stenberg <daniel@haxx.se>2012-06-15 13:32:48 +0200
commit979bf951d3436bf7e86e690de26a174b39a081f8 (patch)
tree1c621aed06a24acef46f3d9eb7151bfd34384254
parent38b69b7269d4abbc75f34b8ab38d7bdab4ad91ab (diff)
downloadc-ares-979bf951d3436bf7e86e690de26a174b39a081f8.tar.gz
c-ares-979bf951d3436bf7e86e690de26a174b39a081f8.tar.bz2
c-ares-979bf951d3436bf7e86e690de26a174b39a081f8.zip
SOA parser added
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
-rw-r--r--Makefile.inc4
-rw-r--r--ares.h16
-rw-r--r--ares_data.c17
-rw-r--r--ares_data.h2
-rw-r--r--ares_free_data.38
-rw-r--r--ares_parse_soa_reply.380
-rw-r--r--ares_parse_soa_reply.c135
7 files changed, 261 insertions, 1 deletions
diff --git a/Makefile.inc b/Makefile.inc
index def54cb..ec0cba4 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -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 a4a119e..c5e4069 100644
--- 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);
diff --git a/ares_data.c b/ares_data.c
index 0e43ddd..7c04650 100644
--- a/ares_data.c
+++ b/ares_data.c
@@ -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;
diff --git a/ares_data.h b/ares_data.h
index a6acd20..fbfc496 100644
--- a/ares_data.h
+++ b/ares_data.h
@@ -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;
};
diff --git a/ares_free_data.3 b/ares_free_data.3
index c6cadd5..f8a65b9 100644
--- a/ares_free_data.3
+++ b/ares_free_data.3
@@ -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
index 0000000..1c4456f
--- /dev/null
+++ b/ares_parse_soa_reply.3
@@ -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
index 0000000..b811954
--- /dev/null
+++ b/ares_parse_soa_reply.c
@@ -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;
+}
+