4
Async resolver - SRV records parsing
7
Jakub Hrozek <jhrozek@redhat.com>
9
Copyright (C) Red Hat, Inc 2009
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 3 of the License, or
14
(at your option) any later version.
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with this program. If not, see <http://www.gnu.org/licenses/>.
26
* This code is based on other c-ares parsing licensed as follows:
28
* Copyright 1998 by the Massachusetts Institute of Technology.
30
* Permission to use, copy, modify, and distribute this
31
* software and its documentation for any purpose and without
32
* fee is hereby granted, provided that the above copyright
33
* notice appear in all copies and that both that copyright
34
* notice and this permission notice appear in supporting
35
* documentation, and that the name of M.I.T. not be used in
36
* advertising or publicity pertaining to distribution of the
37
* software without specific, written prior permission.
38
* M.I.T. makes no representations about the suitability of
39
* this software for any purpose. It is provided "as is"
40
* without express or implied warranty.
44
#include <sys/socket.h>
45
#include <netinet/in.h>
46
#include <arpa/inet.h>
48
#include <arpa/nameser.h>
52
/* this drags in some private macros c-ares uses */
54
#include "ares_data.h"
56
#include "ares_parse_srv_reply.h"
58
int _ares_parse_srv_reply (const unsigned char *abuf, int alen,
59
struct ares_srv_reply **srv_out)
61
unsigned int qdcount, ancount, i;
62
const unsigned char *aptr, *vptr;
63
int status, rr_type, rr_class, rr_len;
65
char *hostname = NULL, *rr_name = NULL;
66
struct ares_srv_reply *srv_head = NULL;
67
struct ares_srv_reply *srv_last = NULL;
68
struct ares_srv_reply *srv_curr;
70
/* Set *srv_out to NULL for all failure cases. */
73
/* Give up if abuf doesn't have room for a header. */
77
/* Fetch the question and answer count from the header. */
78
qdcount = DNS_HEADER_QDCOUNT (abuf);
79
ancount = DNS_HEADER_ANCOUNT (abuf);
85
/* Expand the name from the question, and skip past the question. */
86
aptr = abuf + HFIXEDSZ;
87
status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
88
if (status != ARES_SUCCESS)
91
if (aptr + len + QFIXEDSZ > abuf + alen)
96
aptr += len + QFIXEDSZ;
98
/* Examine each answer resource record (RR) in turn. */
99
for (i = 0; i < (int) ancount; i++)
101
/* Decode the RR up to the data field. */
102
status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
103
if (status != ARES_SUCCESS)
108
if (aptr + RRFIXEDSZ > abuf + alen)
110
status = ARES_EBADRESP;
113
rr_type = DNS_RR_TYPE (aptr);
114
rr_class = DNS_RR_CLASS (aptr);
115
rr_len = DNS_RR_LEN (aptr);
118
/* Check if we are really looking at a SRV record */
119
if (rr_class == C_IN && rr_type == T_SRV)
121
/* parse the SRV record itself */
124
status = ARES_EBADRESP;
128
/* Allocate storage for this SRV answer appending it to the list */
129
srv_curr = _ares_malloc_data(ARES_DATATYPE_SRV_REPLY);
132
status = ARES_ENOMEM;
137
srv_last->next = srv_curr;
146
srv_curr->priority = DNS__16BIT(vptr);
147
vptr += sizeof(const unsigned short);
148
srv_curr->weight = DNS__16BIT(vptr);
149
vptr += sizeof(const unsigned short);
150
srv_curr->port = DNS__16BIT(vptr);
151
vptr += sizeof(const unsigned short);
153
status = ares_expand_name (vptr, abuf, alen, &srv_curr->host, &len);
154
if (status != ARES_SUCCESS)
158
/* Don't lose memory in the next iteration */
162
/* Move on to the next record */
171
/* clean up on error */
172
if (status != ARES_SUCCESS)
175
_ares_free_data (srv_head);
179
/* everything looks fine, return the data */