dns.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006 Thorsten Lockert
00005  *
00006  * Written by Thorsten Lockert <tholo@trollphone.org>
00007  *
00008  * Funding provided by Troll Phone Networks AS
00009  *
00010  * See http://www.asterisk.org for more information about
00011  * the Asterisk project. Please do not directly contact
00012  * any of the maintainers of this project for assistance;
00013  * the project provides a web site, mailing lists and IRC
00014  * channels for your use.
00015  *
00016  * This program is free software, distributed under the terms of
00017  * the GNU General Public License Version 2. See the LICENSE file
00018  * at the top of the source tree.
00019  */
00020 
00021 /*! \file
00022  *
00023  * \brief DNS Support for Asterisk
00024  *
00025  * \author Thorsten Lockert <tholo@trollphone.org>
00026  *
00027  * \par Reference
00028  * - DNR SRV records http://www.ietf.org/rfc/rfc2782.txt
00029  *
00030  */
00031 
00032 /*** MODULEINFO
00033    <support_level>core</support_level>
00034  ***/
00035 
00036 #include "asterisk.h"
00037 
00038 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 421679 $")
00039 
00040 #include "asterisk/network.h"
00041 #include <arpa/nameser.h>  /* res_* functions */
00042 #include <resolv.h>
00043 
00044 #include "asterisk/channel.h"
00045 #include "asterisk/dns.h"
00046 #include "asterisk/endian.h"
00047 
00048 #define MAX_SIZE 4096
00049 
00050 #ifdef __PDP_ENDIAN
00051 #if __BYTE_ORDER == __PDP_ENDIAN
00052 #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
00053 #endif
00054 #endif
00055 #if __BYTE_ORDER == __BIG_ENDIAN
00056 #define DETERMINED_BYTE_ORDER __BIG_ENDIAN
00057 #endif
00058 #if __BYTE_ORDER == __LITTLE_ENDIAN
00059 #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
00060 #endif
00061 
00062 /* The dns_HEADER structure definition below originated
00063    in the arpa/nameser.h header file distributed with ISC
00064    BIND, which contains the following copyright and license
00065    notices:
00066 
00067  * ++Copyright++ 1983, 1989, 1993
00068  * -
00069  * Copyright (c) 1983, 1989, 1993
00070  *    The Regents of the University of California.  All rights reserved.
00071  *
00072  * Redistribution and use in source and binary forms, with or without
00073  * modification, are permitted provided that the following conditions
00074  * are met:
00075  * 1. Redistributions of source code must retain the above copyright
00076  *    notice, this list of conditions and the following disclaimer.
00077  * 2. Redistributions in binary form must reproduce the above copyright
00078  *    notice, this list of conditions and the following disclaimer in the
00079  *    documentation and/or other materials provided with the distribution.
00080  * 3. All advertising materials mentioning features or use of this software
00081  *    must display the following acknowledgement:
00082  * This product includes software developed by the University of
00083  * California, Berkeley and its contributors.
00084  * 4. Neither the name of the University nor the names of its contributors
00085  *    may be used to endorse or promote products derived from this software
00086  *    without specific prior written permission.
00087  *
00088  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00089  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00090  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00091  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00092  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00093  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00094  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00095  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00096  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00097  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00098  * SUCH DAMAGE.
00099  * -
00100  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
00101  *
00102  * Permission to use, copy, modify, and distribute this software for any
00103  * purpose with or without fee is hereby granted, provided that the above
00104  * copyright notice and this permission notice appear in all copies, and that
00105  * the name of Digital Equipment Corporation not be used in advertising or
00106  * publicity pertaining to distribution of the document or software without
00107  * specific, written prior permission.
00108  *
00109  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
00110  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
00111  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
00112  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00113  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00114  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00115  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00116  * SOFTWARE.
00117  * -
00118  * --Copyright--
00119  */
00120 
00121 typedef struct {
00122    unsigned id:16;          /*!< query identification number */
00123 #if DETERMINED_BYTE_ORDER == __BIG_ENDIAN
00124          /* fields in third byte */
00125    unsigned qr:1;           /*!< response flag */
00126    unsigned opcode:4;       /*!< purpose of message */
00127    unsigned aa:1;           /*!< authoritive answer */
00128    unsigned tc:1;           /*!< truncated message */
00129    unsigned rd:1;           /*!< recursion desired */
00130          /* fields in fourth byte */
00131    unsigned ra:1;           /*!< recursion available */
00132    unsigned unused:1;       /*!< unused bits (MBZ as of 4.9.3a3) */
00133    unsigned ad:1;           /*!< authentic data from named */
00134    unsigned cd:1;           /*!< checking disabled by resolver */
00135    unsigned rcode:4;        /*!< response code */
00136 #endif
00137 #if DETERMINED_BYTE_ORDER == __LITTLE_ENDIAN
00138          /* fields in third byte */
00139    unsigned rd:1;           /*!< recursion desired */
00140    unsigned tc:1;           /*!< truncated message */
00141    unsigned aa:1;           /*!< authoritive answer */
00142    unsigned opcode:4;       /*!< purpose of message */
00143    unsigned qr:1;           /*!< response flag */
00144          /* fields in fourth byte */
00145    unsigned rcode:4;        /*!< response code */
00146    unsigned cd:1;           /*!< checking disabled by resolver */
00147    unsigned ad:1;           /*!< authentic data from named */
00148    unsigned unused:1;       /*!< unused bits (MBZ as of 4.9.3a3) */
00149    unsigned ra:1;           /*!< recursion available */
00150 #endif
00151          /* remaining bytes */
00152    unsigned qdcount:16;     /*!< number of question entries */
00153    unsigned ancount:16;     /*!< number of answer entries */
00154    unsigned nscount:16;     /*!< number of authority entries */
00155    unsigned arcount:16;     /*!< number of resource entries */
00156 } dns_HEADER;
00157 
00158 struct dn_answer {
00159    unsigned short rtype;
00160    unsigned short class;
00161    unsigned int ttl;
00162    unsigned short size;
00163 } __attribute__((__packed__));
00164 
00165 static int skip_name(unsigned char *s, int len)
00166 {
00167    int x = 0;
00168 
00169    while (x < len) {
00170       if (*s == '\0') {
00171          s++;
00172          x++;
00173          break;
00174       }
00175       if ((*s & 0xc0) == 0xc0) {
00176          s += 2;
00177          x += 2;
00178          break;
00179       }
00180       x += *s + 1;
00181       s += *s + 1;
00182    }
00183    if (x >= len)
00184       return -1;
00185    return x;
00186 }
00187 
00188 /*! \brief Parse DNS lookup result, call callback */
00189 static int dns_parse_answer(void *context,
00190    int class, int type, unsigned char *answer, int len,
00191    int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
00192 {
00193    unsigned char *fullanswer = answer;
00194    struct dn_answer *ans;
00195    dns_HEADER *h;
00196    int ret = 0;
00197    int res;
00198    int x;
00199 
00200    h = (dns_HEADER *)answer;
00201    answer += sizeof(dns_HEADER);
00202    len -= sizeof(dns_HEADER);
00203 
00204    for (x = 0; x < ntohs(h->qdcount); x++) {
00205       if ((res = skip_name(answer, len)) < 0) {
00206          ast_log(LOG_WARNING, "Couldn't skip over name\n");
00207          return -1;
00208       }
00209       answer += res + 4;   /* Skip name and QCODE / QCLASS */
00210       len -= res + 4;
00211       if (len < 0) {
00212          ast_log(LOG_WARNING, "Strange query size\n");
00213          return -1;
00214       }
00215    }
00216 
00217    for (x = 0; x < ntohs(h->ancount); x++) {
00218       if ((res = skip_name(answer, len)) < 0) {
00219          ast_log(LOG_WARNING, "Failed skipping name\n");
00220          return -1;
00221       }
00222       answer += res;
00223       len -= res;
00224       ans = (struct dn_answer *)answer;
00225       answer += sizeof(struct dn_answer);
00226       len -= sizeof(struct dn_answer);
00227       if (len < 0) {
00228          ast_log(LOG_WARNING, "Length of DNS answer exceeds frame\n");
00229          return -1;
00230       }
00231 
00232       if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
00233          if (callback) {
00234             if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
00235                ast_log(LOG_WARNING, "Failed to parse result\n");
00236                return -1;
00237             }
00238             ret = 1;
00239          }
00240       }
00241       answer += ntohs(ans->size);
00242       len -= ntohs(ans->size);
00243    }
00244    return ret;
00245 }
00246 
00247 #ifndef HAVE_RES_NINIT
00248 AST_MUTEX_DEFINE_STATIC(res_lock);
00249 #endif
00250 
00251 /*! \brief Lookup record in DNS
00252 \note Asterisk DNS is synchronus at this time. This means that if your DNS does
00253 not work properly, Asterisk might not start properly or a channel may lock.
00254 */
00255 int ast_search_dns(void *context,
00256       const char *dname, int class, int type,
00257       int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
00258 {
00259 #ifdef HAVE_RES_NINIT
00260    struct __res_state dnsstate;
00261 #endif
00262    unsigned char answer[MAX_SIZE];
00263    int res, ret = -1;
00264 
00265 #ifdef HAVE_RES_NINIT
00266    memset(&dnsstate, 0, sizeof(dnsstate));
00267    res_ninit(&dnsstate);
00268    res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer));
00269 #else
00270    ast_mutex_lock(&res_lock);
00271    res_init();
00272    res = res_search(dname, class, type, answer, sizeof(answer));
00273 #endif
00274    if (res > 0) {
00275       if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
00276          ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
00277          ret = -1;
00278       } else if (res == 0) {
00279          ast_debug(1, "No matches found in DNS for %s\n", dname);
00280          ret = 0;
00281       } else
00282          ret = 1;
00283    }
00284 #ifdef HAVE_RES_NINIT
00285 #ifdef HAVE_RES_NDESTROY
00286    res_ndestroy(&dnsstate);
00287 #else
00288    res_nclose(&dnsstate);
00289 #endif
00290 #else
00291 #ifdef HAVE_RES_CLOSE
00292    res_close();
00293 #endif
00294    ast_mutex_unlock(&res_lock);
00295 #endif
00296 
00297    return ret;
00298 }
00299 
00300 struct ao2_container *ast_dns_get_nameservers(void)
00301 {
00302 #ifdef HAVE_RES_NINIT
00303    struct __res_state dnsstate;
00304 #endif
00305    struct __res_state *state;
00306    struct ao2_container *nameservers;
00307    int i;
00308 
00309    nameservers = ast_str_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 3);
00310    if (!nameservers) {
00311       return NULL;
00312    }
00313 
00314 #ifdef HAVE_RES_NINIT
00315    memset(&dnsstate, 0, sizeof(dnsstate));
00316    res_ninit(&dnsstate);
00317    state = &dnsstate;
00318 #else
00319    ast_mutex_lock(&res_lock);
00320    res_init();
00321    state = &_res;
00322 #endif
00323 
00324    for (i = 0; i < state->nscount; i++) {
00325       ast_str_container_add(nameservers, ast_inet_ntoa(state->nsaddr_list[i].sin_addr));
00326    }
00327 
00328 #ifdef HAVE_RES_NINIT
00329 #ifdef HAVE_RES_NDESTROY
00330    res_ndestroy(&dnsstate);
00331 #else
00332    res_nclose(&dnsstate);
00333 #endif
00334 #else
00335 #ifdef HAVE_RES_CLOSE
00336    res_close();
00337 #endif
00338    ast_mutex_unlock(&res_lock);
00339 #endif
00340 
00341    return nameservers;
00342 }
00343 

Generated on Thu Apr 16 06:27:33 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6