michael@0: /* $NetBSD: res_data.c,v 1.8 2004/06/09 18:07:03 christos Exp $ */ michael@0: michael@0: /* michael@0: * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") michael@0: * Copyright (c) 1995-1999 by Internet Software Consortium. michael@0: * michael@0: * Permission to use, copy, modify, and distribute this software for any michael@0: * purpose with or without fee is hereby granted, provided that the above michael@0: * copyright notice and this permission notice appear in all copies. michael@0: * michael@0: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES michael@0: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF michael@0: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR michael@0: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES michael@0: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN michael@0: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT michael@0: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. michael@0: */ michael@0: michael@0: /* michael@0: * This version of this file is derived from Android 2.3 "Gingerbread", michael@0: * which contains uncredited changes by Android/Google developers. It has michael@0: * been modified in 2011 for use in the Android build of Mozilla Firefox by michael@0: * Mozilla contributors (including Michael Edwards , michael@0: * and Steve Workman ). michael@0: * These changes are offered under the same license as the original NetBSD michael@0: * file, whose copyright and license are unchanged above. michael@0: */ michael@0: michael@0: #define ANDROID_CHANGES 1 michael@0: #define MOZILLA_NECKO_EXCLUDE_CODE 1 michael@0: michael@0: #include michael@0: #if defined(LIBC_SCCS) && !defined(lint) michael@0: #ifdef notdef michael@0: static const char rcsid[] = "Id: res_data.c,v 1.1.206.2 2004/03/16 12:34:18 marka Exp"; michael@0: #else michael@0: __RCSID("$NetBSD: res_data.c,v 1.8 2004/06/09 18:07:03 christos Exp $"); michael@0: #endif michael@0: #endif /* LIBC_SCCS and not lint */ michael@0: michael@0: michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: #include "arpa_nameser.h" michael@0: michael@0: #include michael@0: #include michael@0: #include "resolv_private.h" michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: michael@0: const char * const _res_opcodes[] = { michael@0: "QUERY", michael@0: "IQUERY", michael@0: "CQUERYM", michael@0: "CQUERYU", /* experimental */ michael@0: "NOTIFY", /* experimental */ michael@0: "UPDATE", michael@0: "6", michael@0: "7", michael@0: "8", michael@0: "9", michael@0: "10", michael@0: "11", michael@0: "12", michael@0: "13", michael@0: "ZONEINIT", michael@0: "ZONEREF", michael@0: }; michael@0: michael@0: #ifdef BIND_UPDATE michael@0: const char * const _res_sectioncodes[] = { michael@0: "ZONE", michael@0: "PREREQUISITES", michael@0: "UPDATE", michael@0: "ADDITIONAL", michael@0: }; michael@0: #endif michael@0: michael@0: #ifndef MOZILLA_NECKO_EXCLUDE_CODE michael@0: #ifndef __BIND_NOSTATIC michael@0: extern struct __res_state _nres; michael@0: michael@0: /* Proto. */ michael@0: michael@0: int res_ourserver_p(const res_state, const struct sockaddr *); michael@0: michael@0: #ifdef ANDROID_CHANGES michael@0: int res_need_init() { michael@0: return ((_nres.options & RES_INIT) == 0U) || res_get_dns_changed(); michael@0: } michael@0: #else michael@0: #define res_need_init() ((_nres.options & RES_INIT) == 0U) michael@0: #endif michael@0: michael@0: int michael@0: res_init(void) { michael@0: int rv; michael@0: extern int __res_vinit(res_state, int); michael@0: #ifdef COMPAT__RES michael@0: /* michael@0: * Compatibility with program that were accessing _res directly michael@0: * to set options. We keep another struct res that is the same michael@0: * size as the original res structure, and then copy fields to michael@0: * it so that we achieve the same initialization michael@0: */ michael@0: extern void *__res_get_old_state(void); michael@0: extern void __res_put_old_state(void *); michael@0: res_state ores = __res_get_old_state(); michael@0: michael@0: if (ores->options != 0) michael@0: _nres.options = ores->options; michael@0: if (ores->retrans != 0) michael@0: _nres.retrans = ores->retrans; michael@0: if (ores->retry != 0) michael@0: _nres.retry = ores->retry; michael@0: #endif michael@0: michael@0: /* michael@0: * These three fields used to be statically initialized. This made michael@0: * it hard to use this code in a shared library. It is necessary, michael@0: * now that we're doing dynamic initialization here, that we preserve michael@0: * the old semantics: if an application modifies one of these three michael@0: * fields of _res before res_init() is called, res_init() will not michael@0: * alter them. Of course, if an application is setting them to michael@0: * _zero_ before calling res_init(), hoping to override what used michael@0: * to be the static default, we can't detect it and unexpected results michael@0: * will follow. Zero for any of these fields would make no sense, michael@0: * so one can safely assume that the applications were already getting michael@0: * unexpected results. michael@0: * michael@0: * _nres.options is tricky since some apps were known to diddle the bits michael@0: * before res_init() was first called. We can't replicate that semantic michael@0: * with dynamic initialization (they may have turned bits off that are michael@0: * set in RES_DEFAULT). Our solution is to declare such applications michael@0: * "broken". They could fool us by setting RES_INIT but none do (yet). michael@0: */ michael@0: if (!_nres.retrans) michael@0: _nres.retrans = RES_TIMEOUT; michael@0: if (!_nres.retry) michael@0: _nres.retry = 4; michael@0: if (!(_nres.options & RES_INIT)) michael@0: _nres.options = RES_DEFAULT; michael@0: michael@0: /* michael@0: * This one used to initialize implicitly to zero, so unless the app michael@0: * has set it to something in particular, we can randomize it now. michael@0: */ michael@0: if (!_nres.id) michael@0: _nres.id = res_randomid(); michael@0: michael@0: rv = __res_vinit(&_nres, 1); michael@0: #ifdef COMPAT__RES michael@0: __res_put_old_state(&_nres); michael@0: #endif michael@0: return rv; michael@0: } michael@0: michael@0: void michael@0: p_query(const u_char *msg) { michael@0: fp_query(msg, stdout); michael@0: } michael@0: michael@0: void michael@0: fp_query(const u_char *msg, FILE *file) { michael@0: fp_nquery(msg, PACKETSZ, file); michael@0: } michael@0: michael@0: void michael@0: fp_nquery(const u_char *msg, int len, FILE *file) { michael@0: if (res_need_init() && res_init() == -1) michael@0: return; michael@0: michael@0: res_pquery(&_nres, msg, len, file); michael@0: } michael@0: michael@0: int michael@0: res_mkquery(int op, /* opcode of query */ michael@0: const char *dname, /* domain name */ michael@0: int class, int type, /* class and type of query */ michael@0: const u_char *data, /* resource record data */ michael@0: int datalen, /* length of data */ michael@0: const u_char *newrr_in, /* new rr for modify or append */ michael@0: u_char *buf, /* buffer to put query */ michael@0: int buflen) /* size of buffer */ michael@0: { michael@0: if (res_need_init() && res_init() == -1) { michael@0: RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); michael@0: return (-1); michael@0: } michael@0: return (res_nmkquery(&_nres, op, dname, class, type, michael@0: data, datalen, michael@0: newrr_in, buf, buflen)); michael@0: } michael@0: michael@0: #ifdef _LIBRESOLV michael@0: int michael@0: res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { michael@0: if (res_need_init() && res_init() == -1) { michael@0: RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); michael@0: return (-1); michael@0: } michael@0: michael@0: return (res_nmkupdate(&_nres, rrecp_in, buf, buflen)); michael@0: } michael@0: #endif michael@0: michael@0: int michael@0: res_query(const char *name, /* domain name */ michael@0: int class, int type, /* class and type of query */ michael@0: u_char *answer, /* buffer to put answer */ michael@0: int anslen) /* size of answer buffer */ michael@0: { michael@0: if (res_need_init() && res_init() == -1) { michael@0: RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); michael@0: return (-1); michael@0: } michael@0: return (res_nquery(&_nres, name, class, type, answer, anslen)); michael@0: } michael@0: michael@0: void michael@0: res_send_setqhook(res_send_qhook hook) { michael@0: _nres.qhook = hook; michael@0: } michael@0: michael@0: void michael@0: res_send_setrhook(res_send_rhook hook) { michael@0: _nres.rhook = hook; michael@0: } michael@0: michael@0: int michael@0: res_isourserver(const struct sockaddr_in *inp) { michael@0: return (res_ourserver_p(&_nres, (const struct sockaddr *)(const void *)inp)); michael@0: } michael@0: michael@0: int michael@0: res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { michael@0: if (res_need_init() && res_init() == -1) { michael@0: /* errno should have been set by res_init() in this case. */ michael@0: return (-1); michael@0: } michael@0: michael@0: return (res_nsend(&_nres, buf, buflen, ans, anssiz)); michael@0: } michael@0: michael@0: #ifdef _LIBRESOLV michael@0: int michael@0: res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, michael@0: u_char *ans, int anssiz) michael@0: { michael@0: if (res_need_init() && res_init() == -1) { michael@0: /* errno should have been set by res_init() in this case. */ michael@0: return (-1); michael@0: } michael@0: michael@0: return (res_nsendsigned(&_nres, buf, buflen, key, ans, anssiz)); michael@0: } michael@0: #endif michael@0: michael@0: void michael@0: res_close(void) { michael@0: res_nclose(&_nres); michael@0: } michael@0: michael@0: #ifdef _LIBRESOLV michael@0: int michael@0: res_update(ns_updrec *rrecp_in) { michael@0: if (res_need_init() && res_init() == -1) { michael@0: RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); michael@0: return (-1); michael@0: } michael@0: michael@0: return (res_nupdate(&_nres, rrecp_in, NULL)); michael@0: } michael@0: #endif michael@0: michael@0: int michael@0: res_search(const char *name, /* domain name */ michael@0: int class, int type, /* class and type of query */ michael@0: u_char *answer, /* buffer to put answer */ michael@0: int anslen) /* size of answer */ michael@0: { michael@0: if (res_need_init() && res_init() == -1) { michael@0: RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); michael@0: return (-1); michael@0: } michael@0: michael@0: return (res_nsearch(&_nres, name, class, type, answer, anslen)); michael@0: } michael@0: michael@0: int michael@0: res_querydomain(const char *name, michael@0: const char *domain, michael@0: int class, int type, /* class and type of query */ michael@0: u_char *answer, /* buffer to put answer */ michael@0: int anslen) /* size of answer */ michael@0: { michael@0: if (res_need_init() && res_init() == -1) { michael@0: RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); michael@0: return (-1); michael@0: } michael@0: michael@0: return (res_nquerydomain(&_nres, name, domain, michael@0: class, type, michael@0: answer, anslen)); michael@0: } michael@0: michael@0: int michael@0: res_opt(int a, u_char *b, int c, int d) michael@0: { michael@0: return res_nopt(&_nres, a, b, c, d); michael@0: } michael@0: #endif michael@0: #endif michael@0: michael@0: const char * michael@0: hostalias(const char *name) { michael@0: return NULL; michael@0: } michael@0: michael@0: #ifndef MOZILLA_NECKO_EXCLUDE_CODE michael@0: #ifdef ultrix michael@0: int michael@0: local_hostname_length(const char *hostname) { michael@0: int len_host, len_domain; michael@0: michael@0: if (!*_nres.defdname) michael@0: res_init(); michael@0: len_host = strlen(hostname); michael@0: len_domain = strlen(_nres.defdname); michael@0: if (len_host > len_domain && michael@0: !strcasecmp(hostname + len_host - len_domain, _nres.defdname) && michael@0: hostname[len_host - len_domain - 1] == '.') michael@0: return (len_host - len_domain - 1); michael@0: return (0); michael@0: } michael@0: #endif /*ultrix*/ michael@0: #endif