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
This commit is contained in:
Marko Kreen 2012-06-15 13:29:03 +02:00 committed by Daniel Stenberg
parent 38b69b7269
commit 979bf951d3
7 changed files with 261 additions and 1 deletions

View 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 \

16
ares.h
View File

@ -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);

View 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;

View 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;
};

View 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

80
ares_parse_soa_reply.3 Normal file
View File

@ -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)

135
ares_parse_soa_reply.c Normal file
View File

@ -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;
}