diff options
author | Stephen Gallagher <sgallagh@redhat.com> | 2010-02-18 07:49:04 -0500 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2010-02-18 13:48:45 -0500 |
commit | 1c48b5a62f73234ed26bb20f0ab345ab61cda0ab (patch) | |
tree | 0b6cddd567a862e1a7b5df23764869782a62ca78 /server/resolv | |
parent | 8c56df3176f528fe0260974b3bf934173c4651ea (diff) | |
download | sssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.tar.gz sssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.tar.bz2 sssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.zip |
Rename server/ directory to src/
Also update BUILD.txt
Diffstat (limited to 'server/resolv')
-rw-r--r-- | server/resolv/ares/ares_data.c | 140 | ||||
-rw-r--r-- | server/resolv/ares/ares_data.h | 68 | ||||
-rw-r--r-- | server/resolv/ares/ares_dns.h | 91 | ||||
-rw-r--r-- | server/resolv/ares/ares_parse_srv_reply.c | 183 | ||||
-rw-r--r-- | server/resolv/ares/ares_parse_srv_reply.h | 35 | ||||
-rw-r--r-- | server/resolv/ares/ares_parse_txt_reply.c | 204 | ||||
-rw-r--r-- | server/resolv/ares/ares_parse_txt_reply.h | 33 | ||||
-rw-r--r-- | server/resolv/async_resolv.c | 1062 | ||||
-rw-r--r-- | server/resolv/async_resolv.h | 95 |
9 files changed, 0 insertions, 1911 deletions
diff --git a/server/resolv/ares/ares_data.c b/server/resolv/ares/ares_data.c deleted file mode 100644 index 1cccaa55..00000000 --- a/server/resolv/ares/ares_data.c +++ /dev/null @@ -1,140 +0,0 @@ -/* $Id: ares_data.c,v 1.2 2009-11-20 09:06:33 yangtse Exp $ */ - -/* Copyright (C) 2009 by Daniel Stenberg - * - * 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 <stddef.h> -#include <stdlib.h> - -#include "ares.h" -#include "ares_data.h" - -/* -** ares_free_data() - c-ares external API function. -** -** This function must be used by the application to free data memory that -** has been internally allocated by some c-ares function and for which a -** pointer has already been returned to the calling application. The list -** of c-ares functions returning pointers that must be free'ed using this -** function is: -** -** ares_parse_srv_reply() -** ares_parse_txt_reply() -*/ - -void _ares_free_data(void *dataptr) -{ - struct ares_data *ptr; - - if (!dataptr) - return; - - ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data)); - - if (ptr->mark != ARES_DATATYPE_MARK) - return; - - switch (ptr->type) - { - case ARES_DATATYPE_SRV_REPLY: - - if (ptr->data.srv_reply.next) - _ares_free_data(ptr->data.srv_reply.next); - if (ptr->data.srv_reply.host) - free(ptr->data.srv_reply.host); - break; - - case ARES_DATATYPE_TXT_REPLY: - - if (ptr->data.txt_reply.next) - _ares_free_data(ptr->data.txt_reply.next); - if (ptr->data.txt_reply.txt) - free(ptr->data.txt_reply.txt); - break; - - default: - return; - } - - free(ptr); -} - - -/* -** ares_malloc_data() - c-ares internal helper function. -** -** This function allocates memory for a c-ares private ares_data struct -** for the specified ares_datatype, initializes c-ares private fields -** and zero initializes those which later might be used from the public -** API. It returns an interior pointer which can be passed by c-ares -** functions to the calling application, and that must be free'ed using -** c-ares external API function ares_free_data(). -*/ - -void *_ares_malloc_data(ares_datatype type) -{ - struct ares_data *ptr; - - ptr = malloc(sizeof(struct ares_data)); - if (!ptr) - return NULL; - - switch (type) - { - case ARES_DATATYPE_SRV_REPLY: - ptr->data.srv_reply.next = NULL; - ptr->data.srv_reply.host = NULL; - ptr->data.srv_reply.priority = 0; - ptr->data.srv_reply.weight = 0; - ptr->data.srv_reply.port = 0; - break; - - case ARES_DATATYPE_TXT_REPLY: - ptr->data.txt_reply.next = NULL; - ptr->data.txt_reply.txt = NULL; - ptr->data.txt_reply.length = 0; - break; - - default: - free(ptr); - return NULL; - } - - ptr->mark = ARES_DATATYPE_MARK; - ptr->type = type; - - return &ptr->data; -} - - -/* -** ares_get_datatype() - c-ares internal helper function. -** -** This function returns the ares_datatype of the data stored in a -** private ares_data struct when given the public API pointer. -*/ - -ares_datatype ares_get_datatype(void * dataptr) -{ - struct ares_data *ptr; - - ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data)); - - if (ptr->mark == ARES_DATATYPE_MARK) - return ptr->type; - - return ARES_DATATYPE_UNKNOWN; -} diff --git a/server/resolv/ares/ares_data.h b/server/resolv/ares/ares_data.h deleted file mode 100644 index d3606314..00000000 --- a/server/resolv/ares/ares_data.h +++ /dev/null @@ -1,68 +0,0 @@ -/* $Id: ares_data.h,v 1.2 2009-11-23 12:03:33 yangtse Exp $ */ - -/* Copyright (C) 2009 by Daniel Stenberg - * - * 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. - */ - -#ifndef HAVE_ARES_DATA -#include "resolv/ares/ares_parse_txt_reply.h" -#include "resolv/ares/ares_parse_srv_reply.h" -#endif /* HAVE_ARES_DATA */ - -typedef enum { - ARES_DATATYPE_UNKNOWN = 1, /* unknown data type - introduced in 1.7.0 */ - ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply - introduced in 1.7.0 */ - ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */ -#if 0 - ARES_DATATYPE_ADDR6TTL, /* struct ares_addrttl */ - ARES_DATATYPE_ADDRTTL, /* struct ares_addr6ttl */ - ARES_DATATYPE_HOSTENT, /* struct hostent */ - ARES_DATATYPE_OPTIONS, /* struct ares_options */ -#endif - ARES_DATATYPE_LAST /* not used - introduced in 1.7.0 */ -} ares_datatype; - -#define ARES_DATATYPE_MARK 0xbead - -/* - * ares_data struct definition is internal to c-ares and shall not - * be exposed by the public API in order to allow future changes - * and extensions to it without breaking ABI. This will be used - * internally by c-ares as the container of multiple types of data - * dynamically allocated for which a reference will be returned - * to the calling application. - * - * c-ares API functions returning a pointer to c-ares internally - * allocated data will actually be returning an interior pointer - * into this ares_data struct. - * - * All this is 'invisible' to the calling application, the only - * requirement is that this kind of data must be free'ed by the - * calling application using ares_free_data() with the pointer - * it has received from a previous c-ares function call. - */ - -struct ares_data { - ares_datatype type; /* Actual data type identifier. */ - unsigned int mark; /* Private ares_data signature. */ - union { - struct ares_txt_reply txt_reply; - struct ares_srv_reply srv_reply; - } data; -}; - -void *_ares_malloc_data(ares_datatype type); -void _ares_free_data(void *dataptr); - -ares_datatype ares_get_datatype(void * dataptr); diff --git a/server/resolv/ares/ares_dns.h b/server/resolv/ares/ares_dns.h deleted file mode 100644 index c0a9dda6..00000000 --- a/server/resolv/ares/ares_dns.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $Id: ares_dns.h,v 1.8 2007-02-16 14:22:08 yangtse Exp $ */ - -/* 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. - */ - -#ifndef ARES__DNS_H -#define ARES__DNS_H - -#define DNS__16BIT(p) (((p)[0] << 8) | (p)[1]) -#define DNS__32BIT(p) (((p)[0] << 24) | ((p)[1] << 16) | \ - ((p)[2] << 8) | (p)[3]) - -#define DNS__SET16BIT(p, v) (((p)[0] = (unsigned char)(((v) >> 8) & 0xff)), \ - ((p)[1] = (unsigned char)((v) & 0xff))) -#define DNS__SET32BIT(p, v) (((p)[0] = (unsigned char)(((v) >> 24) & 0xff)), \ - ((p)[1] = (unsigned char)(((v) >> 16) & 0xff)), \ - ((p)[2] = (unsigned char)(((v) >> 8) & 0xff)), \ - ((p)[3] = (unsigned char)((v) & 0xff))) - -#if 0 -/* we cannot use this approach on systems where we can't access 16/32 bit - data on un-aligned addresses */ -#define DNS__16BIT(p) ntohs(*(unsigned short*)(p)) -#define DNS__32BIT(p) ntohl(*(unsigned long*)(p)) -#define DNS__SET16BIT(p, v) *(unsigned short*)(p) = htons(v) -#define DNS__SET32BIT(p, v) *(unsigned long*)(p) = htonl(v) -#endif - -/* Macros for parsing a DNS header */ -#define DNS_HEADER_QID(h) DNS__16BIT(h) -#define DNS_HEADER_QR(h) (((h)[2] >> 7) & 0x1) -#define DNS_HEADER_OPCODE(h) (((h)[2] >> 3) & 0xf) -#define DNS_HEADER_AA(h) (((h)[2] >> 2) & 0x1) -#define DNS_HEADER_TC(h) (((h)[2] >> 1) & 0x1) -#define DNS_HEADER_RD(h) ((h)[2] & 0x1) -#define DNS_HEADER_RA(h) (((h)[3] >> 7) & 0x1) -#define DNS_HEADER_Z(h) (((h)[3] >> 4) & 0x7) -#define DNS_HEADER_RCODE(h) ((h)[3] & 0xf) -#define DNS_HEADER_QDCOUNT(h) DNS__16BIT((h) + 4) -#define DNS_HEADER_ANCOUNT(h) DNS__16BIT((h) + 6) -#define DNS_HEADER_NSCOUNT(h) DNS__16BIT((h) + 8) -#define DNS_HEADER_ARCOUNT(h) DNS__16BIT((h) + 10) - -/* Macros for constructing a DNS header */ -#define DNS_HEADER_SET_QID(h, v) DNS__SET16BIT(h, v) -#define DNS_HEADER_SET_QR(h, v) ((h)[2] |= (unsigned char)(((v) & 0x1) << 7)) -#define DNS_HEADER_SET_OPCODE(h, v) ((h)[2] |= (unsigned char)(((v) & 0xf) << 3)) -#define DNS_HEADER_SET_AA(h, v) ((h)[2] |= (unsigned char)(((v) & 0x1) << 2)) -#define DNS_HEADER_SET_TC(h, v) ((h)[2] |= (unsigned char)(((v) & 0x1) << 1)) -#define DNS_HEADER_SET_RD(h, v) ((h)[2] |= (unsigned char)((v) & 0x1)) -#define DNS_HEADER_SET_RA(h, v) ((h)[3] |= (unsigned char)(((v) & 0x1) << 7)) -#define DNS_HEADER_SET_Z(h, v) ((h)[3] |= (unsigned char)(((v) & 0x7) << 4)) -#define DNS_HEADER_SET_RCODE(h, v) ((h)[3] |= (unsigned char)((v) & 0xf)) -#define DNS_HEADER_SET_QDCOUNT(h, v) DNS__SET16BIT((h) + 4, v) -#define DNS_HEADER_SET_ANCOUNT(h, v) DNS__SET16BIT((h) + 6, v) -#define DNS_HEADER_SET_NSCOUNT(h, v) DNS__SET16BIT((h) + 8, v) -#define DNS_HEADER_SET_ARCOUNT(h, v) DNS__SET16BIT((h) + 10, v) - -/* Macros for parsing the fixed part of a DNS question */ -#define DNS_QUESTION_TYPE(q) DNS__16BIT(q) -#define DNS_QUESTION_CLASS(q) DNS__16BIT((q) + 2) - -/* Macros for constructing the fixed part of a DNS question */ -#define DNS_QUESTION_SET_TYPE(q, v) DNS__SET16BIT(q, v) -#define DNS_QUESTION_SET_CLASS(q, v) DNS__SET16BIT((q) + 2, v) - -/* Macros for parsing the fixed part of a DNS resource record */ -#define DNS_RR_TYPE(r) DNS__16BIT(r) -#define DNS_RR_CLASS(r) DNS__16BIT((r) + 2) -#define DNS_RR_TTL(r) DNS__32BIT((r) + 4) -#define DNS_RR_LEN(r) DNS__16BIT((r) + 8) - -/* Macros for constructing the fixed part of a DNS resource record */ -#define DNS_RR_SET_TYPE(r) DNS__SET16BIT(r, v) -#define DNS_RR_SET_CLASS(r) DNS__SET16BIT((r) + 2, v) -#define DNS_RR_SET_TTL(r) DNS__SET32BIT((r) + 4, v) -#define DNS_RR_SET_LEN(r) DNS__SET16BIT((r) + 8, v) - -#endif /* ARES__DNS_H */ diff --git a/server/resolv/ares/ares_parse_srv_reply.c b/server/resolv/ares/ares_parse_srv_reply.c deleted file mode 100644 index 086c4dba..00000000 --- a/server/resolv/ares/ares_parse_srv_reply.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - SSSD - - Async resolver - SRV records parsing - - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) Red Hat, Inc 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * This code is based on other c-ares parsing licensed as follows: - - * 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. - */ - - -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <stdlib.h> -#include <string.h> -#include "ares.h" -/* this drags in some private macros c-ares uses */ -#include "ares_dns.h" -#include "ares_data.h" - -#include "ares_parse_srv_reply.h" - -int _ares_parse_srv_reply (const unsigned char *abuf, int alen, - struct ares_srv_reply **srv_out) -{ - unsigned int qdcount, ancount, i; - const unsigned char *aptr, *vptr; - int status, rr_type, rr_class, rr_len; - long len; - char *hostname = NULL, *rr_name = NULL; - struct ares_srv_reply *srv_head = NULL; - struct ares_srv_reply *srv_last = NULL; - struct ares_srv_reply *srv_curr; - - /* Set *srv_out to NULL for all failure cases. */ - *srv_out = NULL; - - /* 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; - - /* 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; - } - - /* Allocate storage for this SRV answer appending it to the list */ - srv_curr = _ares_malloc_data(ARES_DATATYPE_SRV_REPLY); - if (!srv_curr) - { - status = ARES_ENOMEM; - break; - } - if (srv_last) - { - srv_last->next = srv_curr; - } - else - { - srv_head = srv_curr; - } - srv_last = srv_curr; - - vptr = aptr; - srv_curr->priority = ntohs (*((const unsigned short *)vptr)); - vptr += sizeof(const unsigned short); - srv_curr->weight = ntohs (*((const unsigned short *)vptr)); - vptr += sizeof(const unsigned short); - srv_curr->port = ntohs (*((const unsigned short *)vptr)); - vptr += sizeof(const unsigned short); - - status = ares_expand_name (vptr, abuf, alen, &srv_curr->host, &len); - if (status != ARES_SUCCESS) - break; - } - - /* Don't lose memory in the next iteration */ - free(rr_name); - rr_name = NULL; - - /* Move on to the next record */ - aptr += rr_len; - } - - if (hostname) - free (hostname); - if (rr_name) - free (rr_name); - - /* clean up on error */ - if (status != ARES_SUCCESS) - { - if (srv_head) - _ares_free_data (srv_head); - return status; - } - - /* everything looks fine, return the data */ - *srv_out = srv_head; - - return ARES_SUCCESS; -} diff --git a/server/resolv/ares/ares_parse_srv_reply.h b/server/resolv/ares/ares_parse_srv_reply.h deleted file mode 100644 index 29c6e08d..00000000 --- a/server/resolv/ares/ares_parse_srv_reply.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) 2009 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ARES_PARSE_SRV_REPLY_H__ -#define __ARES_PARSE_SRV_REPLY_H__ - -struct ares_srv_reply { - struct ares_srv_reply *next; - char *host; - unsigned short priority; - unsigned short weight; - unsigned short port; -}; - -int _ares_parse_srv_reply (const unsigned char *abuf, int alen, - struct ares_srv_reply **srv_out); - -#endif /* __ARES_PARSE_SRV_REPLY_H__ */ diff --git a/server/resolv/ares/ares_parse_txt_reply.c b/server/resolv/ares/ares_parse_txt_reply.c deleted file mode 100644 index d710e8f9..00000000 --- a/server/resolv/ares/ares_parse_txt_reply.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - SSSD - - Async resolver - TXT records parsing - - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) Red Hat, Inc 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * This code is based on other c-ares parsing licensed as follows: - - * 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. - */ - -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <arpa/nameser.h> -#include <stdlib.h> -#include <string.h> -#include "ares.h" -/* this drags in some private macros c-ares uses */ -#include "ares_dns.h" -#include "ares_data.h" - -#include "ares_parse_txt_reply.h" - -int _ares_parse_txt_reply (const unsigned char *abuf, int alen, - struct ares_txt_reply **txt_out) -{ - size_t substr_len, str_len; - unsigned int qdcount, ancount, i; - const unsigned char *aptr; - const unsigned char *strptr; - int status, rr_type, rr_class, rr_len; - long len; - char *hostname = NULL, *rr_name = NULL; - struct ares_txt_reply *txt_head = NULL; - struct ares_txt_reply *txt_last = NULL; - struct ares_txt_reply *txt_curr; - - /* Set *txt_out to NULL for all failure cases. */ - *txt_out = NULL; - - /* 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; - - /* 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 TXT record */ - if (rr_class == C_IN && rr_type == T_TXT) - { - /* Allocate storage for this TXT answer appending it to the list */ - txt_curr = _ares_malloc_data(ARES_DATATYPE_TXT_REPLY); - if (!txt_curr) - { - status = ARES_ENOMEM; - break; - } - if (txt_last) - { - txt_last->next = txt_curr; - } - else - { - txt_head = txt_curr; - } - txt_last = txt_curr; - - /* - * There may be multiple substrings in a single TXT record. Each - * substring may be up to 255 characters in length, with a - * "length byte" indicating the size of the substring payload. - * RDATA contains both the length-bytes and payloads of all - * substrings contained therein. - */ - - /* Compute total length to allow a single memory allocation */ - strptr = aptr; - while (strptr < (aptr + rr_len)) - { - substr_len = (unsigned char)*strptr; - txt_curr->length += substr_len; - strptr += substr_len + 1; - } - - /* Including null byte */ - txt_curr->txt = malloc (txt_curr->length + 1); - if (txt_curr->txt == NULL) - { - status = ARES_ENOMEM; - break; - } - - /* Step through the list of substrings, concatenating them */ - str_len = 0; - strptr = aptr; - while (strptr < (aptr + rr_len)) - { - substr_len = (unsigned char)*strptr; - strptr++; - memcpy ((char *) txt_curr->txt + str_len, strptr, substr_len); - str_len += substr_len; - strptr += substr_len; - } - /* Make sure we NULL-terminate */ - *((char *) txt_curr->txt + txt_curr->length) = '\0'; - } - - /* Don't lose memory in the next iteration */ - free(rr_name); - rr_name = NULL; - - /* Move on to the next record */ - aptr += rr_len; - } - - if (hostname) - free (hostname); - if (rr_name) - free (rr_name); - - /* clean up on error */ - if (status != ARES_SUCCESS) - { - if (txt_head) - _ares_free_data (txt_head); - return status; - } - - /* everything looks fine, return the data */ - *txt_out = txt_head; - - return ARES_SUCCESS; -} diff --git a/server/resolv/ares/ares_parse_txt_reply.h b/server/resolv/ares/ares_parse_txt_reply.h deleted file mode 100644 index 216e2c0d..00000000 --- a/server/resolv/ares/ares_parse_txt_reply.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) 2009 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ARES_PARSE_TXT_REPLY_H__ -#define __ARES_PARSE_TXT_REPLY_H__ - -struct ares_txt_reply { - struct ares_txt_reply *next; - unsigned char *txt; - size_t length; /* length excludes null termination */ -}; - -int _ares_parse_txt_reply(const unsigned char* abuf, int alen, - struct ares_txt_reply **txt_out); - -#endif /* __ARES_PARSE_TXT_REPLY_H__ */ diff --git a/server/resolv/async_resolv.c b/server/resolv/async_resolv.c deleted file mode 100644 index 70d8d11e..00000000 --- a/server/resolv/async_resolv.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* - SSSD - - Async resolver - - Authors: - Martin Nagy <mnagy@redhat.com> - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) Red Hat, Inc 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <sys/select.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> - -#include <ares.h> -#include <talloc.h> -#include <tevent.h> - -#include <errno.h> -#include <netdb.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> - -#include "config.h" -#include "resolv/async_resolv.h" -#include "util/dlinklist.h" -#include "util/util.h" - -#ifndef HAVE_ARES_DATA -#define ares_parse_srv_reply(abuf, alen, srv_out) \ - _ares_parse_srv_reply(abuf, alen, srv_out) -#define ares_parse_txt_reply(abuf, alen, txt_out) \ - _ares_parse_txt_reply(abuf, alen, txt_out) -#define ares_free_data(dataptr) \ - _ares_free_data(dataptr) -#define ares_malloc_data(data) \ - _ares_malloc_data(data) -#endif /* HAVE_ARES_DATA */ - -struct fd_watch { - struct fd_watch *prev; - struct fd_watch *next; - - int fd; - struct resolv_ctx *ctx; - struct tevent_fd *fde; -}; - -struct resolv_ctx { - /* Contexts are linked so we can keep track of them and re-create - * the ares channels in all of them at once if we need to. */ - struct resolv_ctx *prev; - struct resolv_ctx *next; - - struct tevent_context *ev_ctx; - ares_channel channel; - - /* List of file descriptors that are watched by tevent. */ - struct fd_watch *fds; - - /* Time in milliseconds before canceling a DNS request */ - int timeout; - - /* The timeout watcher periodically calls ares_process_fd() to check - * if our pending requests didn't timeout. */ - int pending_requests; - struct tevent_timer *timeout_watcher; -}; - -struct resolv_ctx *context_list; - -static int -return_code(int ares_code) -{ - switch (ares_code) { - case ARES_SUCCESS: - return EOK; - case ARES_ENOMEM: - return ENOMEM; - case ARES_EFILE: - default: - return EIO; - } -} - -const char * -resolv_strerror(int ares_code) -{ - return ares_strerror(ares_code); -} - -static int -fd_watch_destructor(struct fd_watch *f) -{ - DLIST_REMOVE(f->ctx->fds, f); - f->fd = -1; - - return 0; -} - -static void -fd_input_available(struct tevent_context *ev, struct tevent_fd *fde, - uint16_t flags, void *data) -{ - struct fd_watch *watch = talloc_get_type(data, struct fd_watch); - - if (watch->ctx->channel == NULL) { - DEBUG(1, ("Invalid ares channel - this is likely a bug\n")); - return; - } - - if (flags & TEVENT_FD_READ) { - ares_process_fd(watch->ctx->channel, watch->fd, ARES_SOCKET_BAD); - } - if (flags & TEVENT_FD_WRITE) { - ares_process_fd(watch->ctx->channel, ARES_SOCKET_BAD, watch->fd); - } -} - -static void -check_fd_timeouts(struct tevent_context *ev, struct tevent_timer *te, - struct timeval current_time, void *private_data); - -static void -add_timeout_timer(struct tevent_context *ev, struct resolv_ctx *ctx) -{ - struct timeval tv = { 0 }; - struct timeval *tvp; - - tvp = ares_timeout(ctx->channel, NULL, &tv); - - if (tvp == NULL) { - tvp = &tv; - } - - /* Enforce a minimum of 1 second. */ - if (tvp->tv_sec < 1) { - tv = tevent_timeval_current_ofs(1, 0); - } else { - tv = tevent_timeval_current_ofs(tvp->tv_sec, tvp->tv_usec); - } - - ctx->timeout_watcher = tevent_add_timer(ev, ctx, tv, check_fd_timeouts, - ctx); - if (ctx->timeout_watcher == NULL) { - DEBUG(1, ("Out of memory\n")); - } -} - -static void -check_fd_timeouts(struct tevent_context *ev, struct tevent_timer *te, - struct timeval current_time, void *private_data) -{ - struct resolv_ctx *ctx = talloc_get_type(private_data, struct resolv_ctx); - - DEBUG(9, ("Checking for DNS timeouts\n")); - - /* NULLify the timeout_watcher so we don't - * free it in the _done() function if it - * gets called. Now that we're already in - * the handler, tevent will take care of - * freeing it when it returns. - */ - ctx->timeout_watcher = NULL; - - ares_process_fd(ctx->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); - - if (ctx->pending_requests > 0) { - add_timeout_timer(ev, ctx); - } -} - -static void -schedule_timeout_watcher(struct tevent_context *ev, struct resolv_ctx *ctx) -{ - ctx->pending_requests++; - if (ctx->timeout_watcher) { - return; - } - - DEBUG(9, ("Scheduling DNS timeout watcher\n")); - add_timeout_timer(ev, ctx); -} - -static void -unschedule_timeout_watcher(struct resolv_ctx *ctx) -{ - if (ctx->pending_requests <= 0) { - DEBUG(1, ("Pending DNS requests mismatch\n")); - return; - } - - ctx->pending_requests--; - if (ctx->pending_requests == 0) { - DEBUG(9, ("Unscheduling DNS timeout watcher\n")); - talloc_zfree(ctx->timeout_watcher); - } -} - -static void fd_event_add(struct resolv_ctx *ctx, int s, int flags); -static void fd_event_close(struct resolv_ctx *ctx, int s); - -/* - * When ares is ready to read or write to a file descriptor, it will - * call this callback. If both read and write are 0, it means that ares - * will soon close the socket. We are mainly using this function to register - * new file descriptors with tevent. - */ -static void -fd_event(void *data, int s, int fd_read, int fd_write) -{ - struct resolv_ctx *ctx = talloc_get_type(data, struct resolv_ctx); - struct fd_watch *watch; - int flags; - - /* The socket is about to get closed. */ - if (fd_read == 0 && fd_write == 0) { - fd_event_close(ctx, s); - return; - } - - flags = fd_read ? TEVENT_FD_READ : 0; - flags |= fd_write ? TEVENT_FD_WRITE : 0; - - /* Are we already watching this file descriptor? */ - watch = ctx->fds; - while (watch) { - if (watch->fd == s) { - tevent_fd_set_flags(watch->fde, flags); - return; - } - watch = watch->next; - } - - fd_event_add(ctx, s, flags); -} - -static void -fd_event_add(struct resolv_ctx *ctx, int s, int flags) -{ - struct fd_watch *watch; - - /* The file descriptor is new, register it with tevent. */ - watch = talloc(ctx, struct fd_watch); - if (watch == NULL) { - DEBUG(1, ("Out of memory allocating fd_watch structure\n")); - return; - } - talloc_set_destructor(watch, fd_watch_destructor); - - watch->fd = s; - watch->ctx = ctx; - - watch->fde = tevent_add_fd(ctx->ev_ctx, watch, s, flags, - fd_input_available, watch); - if (watch->fde == NULL) { - DEBUG(1, ("tevent_add_fd() failed\n")); - talloc_free(watch); - return; - } - DLIST_ADD(ctx->fds, watch); -} - -static void -fd_event_close(struct resolv_ctx *ctx, int s) -{ - struct fd_watch *watch; - - /* Remove the socket from list */ - watch = ctx->fds; - while (watch) { - if (watch->fd == s) { - talloc_free(watch); - return; - } - watch = watch->next; - } -} - -static int -resolv_ctx_destructor(struct resolv_ctx *ctx) -{ - ares_channel channel; - - DLIST_REMOVE(context_list, ctx); - - if (ctx->channel == NULL) { - DEBUG(1, ("Ares channel already destroyed?\n")); - return -1; - } - - /* Set ctx->channel to NULL first, so that callbacks that get - * ARES_EDESTRUCTION won't retry. */ - channel = ctx->channel; - ctx->channel = NULL; - ares_destroy(channel); - - return 0; -} - -static int -recreate_ares_channel(struct resolv_ctx *ctx) -{ - int ret; - ares_channel new_channel; - ares_channel old_channel; - struct ares_options options; - - DEBUG(4, ("Initializing new c-ares channel\n")); - /* FIXME: the options would contain - * the nameservers to contact, the domains - * to search, timeout... => get from confdb - */ - options.sock_state_cb = fd_event; - options.sock_state_cb_data = ctx; - options.timeout = ctx->timeout * 1000; - options.tries = 1; - ret = ares_init_options(&new_channel, &options, - ARES_OPT_SOCK_STATE_CB | - ARES_OPT_TIMEOUTMS | - ARES_OPT_TRIES); - if (ret != ARES_SUCCESS) { - DEBUG(1, ("Failed to initialize ares channel: %s\n", - resolv_strerror(ret))); - return return_code(ret); - } - - old_channel = ctx->channel; - ctx->channel = new_channel; - if (old_channel != NULL) { - DEBUG(4, ("Destroying the old c-ares channel\n")); - ares_destroy(old_channel); - } - - return EOK; -} - -int -resolv_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, - int timeout, struct resolv_ctx **ctxp) -{ - int ret; - struct resolv_ctx *ctx; - - ctx = talloc_zero(mem_ctx, struct resolv_ctx); - if (ctx == NULL) - return ENOMEM; - - ctx->ev_ctx = ev_ctx; - ctx->timeout = timeout; - - ret = recreate_ares_channel(ctx); - if (ret != EOK) { - goto done; - } - - DLIST_ADD(context_list, ctx); - talloc_set_destructor(ctx, resolv_ctx_destructor); - - *ctxp = ctx; - return EOK; - -done: - talloc_free(ctx); - return ret; -} - -void -resolv_reread_configuration(void) -{ - struct resolv_ctx *ctx; - - DEBUG(4, ("Recreating all c-ares channels\n")); - DLIST_FOR_EACH(ctx, context_list) { - recreate_ares_channel(ctx); - } -} - -struct hostent * -resolv_copy_hostent(TALLOC_CTX *mem_ctx, struct hostent *src) -{ - struct hostent *ret; - int len; - int i; - - ret = talloc_zero(mem_ctx, struct hostent); - if (ret == NULL) { - return NULL; - } - - if (src->h_name != NULL) { - ret->h_name = talloc_strdup(ret, src->h_name); - if (ret->h_name == NULL) { - goto fail; - } - } - if (src->h_aliases != NULL) { - for (len = 0; src->h_aliases[len] != NULL; len++); - ret->h_aliases = talloc_size(ret, sizeof(char *) * (len + 1)); - if (ret->h_aliases == NULL) { - goto fail; - } - for (i = 0; i < len; i++) { - ret->h_aliases[i] = talloc_strdup(ret->h_aliases, src->h_aliases[i]); - if (ret->h_aliases[i] == NULL) { - goto fail; - } - } - ret->h_aliases[len] = NULL; - } - ret->h_addrtype = src->h_addrtype; - ret->h_length = src->h_length; - if (src->h_addr_list != NULL) { - for (len = 0; src->h_addr_list[len] != NULL; len++); - ret->h_addr_list = talloc_size(ret, sizeof(char *) * (len + 1)); - if (ret->h_addr_list == NULL) { - goto fail; - } - for (i = 0; i < len; i++) { - ret->h_addr_list[i] = talloc_memdup(ret->h_addr_list, - src->h_addr_list[i], - ret->h_length); - if (ret->h_addr_list[i] == NULL) { - goto fail; - } - } - ret->h_addr_list[len] = NULL; - } - - return ret; - -fail: - talloc_free(ret); - return NULL; -} - -/******************************************************************* - * Get host by name. * - *******************************************************************/ - -struct gethostbyname_state { - struct resolv_ctx *resolv_ctx; - /* Part of the query. */ - const char *name; - int family; - /* These are returned by ares. The hostent struct will be freed - * when the user callback returns. */ - struct hostent *hostent; - int status; - int timeouts; - int retrying; -}; - -static void -ares_gethostbyname_wakeup(struct tevent_req *req); - -struct tevent_req * -resolv_gethostbyname_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct resolv_ctx *ctx, const char *name) -{ - struct tevent_req *req, *subreq; - struct gethostbyname_state *state; - struct timeval tv = { 0, 0 }; - - DEBUG(4, ("Trying to resolve A record of '%s'\n", name)); - - if (ctx->channel == NULL) { - DEBUG(1, ("Invalid ares channel - this is likely a bug\n")); - return NULL; - } - - req = tevent_req_create(mem_ctx, &state, struct gethostbyname_state); - if (req == NULL) - return NULL; - - state->resolv_ctx = ctx; - state->name = name; - state->family = AF_INET; - state->hostent = NULL; - state->status = 0; - state->timeouts = 0; - state->retrying = 0; - - /* We need to have a wrapper around ares_gethostbyname(), because - * ares_gethostbyname() can in some cases call it's callback immediately. - * This would not let our caller to set a callback for req. */ - subreq = tevent_wakeup_send(req, ev, tv); - if (subreq == NULL) { - DEBUG(1, ("Failed to add critical timer to run next operation!\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, ares_gethostbyname_wakeup, req); - schedule_timeout_watcher(ev, ctx); - - return req; -} - -static void -resolv_gethostbyname6_done(void *arg, int status, int timeouts, struct hostent *hostent); - -static void -resolv_gethostbyname_done(void *arg, int status, int timeouts, struct hostent *hostent) -{ - struct tevent_req *req = talloc_get_type(arg, struct tevent_req); - struct gethostbyname_state *state = tevent_req_data(req, struct gethostbyname_state); - - if (state->retrying == 0 && status == ARES_EDESTRUCTION - && state->resolv_ctx->channel != NULL) { - state->retrying = 1; - ares_gethostbyname(state->resolv_ctx->channel, state->name, - state->family, resolv_gethostbyname_done, req); - return; - } - - unschedule_timeout_watcher(state->resolv_ctx); - - if (hostent != NULL) { - state->hostent = resolv_copy_hostent(req, hostent); - if (state->hostent == NULL) { - tevent_req_error(req, ENOMEM); - return; - } - } else { - state->hostent = NULL; - } - state->status = status; - state->timeouts = timeouts; - - if (status != ARES_SUCCESS) { - if (status == ARES_ENOTFOUND || status == ARES_ENODATA) { - /* IPv4 failure. Try IPv6 */ - state->family = AF_INET6; - state->retrying = 0; - state->timeouts = 0; - DEBUG(4, ("Trying to resolve AAAA record of '%s'\n", - state->name)); - ares_gethostbyname(state->resolv_ctx->channel, state->name, - state->family, resolv_gethostbyname6_done, - req); - return; - } - - /* Any other error indicates a server error, - * so don't bother trying again - */ - tevent_req_error(req, return_code(status)); - } - else { - tevent_req_done(req); - } -} - -static void -resolv_gethostbyname6_done(void *arg, int status, int timeouts, struct hostent *hostent) -{ - struct tevent_req *req = talloc_get_type(arg, struct tevent_req); - struct gethostbyname_state *state = tevent_req_data(req, struct gethostbyname_state); - - if (state->retrying == 0 && status == ARES_EDESTRUCTION) { - state->retrying = 1; - ares_gethostbyname(state->resolv_ctx->channel, state->name, - state->family, resolv_gethostbyname6_done, req); - return; - } - - if (hostent != NULL) { - state->hostent = resolv_copy_hostent(req, hostent); - if (state->hostent == NULL) { - tevent_req_error(req, ENOMEM); - return; - } - } else { - state->hostent = NULL; - } - state->status = status; - state->timeouts = timeouts; - - if (status != ARES_SUCCESS) { - tevent_req_error(req, return_code(status)); - } - else { - tevent_req_done(req); - } -} - -int -resolv_gethostbyname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - int *status, int *timeouts, - struct hostent **hostent) -{ - struct gethostbyname_state *state = tevent_req_data(req, struct gethostbyname_state); - - /* Fill in even in case of error as status contains the - * c-ares return code */ - if (status) { - *status = state->status; - } - if (timeouts) { - *timeouts = state->timeouts; - } - if (hostent) { - *hostent = talloc_steal(mem_ctx, state->hostent); - } - - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -static void -ares_gethostbyname_wakeup(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct gethostbyname_state *state = tevent_req_data(req, - struct gethostbyname_state); - - if (!tevent_wakeup_recv(subreq)) { - return; - } - talloc_zfree(subreq); - - if (state->resolv_ctx->channel == NULL) { - DEBUG(1, ("Invalid ares channel - this is likely a bug\n")); - tevent_req_error(req, EIO); - return; - } - - ares_gethostbyname(state->resolv_ctx->channel, state->name, - state->family, resolv_gethostbyname_done, req); -} - -/* SRV and TXT parsing is not used anywhere in the code yet, so we disable it - * for now - */ -#ifdef BUILD_TXT_SRV - -/* - * A simple helper function that will take an array of struct ares_srv_reply that - * was allocated by malloc() in c-ares and copies it using talloc. The old one - * is freed and the talloc one is put into 'reply_list' instead. - */ -static int -rewrite_talloc_srv_reply(TALLOC_CTX *mem_ctx, struct ares_srv_reply **reply_list) -{ - struct ares_srv_reply *ptr = NULL; - struct ares_srv_reply *new_list = NULL; - struct ares_srv_reply *old_list = *reply_list; - - /* Nothing to do, but not an error */ - if (!old_list) { - return EOK; - } - - /* Copy the linked list */ - while (old_list) { - /* Special case for the first node */ - if (!new_list) { - new_list = talloc_zero(mem_ctx, struct ares_srv_reply); - if (new_list == NULL) { - ares_free_data(*reply_list); - return ENOMEM; - } - ptr = new_list; - } else { - ptr->next = talloc_zero(new_list, struct ares_srv_reply); - if (ptr->next == NULL) { - ares_free_data(*reply_list); - talloc_free(new_list); - return ENOMEM; - } - ptr = ptr->next; - } - - ptr->weight = old_list->weight; - ptr->priority = old_list->priority; - ptr->port = old_list->port; - ptr->host = talloc_strdup(ptr, old_list->host); - if (ptr->host == NULL) { - ares_free_data(*reply_list); - talloc_free(new_list); - return ENOMEM; - } - - old_list = old_list->next; - } - - /* Free the old one (uses malloc). */ - ares_free_data(*reply_list); - - /* And now put our own new_list in place. */ - *reply_list = new_list; - - return EOK; -} - -/******************************************************************* - * Get SRV record * - *******************************************************************/ - -struct getsrv_state { - struct resolv_ctx *resolv_ctx; - /* the SRV query - for example _ldap._tcp.example.com */ - const char *query; - - /* parsed data returned by ares */ - struct ares_srv_reply *reply_list; - int status; - int timeouts; - int retrying; -}; - -static void -ares_getsrv_wakeup(struct tevent_req *subreq); - -struct tevent_req * -resolv_getsrv_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct resolv_ctx *ctx, const char *query) -{ - struct tevent_req *req, *subreq; - struct getsrv_state *state; - struct timeval tv = { 0, 0 }; - - DEBUG(4, ("Trying to resolve SRV record of '%s'\n", query)); - - if (ctx->channel == NULL) { - DEBUG(1, ("Invalid ares channel - this is likely a bug\n")); - return NULL; - } - - req = tevent_req_create(mem_ctx, &state, struct getsrv_state); - if (req == NULL) - return NULL; - - state->resolv_ctx = ctx; - state->query = query; - state->reply_list = NULL; - state->status = 0; - state->timeouts = 0; - state->retrying = 0; - - subreq = tevent_wakeup_send(req, ev, tv); - if (subreq == NULL) { - DEBUG(1, ("Failed to add critical timer to run next operation!\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, ares_getsrv_wakeup, req); - schedule_timeout_watcher(ev, ctx); - - return req; -} - -static void -resolv_getsrv_done(void *arg, int status, int timeouts, unsigned char *abuf, int alen) -{ - struct tevent_req *req = talloc_get_type(arg, struct tevent_req); - struct getsrv_state *state = tevent_req_data(req, struct getsrv_state); - int ret; - struct ares_srv_reply *reply_list; - - if (state->retrying == 0 && status == ARES_EDESTRUCTION - && state->resolv_ctx->channel != NULL) { - state->retrying = 1; - ares_query(state->resolv_ctx->channel, state->query, - ns_c_in, ns_t_srv, resolv_getsrv_done, req); - return; - } - - unschedule_timeout_watcher(state->resolv_ctx); - - state->status = status; - state->timeouts = timeouts; - - if (status != ARES_SUCCESS) { - tevent_req_error(req, return_code(status)); - ret = return_code(status); - goto fail; - } - - ret = ares_parse_srv_reply(abuf, alen, &reply_list); - if (status != ARES_SUCCESS) { - DEBUG(2, ("SRV record parsing failed: %d: %s\n", ret, ares_strerror(ret))); - ret = return_code(ret); - goto fail; - } - ret = rewrite_talloc_srv_reply(req, &reply_list); - if (ret != EOK) { - goto fail; - } - state->reply_list = reply_list; - - tevent_req_done(req); - return; - -fail: - state->reply_list = NULL; - tevent_req_error(req, ret); -} - -int -resolv_getsrv_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, int *status, - int *timeouts, struct ares_srv_reply **reply_list) -{ - struct getsrv_state *state = tevent_req_data(req, struct getsrv_state); - - if (status) - *status = state->status; - if (timeouts) - *timeouts = state->timeouts; - if (reply_list) - *reply_list = talloc_steal(mem_ctx, state->reply_list); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -static void -ares_getsrv_wakeup(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct getsrv_state *state = tevent_req_data(req, - struct getsrv_state); - - if (!tevent_wakeup_recv(subreq)) { - return; - } - talloc_zfree(subreq); - - if (state->resolv_ctx->channel == NULL) { - DEBUG(1, ("Invalid ares channel - this is likely a bug\n")); - tevent_req_error(req, EIO); - return; - } - - ares_query(state->resolv_ctx->channel, state->query, - ns_c_in, ns_t_srv, resolv_getsrv_done, req); -} - -/* - * A simple helper function that will take an array of struct txt_reply that - * was allocated by malloc() in c-ares and copies it using talloc. The old one - * is freed and the talloc one is put into 'reply_list' instead. - */ -static int -rewrite_talloc_txt_reply(TALLOC_CTX *mem_ctx, struct ares_txt_reply **reply_list) -{ - struct ares_txt_reply *ptr = NULL; - struct ares_txt_reply *new_list = NULL; - struct ares_txt_reply *old_list = *reply_list; - - /* Nothing to do, but not an error */ - if (!old_list) { - return EOK; - } - - /* Copy the linked list */ - while (old_list) { - - /* Special case for the first node */ - if (!new_list) { - new_list = talloc_zero(mem_ctx, struct ares_txt_reply); - if (new_list == NULL) { - ares_free_data(*reply_list); - talloc_free(new_list); - return ENOMEM; - } - ptr = new_list; - } else { - ptr->next = talloc_zero(new_list, struct ares_txt_reply); - if (ptr->next == NULL) { - ares_free_data(*reply_list); - talloc_free(new_list); - return ENOMEM; - } - ptr = ptr->next; - } - - ptr->length = old_list->length; - ptr->txt = talloc_memdup(ptr, old_list->txt, - old_list->length); - if (ptr->txt == NULL) { - ares_free_data(*reply_list); - talloc_free(new_list); - return ENOMEM; - } - - old_list = old_list->next; - } - - ares_free_data(*reply_list); - - /* And now put our own new_list in place. */ - *reply_list = new_list; - - return EOK; -} - -/******************************************************************* - * Get TXT record * - *******************************************************************/ - -struct gettxt_state { - struct resolv_ctx *resolv_ctx; - /* the TXT query */ - const char *query; - - /* parsed data returned by ares */ - struct ares_txt_reply *reply_list; - int status; - int timeouts; - int retrying; -}; - -static void -ares_gettxt_wakeup(struct tevent_req *subreq); - -struct tevent_req * -resolv_gettxt_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct resolv_ctx *ctx, const char *query) -{ - struct tevent_req *req, *subreq; - struct gettxt_state *state; - struct timeval tv = { 0, 0 }; - - DEBUG(4, ("Trying to resolve TXT record of '%s'\n", query)); - - if (ctx->channel == NULL) { - DEBUG(1, ("Invalid ares channel - this is likely a bug\n")); - return NULL; - } - - req = tevent_req_create(mem_ctx, &state, struct gettxt_state); - if (req == NULL) - return NULL; - - state->resolv_ctx = ctx; - state->query = query; - state->reply_list = NULL; - state->status = 0; - state->timeouts = 0; - state->retrying = 0; - - subreq = tevent_wakeup_send(req, ev, tv); - if (subreq == NULL) { - DEBUG(1, ("Failed to add critical timer to run next operation!\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, ares_gettxt_wakeup, req); - schedule_timeout_watcher(ev, ctx); - - return req; -} - -static void -resolv_gettxt_done(void *arg, int status, int timeouts, unsigned char *abuf, int alen) -{ - struct tevent_req *req = talloc_get_type(arg, struct tevent_req); - struct gettxt_state *state = tevent_req_data(req, struct gettxt_state); - int ret; - struct ares_txt_reply *reply_list; - - if (state->retrying == 0 && status == ARES_EDESTRUCTION - && state->resolv_ctx->channel != NULL) { - state->retrying = 1; - ares_query(state->resolv_ctx->channel, state->query, - ns_c_in, ns_t_txt, resolv_gettxt_done, req); - return; - } - - unschedule_timeout_watcher(state->resolv_ctx); - - state->status = status; - state->timeouts = timeouts; - - if (status != ARES_SUCCESS) { - ret = return_code(status); - goto fail; - } - - ret = ares_parse_txt_reply(abuf, alen, &reply_list); - if (status != ARES_SUCCESS) { - DEBUG(2, ("TXT record parsing failed: %d: %s\n", ret, ares_strerror(ret))); - ret = return_code(ret); - goto fail; - } - ret = rewrite_talloc_txt_reply(req, &reply_list); - if (ret != EOK) { - goto fail; - } - state->reply_list = reply_list; - - tevent_req_done(req); - return; - -fail: - state->reply_list = NULL; - tevent_req_error(req, ret); -} - -int -resolv_gettxt_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, int *status, - int *timeouts, struct ares_txt_reply **reply_list) -{ - struct gettxt_state *state = tevent_req_data(req, struct gettxt_state); - - if (status) - *status = state->status; - if (timeouts) - *timeouts = state->timeouts; - if (reply_list) - *reply_list = talloc_steal(mem_ctx, state->reply_list); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -static void -ares_gettxt_wakeup(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct gettxt_state *state = tevent_req_data(req, - struct gettxt_state); - - if (!tevent_wakeup_recv(subreq)) { - return; - } - talloc_zfree(subreq); - - if (state->resolv_ctx->channel == NULL) { - DEBUG(1, ("Invalid ares channel - this is likely a bug\n")); - tevent_req_error(req, EIO); - return; - } - - ares_query(state->resolv_ctx->channel, state->query, - ns_c_in, ns_t_txt, resolv_gettxt_done, req); -} - -#endif diff --git a/server/resolv/async_resolv.h b/server/resolv/async_resolv.h deleted file mode 100644 index 2ba6449b..00000000 --- a/server/resolv/async_resolv.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - SSSD - - Async resolver header - - Authors: - Martin Nagy <mnagy@redhat.com> - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) Red Hat, Inc 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ASYNC_RESOLV_H__ -#define __ASYNC_RESOLV_H__ - -#include <netdb.h> -#include <ares.h> - -#include "config.h" - -#ifndef HAVE_ARES_DATA -#include "resolv/ares/ares_parse_srv_reply.h" -#include "resolv/ares/ares_parse_txt_reply.h" -#include "resolv/ares/ares_data.h" -#endif /* HAVE_ARES_DATA */ - -/* - * An opaque structure which holds context for a module using the async - * resolver. Is should be used as a "local-global" variable - in sssd, - * every backend should have its own. - - * Do NOT free the context until there are any pending resolv_ calls - */ -struct resolv_ctx; - -int resolv_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, - int timeout, struct resolv_ctx **ctxp); - -void resolv_reread_configuration(void); - -const char *resolv_strerror(int ares_code); - -struct hostent *resolv_copy_hostent(TALLOC_CTX *mem_ctx, - struct hostent *src); - -/** Get host by name **/ -struct tevent_req *resolv_gethostbyname_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct resolv_ctx *ctx, - const char *name); - -int resolv_gethostbyname_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - int *status, - int *timeouts, - struct hostent **hostent); - -/** Get SRV record **/ -struct tevent_req *resolv_getsrv_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct resolv_ctx *ctx, - const char *query); - -int resolv_getsrv_recv(TALLOC_CTX *mem_ctx, - struct tevent_req *req, - int *status, - int *timeouts, - struct ares_srv_reply **reply_list); - -/** Get TXT record **/ -struct tevent_req *resolv_gettxt_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct resolv_ctx *ctx, - const char *query); - -int resolv_gettxt_recv(TALLOC_CTX *mem_ctx, - struct tevent_req *req, - int *status, - int *timeouts, - struct ares_txt_reply **reply_list); - -#endif /* __ASYNC_RESOLV_H__ */ |