17c478bd9Sstevel@tonic-gate /*
2*4e567b44SStacey Marshall * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate */
47c478bd9Sstevel@tonic-gate
59525b14bSRao Shoaib
67c478bd9Sstevel@tonic-gate /*
79525b14bSRao Shoaib * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
87c478bd9Sstevel@tonic-gate * Copyright (c) 1995-1999 by Internet Software Consortium.
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any
117c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above
127c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies.
137c478bd9Sstevel@tonic-gate *
149525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
159525b14bSRao Shoaib * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
169525b14bSRao Shoaib * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
179525b14bSRao Shoaib * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
189525b14bSRao Shoaib * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
199525b14bSRao Shoaib * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
209525b14bSRao Shoaib * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate
237c478bd9Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint)
249525b14bSRao Shoaib static const char rcsid[] = "$Id: res_data.c,v 1.7 2008/12/11 09:59:00 marka Exp $";
257c478bd9Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include "port_before.h"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/param.h>
317c478bd9Sstevel@tonic-gate #include <sys/socket.h>
327c478bd9Sstevel@tonic-gate #include <sys/time.h>
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include <netinet/in.h>
357c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
367c478bd9Sstevel@tonic-gate #include <arpa/nameser.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate #include <ctype.h>
397c478bd9Sstevel@tonic-gate #include <netdb.h>
407c478bd9Sstevel@tonic-gate #include <resolv.h>
417c478bd9Sstevel@tonic-gate #include <res_update.h>
427c478bd9Sstevel@tonic-gate #include <stdio.h>
437c478bd9Sstevel@tonic-gate #include <stdlib.h>
447c478bd9Sstevel@tonic-gate #include <string.h>
457c478bd9Sstevel@tonic-gate #include <unistd.h>
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate #include "port_after.h"
487c478bd9Sstevel@tonic-gate
499525b14bSRao Shoaib #ifndef ORIGINAL_ISC_CODE
507c478bd9Sstevel@tonic-gate #pragma weak __fp_nquery = fp_nquery
517c478bd9Sstevel@tonic-gate #pragma weak __fp_query = fp_query
527c478bd9Sstevel@tonic-gate #pragma weak __p_query = p_query
537c478bd9Sstevel@tonic-gate #pragma weak __hostalias = hostalias
549525b14bSRao Shoaib #pragma weak __res_randomid = res_randomid
557c478bd9Sstevel@tonic-gate #endif
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate const char *_res_opcodes[] = {
587c478bd9Sstevel@tonic-gate "QUERY",
597c478bd9Sstevel@tonic-gate "IQUERY",
607c478bd9Sstevel@tonic-gate "CQUERYM",
619525b14bSRao Shoaib "CQUERYU", /*%< experimental */
629525b14bSRao Shoaib "NOTIFY", /*%< experimental */
637c478bd9Sstevel@tonic-gate "UPDATE",
647c478bd9Sstevel@tonic-gate "6",
657c478bd9Sstevel@tonic-gate "7",
667c478bd9Sstevel@tonic-gate "8",
677c478bd9Sstevel@tonic-gate "9",
687c478bd9Sstevel@tonic-gate "10",
697c478bd9Sstevel@tonic-gate "11",
707c478bd9Sstevel@tonic-gate "12",
717c478bd9Sstevel@tonic-gate "13",
727c478bd9Sstevel@tonic-gate "ZONEINIT",
737c478bd9Sstevel@tonic-gate "ZONEREF",
747c478bd9Sstevel@tonic-gate };
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate #ifdef BIND_UPDATE
777c478bd9Sstevel@tonic-gate const char *_res_sectioncodes[] = {
787c478bd9Sstevel@tonic-gate "ZONE",
797c478bd9Sstevel@tonic-gate "PREREQUISITES",
807c478bd9Sstevel@tonic-gate "UPDATE",
817c478bd9Sstevel@tonic-gate "ADDITIONAL",
827c478bd9Sstevel@tonic-gate };
837c478bd9Sstevel@tonic-gate #endif
847c478bd9Sstevel@tonic-gate
859525b14bSRao Shoaib #undef _res
867c478bd9Sstevel@tonic-gate #ifndef __BIND_NOSTATIC
877c478bd9Sstevel@tonic-gate struct __res_state _res
887c478bd9Sstevel@tonic-gate # if defined(__BIND_RES_TEXT)
899525b14bSRao Shoaib = { RES_TIMEOUT, } /*%< Motorola, et al. */
907c478bd9Sstevel@tonic-gate # endif
917c478bd9Sstevel@tonic-gate ;
927c478bd9Sstevel@tonic-gate
93*4e567b44SStacey Marshall #ifdef ORIGINAL_ISC_CODE
949525b14bSRao Shoaib #if defined(DO_PTHREADS) || defined(__linux)
959525b14bSRao Shoaib #define _res (*__res_state())
969525b14bSRao Shoaib #endif
97*4e567b44SStacey Marshall #endif
989525b14bSRao Shoaib
997c478bd9Sstevel@tonic-gate /* Proto. */
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate int res_ourserver_p(const res_state, const struct sockaddr_in *);
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate int
res_init(void)1047c478bd9Sstevel@tonic-gate res_init(void) {
1057c478bd9Sstevel@tonic-gate extern int __res_vinit(res_state, int);
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate * These three fields used to be statically initialized. This made
1097c478bd9Sstevel@tonic-gate * it hard to use this code in a shared library. It is necessary,
1107c478bd9Sstevel@tonic-gate * now that we're doing dynamic initialization here, that we preserve
1117c478bd9Sstevel@tonic-gate * the old semantics: if an application modifies one of these three
1127c478bd9Sstevel@tonic-gate * fields of _res before res_init() is called, res_init() will not
1137c478bd9Sstevel@tonic-gate * alter them. Of course, if an application is setting them to
1147c478bd9Sstevel@tonic-gate * _zero_ before calling res_init(), hoping to override what used
1157c478bd9Sstevel@tonic-gate * to be the static default, we can't detect it and unexpected results
1167c478bd9Sstevel@tonic-gate * will follow. Zero for any of these fields would make no sense,
1177c478bd9Sstevel@tonic-gate * so one can safely assume that the applications were already getting
1187c478bd9Sstevel@tonic-gate * unexpected results.
1197c478bd9Sstevel@tonic-gate *
1207c478bd9Sstevel@tonic-gate * _res.options is tricky since some apps were known to diddle the bits
1217c478bd9Sstevel@tonic-gate * before res_init() was first called. We can't replicate that semantic
1227c478bd9Sstevel@tonic-gate * with dynamic initialization (they may have turned bits off that are
1237c478bd9Sstevel@tonic-gate * set in RES_DEFAULT). Our solution is to declare such applications
1247c478bd9Sstevel@tonic-gate * "broken". They could fool us by setting RES_INIT but none do (yet).
1257c478bd9Sstevel@tonic-gate */
1267c478bd9Sstevel@tonic-gate if (!_res.retrans)
1277c478bd9Sstevel@tonic-gate _res.retrans = RES_TIMEOUT;
1287c478bd9Sstevel@tonic-gate if (!_res.retry)
1297c478bd9Sstevel@tonic-gate _res.retry = 4;
1307c478bd9Sstevel@tonic-gate if (!(_res.options & RES_INIT))
1317c478bd9Sstevel@tonic-gate _res.options = RES_DEFAULT;
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate * This one used to initialize implicitly to zero, so unless the app
1357c478bd9Sstevel@tonic-gate * has set it to something in particular, we can randomize it now.
1367c478bd9Sstevel@tonic-gate */
1377c478bd9Sstevel@tonic-gate if (!_res.id)
1389525b14bSRao Shoaib _res.id = res_nrandomid(&_res);
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate return (__res_vinit(&_res, 1));
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate void
p_query(const u_char * msg)1447c478bd9Sstevel@tonic-gate p_query(const u_char *msg) {
1457c478bd9Sstevel@tonic-gate fp_query(msg, stdout);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate void
fp_query(const u_char * msg,FILE * file)1497c478bd9Sstevel@tonic-gate fp_query(const u_char *msg, FILE *file) {
1507c478bd9Sstevel@tonic-gate fp_nquery(msg, PACKETSZ, file);
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate void
fp_nquery(const u_char * msg,int len,FILE * file)1547c478bd9Sstevel@tonic-gate fp_nquery(const u_char *msg, int len, FILE *file) {
1559525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1)
1567c478bd9Sstevel@tonic-gate return;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate res_pquery(&_res, msg, len, file);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate int
res_mkquery(int op,const char * dname,int class,int type,const u_char * data,int datalen,const u_char * newrr_in,u_char * buf,int buflen)1629525b14bSRao Shoaib res_mkquery(int op, /*!< opcode of query */
1639525b14bSRao Shoaib const char *dname, /*!< domain name */
1649525b14bSRao Shoaib int class, int type, /*!< class and type of query */
1659525b14bSRao Shoaib const u_char *data, /*!< resource record data */
1669525b14bSRao Shoaib int datalen, /*!< length of data */
1679525b14bSRao Shoaib const u_char *newrr_in, /*!< new rr for modify or append */
1689525b14bSRao Shoaib u_char *buf, /*!< buffer to put query */
1699525b14bSRao Shoaib int buflen) /*!< size of buffer */
1707c478bd9Sstevel@tonic-gate {
1719525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
1727c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
1737c478bd9Sstevel@tonic-gate return (-1);
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate return (res_nmkquery(&_res, op, dname, class, type,
1767c478bd9Sstevel@tonic-gate data, datalen,
1777c478bd9Sstevel@tonic-gate newrr_in, buf, buflen));
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate int
res_mkupdate(ns_updrec * rrecp_in,u_char * buf,int buflen)1817c478bd9Sstevel@tonic-gate res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
1829525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
1837c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
1847c478bd9Sstevel@tonic-gate return (-1);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate int
res_query(const char * name,int class,int type,u_char * answer,int anslen)1919525b14bSRao Shoaib res_query(const char *name, /*!< domain name */
1929525b14bSRao Shoaib int class, int type, /*!< class and type of query */
1939525b14bSRao Shoaib u_char *answer, /*!< buffer to put answer */
1949525b14bSRao Shoaib int anslen) /*!< size of answer buffer */
1957c478bd9Sstevel@tonic-gate {
1969525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
1977c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
1987c478bd9Sstevel@tonic-gate return (-1);
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate return (res_nquery(&_res, name, class, type, answer, anslen));
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate void
res_send_setqhook(res_send_qhook hook)2047c478bd9Sstevel@tonic-gate res_send_setqhook(res_send_qhook hook) {
2057c478bd9Sstevel@tonic-gate _res.qhook = hook;
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate void
res_send_setrhook(res_send_rhook hook)2097c478bd9Sstevel@tonic-gate res_send_setrhook(res_send_rhook hook) {
2107c478bd9Sstevel@tonic-gate _res.rhook = hook;
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate int
res_isourserver(const struct sockaddr_in * inp)2147c478bd9Sstevel@tonic-gate res_isourserver(const struct sockaddr_in *inp) {
2157c478bd9Sstevel@tonic-gate return (res_ourserver_p(&_res, inp));
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate int
res_send(const u_char * buf,int buflen,u_char * ans,int anssiz)2197c478bd9Sstevel@tonic-gate res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
2209525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
2217c478bd9Sstevel@tonic-gate /* errno should have been set by res_init() in this case. */
2227c478bd9Sstevel@tonic-gate return (-1);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate return (res_nsend(&_res, buf, buflen, ans, anssiz));
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate int
res_sendsigned(const u_char * buf,int buflen,ns_tsig_key * key,u_char * ans,int anssiz)2297c478bd9Sstevel@tonic-gate res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
2307c478bd9Sstevel@tonic-gate u_char *ans, int anssiz)
2317c478bd9Sstevel@tonic-gate {
2329525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
2337c478bd9Sstevel@tonic-gate /* errno should have been set by res_init() in this case. */
2347c478bd9Sstevel@tonic-gate return (-1);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate void
res_close(void)2417c478bd9Sstevel@tonic-gate res_close(void) {
2427c478bd9Sstevel@tonic-gate res_nclose(&_res);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate int
res_update(ns_updrec * rrecp_in)2467c478bd9Sstevel@tonic-gate res_update(ns_updrec *rrecp_in) {
2479525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
2487c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
2497c478bd9Sstevel@tonic-gate return (-1);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate return (res_nupdate(&_res, rrecp_in, NULL));
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate int
res_search(const char * name,int class,int type,u_char * answer,int anslen)2569525b14bSRao Shoaib res_search(const char *name, /*!< domain name */
2579525b14bSRao Shoaib int class, int type, /*!< class and type of query */
2589525b14bSRao Shoaib u_char *answer, /*!< buffer to put answer */
2599525b14bSRao Shoaib int anslen) /*!< size of answer */
2607c478bd9Sstevel@tonic-gate {
2619525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
2627c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
2637c478bd9Sstevel@tonic-gate return (-1);
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate return (res_nsearch(&_res, name, class, type, answer, anslen));
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate int
res_querydomain(const char * name,const char * domain,int class,int type,u_char * answer,int anslen)2707c478bd9Sstevel@tonic-gate res_querydomain(const char *name,
2717c478bd9Sstevel@tonic-gate const char *domain,
2729525b14bSRao Shoaib int class, int type, /*!< class and type of query */
2739525b14bSRao Shoaib u_char *answer, /*!< buffer to put answer */
2749525b14bSRao Shoaib int anslen) /*!< size of answer */
2757c478bd9Sstevel@tonic-gate {
2769525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
2777c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
2787c478bd9Sstevel@tonic-gate return (-1);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate return (res_nquerydomain(&_res, name, domain,
2827c478bd9Sstevel@tonic-gate class, type,
2837c478bd9Sstevel@tonic-gate answer, anslen));
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate
2869525b14bSRao Shoaib u_int
res_randomid(void)2879525b14bSRao Shoaib res_randomid(void) {
2889525b14bSRao Shoaib if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
2899525b14bSRao Shoaib RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
2909525b14bSRao Shoaib return (-1);
2919525b14bSRao Shoaib }
2929525b14bSRao Shoaib
2939525b14bSRao Shoaib return (res_nrandomid(&_res));
2949525b14bSRao Shoaib }
2959525b14bSRao Shoaib
2967c478bd9Sstevel@tonic-gate const char *
hostalias(const char * name)2977c478bd9Sstevel@tonic-gate hostalias(const char *name) {
2987c478bd9Sstevel@tonic-gate static char abuf[MAXDNAME];
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate return (res_hostalias(&_res, name, abuf, sizeof abuf));
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate #ifdef ultrix
3047c478bd9Sstevel@tonic-gate int
local_hostname_length(const char * hostname)3057c478bd9Sstevel@tonic-gate local_hostname_length(const char *hostname) {
3067c478bd9Sstevel@tonic-gate int len_host, len_domain;
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate if (!*_res.defdname)
3097c478bd9Sstevel@tonic-gate res_init();
3107c478bd9Sstevel@tonic-gate len_host = strlen(hostname);
3117c478bd9Sstevel@tonic-gate len_domain = strlen(_res.defdname);
3127c478bd9Sstevel@tonic-gate if (len_host > len_domain &&
3137c478bd9Sstevel@tonic-gate !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
3147c478bd9Sstevel@tonic-gate hostname[len_host - len_domain - 1] == '.')
3157c478bd9Sstevel@tonic-gate return (len_host - len_domain - 1);
3167c478bd9Sstevel@tonic-gate return (0);
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate #endif /*ultrix*/
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate #endif
3219525b14bSRao Shoaib
3229525b14bSRao Shoaib /*! \file */
323