- Jakub Hrozek added ares_parse_srv_reply() for SRV parsing

This commit is contained in:
Daniel Stenberg 2009-09-04 21:56:14 +00:00
parent 223c0b980b
commit 2cf0f80e9f
6 changed files with 253 additions and 2 deletions

View File

@ -1,5 +1,8 @@
Changelog for the c-ares project
* 4 Sep 2009 (Daniel Stenberg)
- Jakub Hrozek added ares_parse_srv_reply() for SRV parsing
* 3 Aug 2009 (Daniel Stenberg)
- Joshua Kwan fixed the init routine to fill in the defaults for stuff that
fails to get inited by other means. This fixes a case of when the c-ares

View File

@ -22,6 +22,7 @@ CSOURCES = ares__close_sockets.c \
ares_parse_aaaa_reply.c \
ares_parse_ns_reply.c \
ares_parse_ptr_reply.c \
ares_parse_srv_reply.c \
ares_process.c \
ares_query.c \
ares_search.c \

View File

@ -10,6 +10,7 @@ Changed:
o new ares_library_init() and ares_library_cleanup() functions
o new --enable-curldebug configure option
o ARES_ECANCELLED is now sent as reason for ares_cancel()
o added ares_parse_srv_reply()
Fixed:
@ -22,6 +23,6 @@ Fixed:
Thanks go to these friendly people for their efforts and contributions:
Phil Blundell, Japheth Cleaver, Yang Tse, Gregor Jasny, Joshua Kwan,
Timo Teras
Timo Teras, Jakub Hrozek
Have fun!

View File

@ -1,6 +1,6 @@
/* $Id$ */
/* Copyright 1998 by the Massachusetts Institute of Technology.
/* Copyright 1998, 2009 by the Massachusetts Institute of Technology.
* Copyright (C) 2007-2009 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
@ -322,6 +322,13 @@ struct addr6ttl {
int ttl;
};
struct srv_reply {
u_int16_t weight;
u_int16_t priority;
u_int16_t port;
char *host;
};
/*
** 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.
@ -339,6 +346,8 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
int addrlen, int family, struct hostent **host);
int ares_parse_ns_reply(const unsigned char *abuf, int alen,
struct hostent **host);
int ares_parse_srv_reply(const unsigned char* abuf, int alen,
struct srv_reply** srv_out, int *nsrvreply);
void ares_free_string(void *str);
void ares_free_hostent(struct hostent *host);
const char *ares_strerror(int code);

View File

@ -0,0 +1,78 @@
.\"
.\" 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_SRV_REPLY 3 "4 August 2009"
.SH NAME
ares_parse_srv_reply \- Parse a reply to a DNS query of type SRV into a
struct srv_reply
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_srv_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct srv_reply** \fIsrv_out\fP, int *\fInsrvreply\fP);
.fi
.SH DESCRIPTION
The
.B ares_parse_srv_reply
function parses the response to a query of type SRV into a
.I struct srv_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 srv_out .
The number of responses is stored into the variable pointed to by
.IR nsrvreply .
It is the caller's responsibility to free the resulting
.IR srv_out
structure when it is no longer needed.
.PP
The structure
.I srv_reply
contains the following fields:
.sp
.in +4n
.nf
struct srv_reply {
u_int16_t weight;
u_int16_t priority;
u_int16_t port;
char *host;
};
.fi
.in
.PP
.SH RETURN VALUES
.B ares_parse_srv_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 SEE ALSO
.BR ares_query (3)
.SH AUTHOR
Written by Jakub Hrozek <jhrozek@redhat.com>, on behalf of Red Hat, Inc http://www.redhat.com

159
ares/ares_parse_srv_reply.c Normal file
View File

@ -0,0 +1,159 @@
/* 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.
*/
/*
* ares_parse_srv_reply created by Jakub Hrozek <jhrozek@redhat.com>
* on behalf of Red Hat - http://www.redhat.com
*/
#include "setup.h"
#if defined(WIN32) && !defined(WATT32)
#include "nameser.h"
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#endif
#include <stdlib.h>
#include <string.h>
#include "ares.h"
#include "ares_dns.h"
#include "ares_private.h"
int
ares_parse_srv_reply (const unsigned char *abuf, int alen,
struct srv_reply **srv_out, int *nsrvreply)
{
unsigned int qdcount, ancount;
const unsigned char *aptr;
int status, i, rr_type, rr_class, rr_len;
long len;
char *hostname = NULL, *rr_name = NULL;
struct srv_reply *srv = NULL;
/* Set *srv_out to NULL for all failure cases. */
if (srv_out)
*srv_out = NULL;
/* Same with *nsrvreply. */
if (nsrvreply)
*nsrvreply = 0;
/* Give up if abuf doesn't have room for a header. */
if (alen < HFIXEDSZ)
return ARES_EBADRESP;
/* Fetch the question and answer count from the header. */
qdcount = DNS_HEADER_QDCOUNT (abuf);
ancount = DNS_HEADER_ANCOUNT (abuf);
if (qdcount != 1)
return ARES_EBADRESP;
if (ancount == 0)
return ARES_ENODATA;
/* Expand the name from the question, and skip past the question. */
aptr = abuf + HFIXEDSZ;
status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
if (status != ARES_SUCCESS)
return status;
if (aptr + len + QFIXEDSZ > abuf + alen)
{
free (hostname);
return ARES_EBADRESP;
}
aptr += len + QFIXEDSZ;
/* Allocate srv_reply array; ancount gives an upper bound */
srv = malloc ((ancount) * sizeof (struct srv_reply));
if (!srv)
{
free (hostname);
return ARES_ENOMEM;
}
/* Examine each answer resource record (RR) in turn. */
for (i = 0; i < (int) ancount; i++)
{
/* Decode the RR up to the data field. */
status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
if (status != ARES_SUCCESS)
{
break;
}
aptr += len;
if (aptr + RRFIXEDSZ > abuf + alen)
{
status = ARES_EBADRESP;
break;
}
rr_type = DNS_RR_TYPE (aptr);
rr_class = DNS_RR_CLASS (aptr);
rr_len = DNS_RR_LEN (aptr);
aptr += RRFIXEDSZ;
/* Check if we are really looking at a SRV record */
if (rr_class == C_IN && rr_type == T_SRV)
{
/* parse the SRV record itself */
if (rr_len < 6)
{
status = ARES_EBADRESP;
break;
}
srv[i].priority = ntohs (*((uint16_t *)aptr));
aptr += sizeof(uint16_t);
srv[i].weight = ntohs (*((uint16_t *)aptr));
aptr += sizeof(uint16_t);
srv[i].port = ntohs (*((uint16_t *)aptr));
aptr += sizeof(uint16_t);
status = ares_expand_name (aptr, abuf, alen, &srv[i].host, &len);
if (status != ARES_SUCCESS)
break;
/* Move on to the next record */
aptr += len;
/* Don't lose memory in the next iteration */
free (rr_name);
rr_name = NULL;
}
}
/* clean up on error */
if (status != ARES_SUCCESS)
{
free (srv);
free (hostname);
free (rr_name);
return status;
}
/* everything looks fine, return the data */
*srv_out = srv;
*nsrvreply = ancount;
free (hostname);
free (rr_name);
return status;
}