Home | History | Annotate | Line # | Download | only in resolv
res_data.c revision 1.14
      1  1.14  christos /*	$NetBSD: res_data.c,v 1.14 2009/10/24 05:35:37 christos Exp $	*/
      2   1.1  christos 
      3   1.1  christos /*
      4   1.1  christos  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
      5   1.1  christos  * Copyright (c) 1995-1999 by Internet Software Consortium.
      6   1.1  christos  *
      7   1.1  christos  * Permission to use, copy, modify, and distribute this software for any
      8   1.1  christos  * purpose with or without fee is hereby granted, provided that the above
      9   1.1  christos  * copyright notice and this permission notice appear in all copies.
     10   1.1  christos  *
     11   1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     12   1.1  christos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13   1.1  christos  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     14   1.1  christos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15   1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16   1.1  christos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     17   1.1  christos  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18   1.1  christos  */
     19   1.1  christos 
     20   1.4  christos #include <sys/cdefs.h>
     21   1.1  christos #if defined(LIBC_SCCS) && !defined(lint)
     22   1.4  christos #ifdef notdef
     23  1.12  christos static const char rcsid[] = "Id: res_data.c,v 1.7 2008/12/11 09:59:00 marka Exp";
     24   1.4  christos #else
     25  1.14  christos __RCSID("$NetBSD: res_data.c,v 1.14 2009/10/24 05:35:37 christos Exp $");
     26   1.4  christos #endif
     27   1.1  christos #endif /* LIBC_SCCS and not lint */
     28   1.1  christos 
     29   1.1  christos #include "port_before.h"
     30   1.1  christos 
     31   1.5  christos #include "namespace.h"
     32   1.1  christos #include <sys/types.h>
     33   1.1  christos #include <sys/param.h>
     34   1.1  christos #include <sys/socket.h>
     35   1.1  christos #include <sys/time.h>
     36   1.1  christos 
     37   1.1  christos #include <netinet/in.h>
     38   1.1  christos #include <arpa/inet.h>
     39   1.1  christos #include <arpa/nameser.h>
     40   1.1  christos 
     41   1.1  christos #include <ctype.h>
     42   1.1  christos #include <netdb.h>
     43   1.1  christos #include <resolv.h>
     44   1.1  christos #include <res_update.h>
     45   1.1  christos #include <stdio.h>
     46   1.1  christos #include <stdlib.h>
     47   1.1  christos #include <string.h>
     48   1.1  christos #include <unistd.h>
     49   1.1  christos 
     50   1.1  christos #include "port_after.h"
     51   1.5  christos 
     52  1.14  christos #include "res_private.h"
     53  1.14  christos 
     54   1.5  christos #ifdef __weak_alias
     55   1.5  christos __weak_alias(res_init,_res_init)
     56   1.5  christos __weak_alias(res_mkquery,_res_mkquery)
     57   1.7  christos __weak_alias(res_query,_res_query)
     58   1.7  christos __weak_alias(res_search,_res_search)
     59   1.7  christos __weak_alias(res_send,__res_send)
     60   1.7  christos __weak_alias(res_close,__res_close)
     61   1.7  christos /* XXX: these leaked in the old bind8 libc */
     62   1.7  christos __weak_alias(res_querydomain,__res_querydomain)
     63   1.5  christos __weak_alias(res_send_setqhook,__res_send_setqhook)
     64   1.5  christos __weak_alias(res_send_setrhook,__res_send_setrhook)
     65   1.7  christos #if 0
     66   1.7  christos __weak_alias(p_query,__p_query)
     67   1.7  christos __weak_alias(fp_query,__fp_query)
     68   1.7  christos __weak_alias(fp_nquery,__fp_nquery)
     69   1.5  christos __weak_alias(res_isourserver,__res_isourserver)
     70   1.5  christos __weak_alias(res_opt,_res_opt)
     71   1.5  christos __weak_alias(hostalias,__hostalias)
     72   1.5  christos #endif
     73   1.6  christos #endif
     74   1.5  christos 
     75   1.1  christos const char *_res_opcodes[] = {
     76   1.1  christos 	"QUERY",
     77   1.1  christos 	"IQUERY",
     78   1.1  christos 	"CQUERYM",
     79   1.9  christos 	"CQUERYU",	/*%< experimental */
     80   1.9  christos 	"NOTIFY",	/*%< experimental */
     81   1.1  christos 	"UPDATE",
     82   1.1  christos 	"6",
     83   1.1  christos 	"7",
     84   1.1  christos 	"8",
     85   1.1  christos 	"9",
     86   1.1  christos 	"10",
     87   1.1  christos 	"11",
     88   1.1  christos 	"12",
     89   1.1  christos 	"13",
     90   1.1  christos 	"ZONEINIT",
     91   1.1  christos 	"ZONEREF",
     92   1.1  christos };
     93   1.1  christos 
     94   1.1  christos #ifdef BIND_UPDATE
     95   1.1  christos const char *_res_sectioncodes[] = {
     96   1.1  christos 	"ZONE",
     97   1.1  christos 	"PREREQUISITES",
     98   1.1  christos 	"UPDATE",
     99   1.1  christos 	"ADDITIONAL",
    100   1.1  christos };
    101   1.1  christos #endif
    102   1.1  christos 
    103   1.8  christos #ifndef __BIND_NOSTATIC
    104   1.8  christos extern struct __res_state _nres;
    105   1.1  christos 
    106   1.1  christos /* Proto. */
    107   1.1  christos 
    108   1.2  christos int  res_ourserver_p(const res_state, const struct sockaddr *);
    109   1.1  christos 
    110   1.1  christos int
    111   1.1  christos res_init(void) {
    112   1.8  christos 	int rv;
    113   1.8  christos #ifdef COMPAT__RES
    114   1.8  christos 	/*
    115   1.8  christos 	 * Compatibility with program that were accessing _res directly
    116   1.8  christos 	 * to set options. We keep another struct res that is the same
    117   1.8  christos 	 * size as the original res structure, and then copy fields to
    118   1.8  christos 	 * it so that we achieve the same initialization
    119   1.8  christos 	 */
    120   1.8  christos 	extern void *__res_get_old_state(void);
    121   1.8  christos 	extern void __res_put_old_state(void *);
    122   1.8  christos 	res_state ores = __res_get_old_state();
    123   1.8  christos 
    124   1.8  christos 	if (ores->options != 0)
    125   1.8  christos 		_nres.options = ores->options;
    126   1.8  christos 	if (ores->retrans != 0)
    127   1.8  christos 		_nres.retrans = ores->retrans;
    128   1.8  christos 	if (ores->retry != 0)
    129   1.8  christos 		_nres.retry = ores->retry;
    130   1.8  christos #endif
    131   1.1  christos 
    132   1.1  christos 	/*
    133   1.1  christos 	 * These three fields used to be statically initialized.  This made
    134   1.1  christos 	 * it hard to use this code in a shared library.  It is necessary,
    135   1.1  christos 	 * now that we're doing dynamic initialization here, that we preserve
    136   1.1  christos 	 * the old semantics: if an application modifies one of these three
    137   1.1  christos 	 * fields of _res before res_init() is called, res_init() will not
    138   1.1  christos 	 * alter them.  Of course, if an application is setting them to
    139   1.1  christos 	 * _zero_ before calling res_init(), hoping to override what used
    140   1.1  christos 	 * to be the static default, we can't detect it and unexpected results
    141   1.1  christos 	 * will follow.  Zero for any of these fields would make no sense,
    142   1.1  christos 	 * so one can safely assume that the applications were already getting
    143   1.1  christos 	 * unexpected results.
    144   1.1  christos 	 *
    145   1.8  christos 	 * _nres.options is tricky since some apps were known to diddle the bits
    146   1.1  christos 	 * before res_init() was first called. We can't replicate that semantic
    147   1.1  christos 	 * with dynamic initialization (they may have turned bits off that are
    148   1.1  christos 	 * set in RES_DEFAULT).  Our solution is to declare such applications
    149   1.1  christos 	 * "broken".  They could fool us by setting RES_INIT but none do (yet).
    150   1.1  christos 	 */
    151   1.8  christos 	if (!_nres.retrans)
    152   1.8  christos 		_nres.retrans = RES_TIMEOUT;
    153   1.8  christos 	if (!_nres.retry)
    154   1.8  christos 		_nres.retry = 4;
    155   1.8  christos 	if (!(_nres.options & RES_INIT))
    156   1.8  christos 		_nres.options = RES_DEFAULT;
    157   1.1  christos 
    158   1.1  christos 	/*
    159   1.1  christos 	 * This one used to initialize implicitly to zero, so unless the app
    160   1.1  christos 	 * has set it to something in particular, we can randomize it now.
    161   1.1  christos 	 */
    162   1.8  christos 	if (!_nres.id)
    163  1.12  christos 		_nres.id = res_nrandomid(&_nres);
    164   1.1  christos 
    165   1.8  christos 	rv = __res_vinit(&_nres, 1);
    166   1.8  christos #ifdef COMPAT__RES
    167   1.8  christos 	__res_put_old_state(&_nres);
    168   1.8  christos #endif
    169   1.8  christos 	return rv;
    170   1.1  christos }
    171   1.1  christos 
    172   1.1  christos void
    173   1.1  christos p_query(const u_char *msg) {
    174   1.1  christos 	fp_query(msg, stdout);
    175   1.1  christos }
    176   1.1  christos 
    177   1.1  christos void
    178   1.1  christos fp_query(const u_char *msg, FILE *file) {
    179   1.1  christos 	fp_nquery(msg, PACKETSZ, file);
    180   1.1  christos }
    181   1.1  christos 
    182   1.1  christos void
    183   1.1  christos fp_nquery(const u_char *msg, int len, FILE *file) {
    184   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1)
    185   1.1  christos 		return;
    186   1.1  christos 
    187   1.8  christos 	res_pquery(&_nres, msg, len, file);
    188   1.1  christos }
    189   1.1  christos 
    190   1.1  christos int
    191   1.9  christos res_mkquery(int op,			/*!< opcode of query  */
    192   1.9  christos 	    const char *dname,		/*!< domain name  */
    193   1.9  christos 	    int class, int type,	/*!< class and type of query  */
    194   1.9  christos 	    const u_char *data,		/*!< resource record data  */
    195   1.9  christos 	    int datalen,		/*!< length of data  */
    196   1.9  christos 	    const u_char *newrr_in,	/*!< new rr for modify or append  */
    197   1.9  christos 	    u_char *buf,		/*!< buffer to put query  */
    198   1.9  christos 	    int buflen)			/*!< size of buffer  */
    199   1.1  christos {
    200   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    201   1.8  christos 		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
    202   1.1  christos 		return (-1);
    203   1.1  christos 	}
    204   1.8  christos 	return (res_nmkquery(&_nres, op, dname, class, type,
    205   1.1  christos 			     data, datalen,
    206   1.1  christos 			     newrr_in, buf, buflen));
    207   1.1  christos }
    208   1.1  christos 
    209   1.2  christos #ifdef _LIBRESOLV
    210   1.1  christos int
    211   1.1  christos res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
    212   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    213   1.8  christos 		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
    214   1.1  christos 		return (-1);
    215   1.1  christos 	}
    216   1.1  christos 
    217   1.8  christos 	return (res_nmkupdate(&_nres, rrecp_in, buf, buflen));
    218   1.1  christos }
    219   1.2  christos #endif
    220   1.1  christos 
    221   1.1  christos int
    222   1.9  christos res_query(const char *name,	/*!< domain name  */
    223   1.9  christos 	  int class, int type,	/*!< class and type of query  */
    224   1.9  christos 	  u_char *answer,	/*!< buffer to put answer  */
    225   1.9  christos 	  int anslen)		/*!< size of answer buffer  */
    226   1.1  christos {
    227   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    228   1.8  christos 		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
    229   1.1  christos 		return (-1);
    230   1.1  christos 	}
    231   1.8  christos 	return (res_nquery(&_nres, name, class, type, answer, anslen));
    232   1.1  christos }
    233   1.1  christos 
    234   1.1  christos void
    235   1.1  christos res_send_setqhook(res_send_qhook hook) {
    236   1.8  christos 	_nres.qhook = hook;
    237   1.1  christos }
    238   1.1  christos 
    239   1.1  christos void
    240   1.1  christos res_send_setrhook(res_send_rhook hook) {
    241   1.8  christos 	_nres.rhook = hook;
    242   1.1  christos }
    243   1.1  christos 
    244   1.1  christos int
    245   1.1  christos res_isourserver(const struct sockaddr_in *inp) {
    246   1.8  christos 	return (res_ourserver_p(&_nres, (const struct sockaddr *)(const void *)inp));
    247   1.1  christos }
    248   1.1  christos 
    249   1.1  christos int
    250   1.1  christos res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
    251   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    252   1.1  christos 		/* errno should have been set by res_init() in this case. */
    253   1.1  christos 		return (-1);
    254   1.1  christos 	}
    255   1.1  christos 
    256   1.8  christos 	return (res_nsend(&_nres, buf, buflen, ans, anssiz));
    257   1.1  christos }
    258   1.1  christos 
    259   1.2  christos #ifdef _LIBRESOLV
    260   1.1  christos int
    261   1.1  christos res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
    262   1.1  christos 	       u_char *ans, int anssiz)
    263   1.1  christos {
    264   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    265   1.1  christos 		/* errno should have been set by res_init() in this case. */
    266   1.1  christos 		return (-1);
    267   1.1  christos 	}
    268   1.1  christos 
    269   1.8  christos 	return (res_nsendsigned(&_nres, buf, buflen, key, ans, anssiz));
    270   1.1  christos }
    271   1.2  christos #endif
    272   1.1  christos 
    273   1.1  christos void
    274   1.1  christos res_close(void) {
    275   1.8  christos 	res_nclose(&_nres);
    276   1.1  christos }
    277   1.1  christos 
    278   1.2  christos #ifdef _LIBRESOLV
    279   1.1  christos int
    280   1.1  christos res_update(ns_updrec *rrecp_in) {
    281   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    282   1.8  christos 		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
    283   1.1  christos 		return (-1);
    284   1.1  christos 	}
    285   1.1  christos 
    286   1.8  christos 	return (res_nupdate(&_nres, rrecp_in, NULL));
    287   1.1  christos }
    288   1.2  christos #endif
    289   1.1  christos 
    290   1.1  christos int
    291   1.9  christos res_search(const char *name,	/*!< domain name  */
    292   1.9  christos 	   int class, int type,	/*!< class and type of query  */
    293   1.9  christos 	   u_char *answer,	/*!< buffer to put answer  */
    294   1.9  christos 	   int anslen)		/*!< size of answer  */
    295   1.1  christos {
    296   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    297   1.8  christos 		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
    298   1.1  christos 		return (-1);
    299   1.1  christos 	}
    300   1.1  christos 
    301   1.8  christos 	return (res_nsearch(&_nres, name, class, type, answer, anslen));
    302   1.1  christos }
    303   1.1  christos 
    304   1.1  christos int
    305   1.1  christos res_querydomain(const char *name,
    306   1.1  christos 		const char *domain,
    307   1.9  christos 		int class, int type,	/*!< class and type of query  */
    308   1.9  christos 		u_char *answer,		/*!< buffer to put answer  */
    309   1.9  christos 		int anslen)		/*!< size of answer  */
    310   1.1  christos {
    311   1.8  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    312   1.8  christos 		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
    313   1.1  christos 		return (-1);
    314   1.1  christos 	}
    315   1.1  christos 
    316   1.8  christos 	return (res_nquerydomain(&_nres, name, domain,
    317   1.1  christos 				 class, type,
    318   1.1  christos 				 answer, anslen));
    319   1.1  christos }
    320   1.1  christos 
    321   1.2  christos int
    322   1.2  christos res_opt(int a, u_char *b, int c, int d)
    323   1.2  christos {
    324   1.8  christos 	return res_nopt(&_nres, a, b, c, d);
    325   1.2  christos }
    326   1.2  christos 
    327  1.12  christos u_int
    328  1.12  christos res_randomid(void) {
    329  1.12  christos 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
    330  1.12  christos 		RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
    331  1.13  christos 		return (u_int)-1;
    332  1.12  christos 	}
    333  1.12  christos 
    334  1.12  christos 	return (res_nrandomid(&_nres));
    335  1.12  christos }
    336  1.12  christos 
    337   1.1  christos const char *
    338   1.1  christos hostalias(const char *name) {
    339   1.1  christos 	static char abuf[MAXDNAME];
    340   1.1  christos 
    341   1.8  christos 	return (res_hostalias(&_nres, name, abuf, sizeof abuf));
    342   1.1  christos }
    343   1.1  christos 
    344   1.1  christos #ifdef ultrix
    345   1.1  christos int
    346   1.1  christos local_hostname_length(const char *hostname) {
    347   1.1  christos 	int len_host, len_domain;
    348   1.1  christos 
    349   1.8  christos 	if (!*_nres.defdname)
    350   1.1  christos 		res_init();
    351   1.1  christos 	len_host = strlen(hostname);
    352   1.8  christos 	len_domain = strlen(_nres.defdname);
    353   1.1  christos 	if (len_host > len_domain &&
    354   1.8  christos 	    !strcasecmp(hostname + len_host - len_domain, _nres.defdname) &&
    355   1.1  christos 	    hostname[len_host - len_domain - 1] == '.')
    356   1.1  christos 		return (len_host - len_domain - 1);
    357   1.1  christos 	return (0);
    358   1.1  christos }
    359   1.1  christos #endif /*ultrix*/
    360   1.1  christos 
    361   1.1  christos #endif
    362   1.9  christos 
    363   1.9  christos /*! \file */
    364