| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-01-05 09:40:22 +00:00
										 |  |  |  * Copyright (C) 1999 - 2006 Thorsten Lockert | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Written by Thorsten Lockert <tholo@trollphone.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Funding provided by Troll Phone Networks AS | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief DNS Support for Asterisk | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \author Thorsten Lockert <tholo@trollphone.org> | 
					
						
							| 
									
										
										
										
											2006-04-05 13:53:06 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \par Reference | 
					
						
							|  |  |  |  * - DNR SRV records http://www.ietf.org/rfc/rfc2782.txt
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-15 16:20:16 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<support_level>core</support_level> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-17 14:45:46 +00:00
										 |  |  | #include "asterisk/network.h"
 | 
					
						
							|  |  |  | #include <arpa/nameser.h>	/* res_* functions */
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | #include <resolv.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/dns.h"
 | 
					
						
							|  |  |  | #include "asterisk/endian.h"
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | /*! \brief The maximum size permitted for the answer from the DNS server */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | #define MAX_SIZE 4096
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-21 01:05:26 +00:00
										 |  |  | #ifdef __PDP_ENDIAN
 | 
					
						
							|  |  |  | #if __BYTE_ORDER == __PDP_ENDIAN
 | 
					
						
							|  |  |  | #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if __BYTE_ORDER == __BIG_ENDIAN
 | 
					
						
							|  |  |  | #define DETERMINED_BYTE_ORDER __BIG_ENDIAN
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
					
						
							|  |  |  | #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | #ifndef HAVE_RES_NINIT
 | 
					
						
							|  |  |  | AST_MUTEX_DEFINE_STATIC(res_lock); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-16 20:58:56 +00:00
										 |  |  | /* The dns_HEADER structure definition below originated
 | 
					
						
							|  |  |  |    in the arpa/nameser.h header file distributed with ISC | 
					
						
							|  |  |  |    BIND, which contains the following copyright and license | 
					
						
							|  |  |  |    notices: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * ++Copyright++ 1983, 1989, 1993 | 
					
						
							|  |  |  |  * - | 
					
						
							|  |  |  |  * Copyright (c) 1983, 1989, 1993 | 
					
						
							|  |  |  |  *    The Regents of the University of California.  All rights reserved. | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-16 20:58:56 +00:00
										 |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |  * are met: | 
					
						
							|  |  |  |  * 1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |  *    notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * 2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |  *    notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |  *    documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * 3. All advertising materials mentioning features or use of this software | 
					
						
							|  |  |  |  *    must display the following acknowledgement: | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  |  *	This product includes software developed by the University of | 
					
						
							|  |  |  |  *	California, Berkeley and its contributors. | 
					
						
							| 
									
										
										
										
											2007-07-16 20:58:56 +00:00
										 |  |  |  * 4. Neither the name of the University nor the names of its contributors | 
					
						
							|  |  |  |  *    may be used to endorse or promote products derived from this software | 
					
						
							|  |  |  |  *    without specific prior written permission. | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-16 20:58:56 +00:00
										 |  |  |  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 
					
						
							|  |  |  |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
					
						
							|  |  |  |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
					
						
							|  |  |  |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
					
						
							|  |  |  |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
					
						
							|  |  |  |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
					
						
							|  |  |  |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
					
						
							|  |  |  |  * SUCH DAMAGE. | 
					
						
							|  |  |  |  * - | 
					
						
							|  |  |  |  * Portions Copyright (c) 1993 by Digital Equipment Corporation. | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-16 20:58:56 +00:00
										 |  |  |  * Permission to use, copy, modify, and distribute this software for any | 
					
						
							|  |  |  |  * purpose with or without fee is hereby granted, provided that the above | 
					
						
							|  |  |  |  * copyright notice and this permission notice appear in all copies, and that | 
					
						
							|  |  |  |  * the name of Digital Equipment Corporation not be used in advertising or | 
					
						
							|  |  |  |  * publicity pertaining to distribution of the document or software without | 
					
						
							|  |  |  |  * specific, written prior permission. | 
					
						
							| 
									
										
										
										
											2012-03-22 19:51:16 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-16 20:58:56 +00:00
										 |  |  |  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL | 
					
						
							|  |  |  |  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES | 
					
						
							|  |  |  |  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT | 
					
						
							|  |  |  |  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR | 
					
						
							|  |  |  |  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | 
					
						
							|  |  |  |  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | 
					
						
							|  |  |  |  * SOFTWARE. | 
					
						
							|  |  |  |  * - | 
					
						
							|  |  |  |  * --Copyright-- | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	unsigned	id:16;          /*!< query identification number */ | 
					
						
							| 
									
										
										
										
											2007-02-21 01:05:26 +00:00
										 |  |  | #if DETERMINED_BYTE_ORDER == __BIG_ENDIAN
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			/* fields in third byte */ | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	unsigned	qr:1;           /*!< response flag */ | 
					
						
							|  |  |  | 	unsigned	opcode:4;       /*!< purpose of message */ | 
					
						
							| 
									
										
										
										
											2021-10-30 21:04:30 -04:00
										 |  |  | 	unsigned	aa:1;           /*!< authoritative answer */ | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	unsigned	tc:1;           /*!< truncated message */ | 
					
						
							|  |  |  | 	unsigned	rd:1;           /*!< recursion desired */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			/* fields in fourth byte */ | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	unsigned	ra:1;           /*!< recursion available */ | 
					
						
							|  |  |  | 	unsigned	unused:1;       /*!< unused bits (MBZ as of 4.9.3a3) */ | 
					
						
							|  |  |  | 	unsigned	ad:1;           /*!< authentic data from named */ | 
					
						
							|  |  |  | 	unsigned	cd:1;           /*!< checking disabled by resolver */ | 
					
						
							|  |  |  | 	unsigned	rcode:4;        /*!< response code */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-02-21 01:05:26 +00:00
										 |  |  | #if DETERMINED_BYTE_ORDER == __LITTLE_ENDIAN
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			/* fields in third byte */ | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	unsigned	rd:1;           /*!< recursion desired */ | 
					
						
							|  |  |  | 	unsigned	tc:1;           /*!< truncated message */ | 
					
						
							| 
									
										
										
										
											2021-10-30 21:04:30 -04:00
										 |  |  | 	unsigned	aa:1;           /*!< authoritative answer */ | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	unsigned	opcode:4;       /*!< purpose of message */ | 
					
						
							|  |  |  | 	unsigned	qr:1;           /*!< response flag */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			/* fields in fourth byte */ | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	unsigned	rcode:4;        /*!< response code */ | 
					
						
							|  |  |  | 	unsigned	cd:1;           /*!< checking disabled by resolver */ | 
					
						
							|  |  |  | 	unsigned	ad:1;           /*!< authentic data from named */ | 
					
						
							|  |  |  | 	unsigned	unused:1;       /*!< unused bits (MBZ as of 4.9.3a3) */ | 
					
						
							|  |  |  | 	unsigned	ra:1;           /*!< recursion available */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 			/* remaining bytes */ | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	unsigned	qdcount:16;     /*!< number of question entries */ | 
					
						
							|  |  |  | 	unsigned	ancount:16;     /*!< number of answer entries */ | 
					
						
							|  |  |  | 	unsigned	nscount:16;     /*!< number of authority entries */ | 
					
						
							|  |  |  | 	unsigned	arcount:16;     /*!< number of resource entries */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | } dns_HEADER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct dn_answer { | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 	unsigned short rtype;       /*!< The resource record type. */ | 
					
						
							|  |  |  | 	unsigned short class;       /*!< The resource record class. */ | 
					
						
							|  |  |  | 	unsigned int ttl;           /*!< The resource record time to live. */ | 
					
						
							|  |  |  | 	unsigned short size;        /*!< The resource record size. */ | 
					
						
							| 
									
										
										
										
											2008-11-29 17:57:39 +00:00
										 |  |  | } __attribute__((__packed__)); | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Tries to find the position of the next field in the DNS response. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param  s    A char pointer to the current frame in the DNS response. | 
					
						
							|  |  |  |  * \param  len  The remaining available length of the DNS response. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-11-19 16:47:25 +01:00
										 |  |  |  * \return The position of the next field | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  |  * \retval -1 if there are no remaining fields | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-07-07 06:55:48 +00:00
										 |  |  | static int skip_name(unsigned char *s, int len) | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int x = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (x < len) { | 
					
						
							|  |  |  | 		if (*s == '\0') { | 
					
						
							|  |  |  | 			s++; | 
					
						
							|  |  |  | 			x++; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 		if ((*s & 0xc0) == 0xc0) { | 
					
						
							|  |  |  | 			s += 2; | 
					
						
							|  |  |  | 			x += 2; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 		x += *s + 1; | 
					
						
							|  |  |  | 		s += *s + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* If we are out of room to search, return failure. */ | 
					
						
							|  |  |  | 	if (x >= len) { | 
					
						
							|  |  |  | 		return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Return the value for the current position in the DNS response. This is the start
 | 
					
						
							|  |  |  | 	position of the next field. */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Advances the position of the DNS response pointer by the size of the current field. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param  dns_response   A pointer to a char pointer to the current field in the DNS response. | 
					
						
							|  |  |  |  * \param  remaining_len  The remaining available length in the DNS response to search. | 
					
						
							|  |  |  |  * \param  field_size     A positive value representing the size of the current field | 
					
						
							|  |  |  |                           pointed to by the dns_response parameter. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-11-19 16:47:25 +01:00
										 |  |  |  * \return The remaining length in the DNS response | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  |  * \retval -1 there are no frames remaining in the DNS response | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int dns_advance_field(unsigned char **dns_response, int remaining_len, int field_size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (dns_response == NULL || field_size < 0 || remaining_len < field_size) { | 
					
						
							|  |  |  | 		return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*dns_response += field_size; | 
					
						
							|  |  |  | 	remaining_len -= field_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return remaining_len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef HAVE_RES_NINIT
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Handles the DNS search if the system has RES_INIT. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param  dname             Domain name to lookup (host, SRV domain, TXT record name). | 
					
						
							|  |  |  |  * \param  rr_class          Record Class (see "man res_search"). | 
					
						
							|  |  |  |  * \param  rr_type           Record type (see "man res_search"). | 
					
						
							|  |  |  |  * \param  dns_response      The full DNS response. | 
					
						
							|  |  |  |  * \param  dns_response_len  The length of the full DNS response. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-11-19 16:47:25 +01:00
										 |  |  |  * \return The length of the DNS response | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  |  * \retval -1 on search failure | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int dns_search_res(const char *dname, int rr_class, int rr_type, | 
					
						
							|  |  |  | 	unsigned char *dns_response, int dns_response_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int ret = AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&res_lock); | 
					
						
							|  |  |  | 	res_init(); | 
					
						
							| 
									
										
										
										
											2016-06-02 22:57:49 +03:00
										 |  |  | 	ret = res_search(dname, | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 	                 rr_class, | 
					
						
							|  |  |  | 	                 rr_type, | 
					
						
							|  |  |  | 	                 dns_response, | 
					
						
							|  |  |  | 	                 dns_response_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_RES_CLOSE
 | 
					
						
							|  |  |  | 	res_close(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&res_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Handles the DNS search if the system has RES_NINIT. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param  dname             Domain name to lookup (host, SRV domain, TXT record name). | 
					
						
							|  |  |  |  * \param  rr_class          Record Class (see "man res_search"). | 
					
						
							|  |  |  |  * \param  rr_type           Record type (see "man res_search"). | 
					
						
							|  |  |  |  * \param  dns_response      The full DNS response. | 
					
						
							|  |  |  |  * \param  dns_response_len  The length of the full DNS response. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-11-19 16:47:25 +01:00
										 |  |  |  * \return The length of the DNS response | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  |  * \retval -1 on search failure | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int dns_search_res(const char *dname, int rr_class, int rr_type, | 
					
						
							|  |  |  | 	unsigned char *dns_response, int dns_response_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int ret = AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 	struct __res_state dns_state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(&dns_state, 0, sizeof(dns_state)); | 
					
						
							|  |  |  | 	res_ninit(&dns_state); | 
					
						
							|  |  |  | 	ret = res_nsearch(&dns_state, | 
					
						
							|  |  |  | 	                  dname, | 
					
						
							|  |  |  | 	                  rr_class, | 
					
						
							|  |  |  | 	                  rr_type, | 
					
						
							|  |  |  | 	                  dns_response, | 
					
						
							|  |  |  | 	                  dns_response_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_RES_NDESTROY
 | 
					
						
							|  |  |  | 	res_ndestroy(&dns_state); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	res_nclose(&dns_state); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Parse DNS lookup result, call callback | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param  context   Void pointer containing data to use in the callback functions. | 
					
						
							|  |  |  |  * \param  class     Record Class (see "man res_search"). | 
					
						
							|  |  |  |  * \param  type      Record type (see "man res_search"). | 
					
						
							|  |  |  |  * \param  answer    The full DNS response. | 
					
						
							|  |  |  |  * \param  len       The length of the full DNS response. | 
					
						
							|  |  |  |  * \param  callback  Callback function for handling the discovered resource records from the DNS search. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \retval -1 on search failure | 
					
						
							|  |  |  |  * \retval  0 on no records found | 
					
						
							|  |  |  |  * \retval  1 on success | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | static int dns_parse_answer(void *context, | 
					
						
							| 
									
										
										
										
											2006-07-07 06:55:48 +00:00
										 |  |  | 	int class, int type, unsigned char *answer, int len, | 
					
						
							|  |  |  | 	int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer)) | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-07-07 06:55:48 +00:00
										 |  |  | 	unsigned char *fullanswer = answer; | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	struct dn_answer *ans; | 
					
						
							|  |  |  | 	dns_HEADER *h; | 
					
						
							| 
									
										
										
										
											2008-07-08 21:00:01 +00:00
										 |  |  | 	int ret = 0; | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	int res; | 
					
						
							|  |  |  | 	int x; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-22 20:11:15 +00:00
										 |  |  | 	h = (dns_HEADER *)answer; | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	answer += sizeof(dns_HEADER); | 
					
						
							|  |  |  | 	len -= sizeof(dns_HEADER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (x = 0; x < ntohs(h->qdcount); x++) { | 
					
						
							|  |  |  | 		if ((res = skip_name(answer, len)) < 0) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Couldn't skip over name\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		answer += res + 4;	/* Skip name and QCODE / QCLASS */ | 
					
						
							|  |  |  | 		len -= res + 4; | 
					
						
							|  |  |  | 		if (len < 0) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Strange query size\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (x = 0; x < ntohs(h->ancount); x++) { | 
					
						
							|  |  |  | 		if ((res = skip_name(answer, len)) < 0) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Failed skipping name\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		answer += res; | 
					
						
							|  |  |  | 		len -= res; | 
					
						
							|  |  |  | 		ans = (struct dn_answer *)answer; | 
					
						
							|  |  |  | 		answer += sizeof(struct dn_answer); | 
					
						
							|  |  |  | 		len -= sizeof(struct dn_answer); | 
					
						
							|  |  |  | 		if (len < 0) { | 
					
						
							| 
									
										
										
										
											2013-07-14 02:05:04 +00:00
										 |  |  | 			ast_log(LOG_WARNING, "Length of DNS answer exceeds frame\n"); | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) { | 
					
						
							|  |  |  | 			if (callback) { | 
					
						
							| 
									
										
										
										
											2004-03-03 03:12:59 +00:00
										 |  |  | 				if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) { | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 					ast_log(LOG_WARNING, "Failed to parse result\n"); | 
					
						
							| 
									
										
										
										
											2004-03-03 03:12:59 +00:00
										 |  |  | 					return -1; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-07-08 21:00:01 +00:00
										 |  |  | 				ret = 1; | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		answer += ntohs(ans->size); | 
					
						
							|  |  |  | 		len -= ntohs(ans->size); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 21:00:01 +00:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Extended version of the DNS Parsing function. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \details Parses the DNS lookup result and notifies the observer of each discovered | 
					
						
							|  |  |  |  *          resource record with the provided callback. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param  context           Void pointer containing data to use in the callback functions. | 
					
						
							|  |  |  |  * \param  rr_class          Record Class (see "man res_search"). | 
					
						
							|  |  |  |  * \param  rr_type           Record type (see "man res_search"). | 
					
						
							|  |  |  |  * \param  answer            The full DNS response. | 
					
						
							|  |  |  |  * \param  answer_len        The length of the full DNS response. | 
					
						
							|  |  |  |  * \param  response_handler  Callback function for handling the DNS response. | 
					
						
							|  |  |  |  * \param  record_handler    Callback function for handling the discovered resource records from the DNS search. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \retval -1 on search failure | 
					
						
							|  |  |  |  * \retval  0 on no records found | 
					
						
							|  |  |  |  * \retval  1 on success | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int dns_parse_answer_ex(void *context, int rr_class, int rr_type, unsigned char *answer, int answer_len, | 
					
						
							|  |  |  | 	int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode), | 
					
						
							|  |  |  | 	int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned char *dns_response = answer; | 
					
						
							|  |  |  | 	dns_HEADER *dns_header = (dns_HEADER *)answer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct dn_answer *ans; | 
					
						
							|  |  |  | 	int res, x, pos, dns_response_len, ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dns_response_len = answer_len; | 
					
						
							|  |  |  | 	ret = AST_DNS_SEARCH_NO_RECORDS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Invoke the response_handler callback to notify the observer of the raw DNS response */ | 
					
						
							|  |  |  | 	response_handler(context, dns_response, dns_response_len, ntohs(dns_header->rcode)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Verify there is something to parse */ | 
					
						
							|  |  |  | 	if (answer_len == 0) { | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Try advancing the cursor for the dns header */ | 
					
						
							|  |  |  | 	if ((pos = dns_advance_field(&answer, answer_len, sizeof(dns_HEADER))) < 0) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n"); | 
					
						
							|  |  |  | 		return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Skip domain name and QCODE / QCLASS */ | 
					
						
							|  |  |  | 	for (x = 0; x < ntohs(dns_header->qdcount); x++) { | 
					
						
							|  |  |  | 		if ((res = skip_name(answer, pos)) < 0) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Failed skipping name\n"); | 
					
						
							|  |  |  | 			return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Try advancing the cursor for the name and QCODE / QCLASS fields */ | 
					
						
							|  |  |  | 		if ((pos = dns_advance_field(&answer, pos, res + 4)) < 0) { | 
					
						
							|  |  |  | 			return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-04-26 13:32:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 	/* Extract the individual records */ | 
					
						
							|  |  |  | 	for (x = 0; x < ntohs(dns_header->ancount); x++) { | 
					
						
							|  |  |  | 		if ((res = skip_name(answer, pos)) < 0) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Failed skipping name\n"); | 
					
						
							|  |  |  | 			return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Try advancing the cursor to the current record */ | 
					
						
							|  |  |  | 		if ((pos = dns_advance_field(&answer, pos, res)) < 0) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n"); | 
					
						
							|  |  |  | 			return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Cast the current value for the answer pointer as a dn_answer struct */ | 
					
						
							|  |  |  | 		ans = (struct dn_answer *) answer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Try advancing the cursor to the end of the current record  */ | 
					
						
							|  |  |  | 		if ((pos = dns_advance_field(&answer, pos, sizeof(struct dn_answer)))  < 0) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n"); | 
					
						
							|  |  |  | 			return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Skip over the records that do not have the same resource record class and type we care about */ | 
					
						
							|  |  |  | 		if (ntohs(ans->class) == rr_class && ntohs(ans->rtype) == rr_type) { | 
					
						
							|  |  |  | 			/* Invoke the record handler callback to deliver the discovered record */ | 
					
						
							| 
									
										
										
										
											2015-11-06 13:19:11 -07:00
										 |  |  | 			record_handler(context, answer, ntohs(ans->size), ntohl(ans->ttl)); | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 			/*At least one record was found */ | 
					
						
							|  |  |  | 			ret = AST_DNS_SEARCH_SUCCESS; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Try and update the field to the next record, but ignore any errors that come
 | 
					
						
							|  |  |  | 		 * back because this may be the end of the line. */ | 
					
						
							| 
									
										
										
										
											2015-11-16 15:10:20 -07:00
										 |  |  | 		pos = dns_advance_field(&answer, pos, ntohs(ans->size)); | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Lookup record in DNS | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
											
												docs: Fix various typos in main/
Found via `codespell -q 3 -S "./CREDITS" -L abd,asent,atleast,childrens,contentn,crypted,dne,durationm,exten,inout,leapyear,nd,oclock,offsetp,ot,parm,parms,requestor,ser,slanguage,slin,thirdparty,varn,varns,ues`
											
										 
											2025-02-04 05:53:17 -05:00
										 |  |  |  * \note Asterisk DNS is synchronous at this time. This means that if your DNS does not | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  |  *       work properly, Asterisk might not start properly or a channel may lock. | 
					
						
							| 
									
										
										
										
											2006-01-05 09:40:22 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | int ast_search_dns(void *context, | 
					
						
							| 
									
										
										
										
											2005-03-02 05:17:13 +00:00
										 |  |  | 	   const char *dname, int class, int type, | 
					
						
							| 
									
										
										
										
											2006-07-07 06:55:48 +00:00
										 |  |  | 	   int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer)) | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-02-21 01:05:26 +00:00
										 |  |  | #ifdef HAVE_RES_NINIT
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	struct __res_state dnsstate; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-07-07 06:55:48 +00:00
										 |  |  | 	unsigned char answer[MAX_SIZE]; | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	int res, ret = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-21 01:05:26 +00:00
										 |  |  | #ifdef HAVE_RES_NINIT
 | 
					
						
							| 
									
										
										
										
											2008-04-01 17:23:19 +00:00
										 |  |  | 	memset(&dnsstate, 0, sizeof(dnsstate)); | 
					
						
							| 
									
										
										
										
											2004-04-26 13:32:57 +00:00
										 |  |  | 	res_ninit(&dnsstate); | 
					
						
							| 
									
										
										
										
											2006-07-07 06:55:48 +00:00
										 |  |  | 	res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer)); | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-05-31 19:40:23 +00:00
										 |  |  | 	ast_mutex_lock(&res_lock); | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	res_init(); | 
					
						
							|  |  |  | 	res = res_search(dname, class, type, answer, sizeof(answer)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if (res > 0) { | 
					
						
							|  |  |  | 		if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) { | 
					
						
							| 
									
										
										
										
											2005-03-02 05:17:13 +00:00
										 |  |  | 			ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname); | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			ret = -1; | 
					
						
							| 
									
										
										
										
											2008-03-04 23:04:29 +00:00
										 |  |  | 		} else if (res == 0) { | 
					
						
							| 
									
										
										
										
											2007-06-14 19:39:12 +00:00
										 |  |  | 			ast_debug(1, "No matches found in DNS for %s\n", dname); | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			ret = 0; | 
					
						
							| 
									
										
										
										
											2008-03-04 23:04:29 +00:00
										 |  |  | 		} else | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 			ret = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-02-21 01:05:26 +00:00
										 |  |  | #ifdef HAVE_RES_NINIT
 | 
					
						
							| 
									
										
										
										
											2007-07-10 19:11:25 +00:00
										 |  |  | #ifdef HAVE_RES_NDESTROY
 | 
					
						
							| 
									
										
										
										
											2007-07-10 18:41:03 +00:00
										 |  |  | 	res_ndestroy(&dnsstate); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-04-26 13:32:57 +00:00
										 |  |  | 	res_nclose(&dnsstate); | 
					
						
							| 
									
										
										
										
											2007-07-10 18:41:03 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2009-07-08 16:43:12 +00:00
										 |  |  | #ifdef HAVE_RES_CLOSE
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	res_close(); | 
					
						
							| 
									
										
										
										
											2003-10-26 18:50:49 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-31 19:40:23 +00:00
										 |  |  | 	ast_mutex_unlock(&res_lock); | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-09-27 00:37:07 +00:00
										 |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-03-17 22:54:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | enum ast_dns_search_result ast_search_dns_ex(void *context, const char *dname, int rr_class, int rr_type, | 
					
						
							|  |  |  | 	   int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode), | 
					
						
							|  |  |  | 	   int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int ret, dns_response_len; | 
					
						
							|  |  |  | 	unsigned char dns_response[MAX_SIZE]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Assert that the callbacks are not NULL */ | 
					
						
							|  |  |  | 	ast_assert(response_handler != NULL); | 
					
						
							|  |  |  | 	ast_assert(record_handler != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Try the DNS search. */ | 
					
						
							|  |  |  | 	dns_response_len = dns_search_res(dname, | 
					
						
							|  |  |  | 	                                  rr_class, | 
					
						
							|  |  |  | 	                                  rr_type, | 
					
						
							|  |  |  | 	                                  dns_response, | 
					
						
							|  |  |  | 	                                  sizeof(dns_response)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dns_response_len < 0) { | 
					
						
							| 
									
										
										
										
											2015-11-30 10:13:35 -07:00
										 |  |  | 		ast_debug(1, "DNS search failed for %s\n", dname); | 
					
						
							| 
									
										
										
										
											2016-11-20 09:19:18 +11:00
										 |  |  | 		response_handler(context, (unsigned char *)"", 0, NXDOMAIN); | 
					
						
							| 
									
										
										
										
											2015-07-07 15:03:34 -05:00
										 |  |  | 		return AST_DNS_SEARCH_FAILURE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse records from DNS response */ | 
					
						
							|  |  |  | 	ret = dns_parse_answer_ex(context, | 
					
						
							|  |  |  | 	                          rr_class, | 
					
						
							|  |  |  | 	                          rr_type, | 
					
						
							|  |  |  | 	                          dns_response, | 
					
						
							|  |  |  | 	                          dns_response_len, | 
					
						
							|  |  |  | 	                          response_handler, | 
					
						
							|  |  |  | 	                          record_handler); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Handle the return code from parsing the DNS response */ | 
					
						
							|  |  |  | 	if (ret == AST_DNS_SEARCH_FAILURE) { | 
					
						
							|  |  |  | 		/* Parsing Error */ | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname); | 
					
						
							|  |  |  | 	} else if (ret == AST_DNS_SEARCH_NO_RECORDS) { | 
					
						
							|  |  |  | 		/* No results found */ | 
					
						
							|  |  |  | 		ast_debug(1, "DNS search yielded no results for %s\n", dname); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-17 22:54:32 +00:00
										 |  |  | struct ao2_container *ast_dns_get_nameservers(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef HAVE_RES_NINIT
 | 
					
						
							|  |  |  | 	struct __res_state dnsstate; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	struct __res_state *state; | 
					
						
							|  |  |  | 	struct ao2_container *nameservers; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nameservers = ast_str_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 3); | 
					
						
							|  |  |  | 	if (!nameservers) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_RES_NINIT
 | 
					
						
							|  |  |  | 	memset(&dnsstate, 0, sizeof(dnsstate)); | 
					
						
							|  |  |  | 	res_ninit(&dnsstate); | 
					
						
							|  |  |  | 	state = &dnsstate; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&res_lock); | 
					
						
							|  |  |  | 	res_init(); | 
					
						
							|  |  |  | 	state = &_res; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < state->nscount; i++) { | 
					
						
							| 
									
										
										
										
											2021-09-06 12:37:08 -04:00
										 |  |  | 		char addr[INET6_ADDRSTRLEN]; | 
					
						
							|  |  |  | 		const char *addrp = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* glibc sets sin_family to 0 when the nameserver is an IPv6 address */ | 
					
						
							|  |  |  | 		if (state->nsaddr_list[i].sin_family) { | 
					
						
							|  |  |  | 			addrp = inet_ntop(AF_INET, &state->nsaddr_list[i].sin_addr, addr, sizeof(addr)); | 
					
						
							|  |  |  | #if defined(HAVE_RES_NINIT) && defined(HAVE_STRUCT___RES_STATE__U__EXT_NSADDRS)
 | 
					
						
							|  |  |  | 		} else if (state->_u._ext.nsaddrs[i]) { | 
					
						
							|  |  |  | 			addrp = inet_ntop(AF_INET6, &state->_u._ext.nsaddrs[i]->sin6_addr, addr, sizeof(addr)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (addrp) { | 
					
						
							|  |  |  | 			ast_debug(1, "Discovered nameserver: %s\n", addrp); | 
					
						
							|  |  |  | 			ast_str_container_add(nameservers, addrp); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-03-17 22:54:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_RES_NINIT
 | 
					
						
							|  |  |  | #ifdef HAVE_RES_NDESTROY
 | 
					
						
							|  |  |  | 	res_ndestroy(&dnsstate); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	res_nclose(&dnsstate); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #ifdef HAVE_RES_CLOSE
 | 
					
						
							|  |  |  | 	res_close(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&res_lock); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nameservers; | 
					
						
							| 
									
										
										
										
											2014-08-21 14:52:28 +00:00
										 |  |  | } |