1156952Sume/* 2156952Sume * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3156952Sume * Copyright (c) 1995-1999 by Internet Software Consortium. 4156952Sume * 5156952Sume * Permission to use, copy, modify, and distribute this software for any 6156952Sume * purpose with or without fee is hereby granted, provided that the above 7156952Sume * copyright notice and this permission notice appear in all copies. 8156952Sume * 9156952Sume * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10156952Sume * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11156952Sume * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12156952Sume * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13156952Sume * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14156952Sume * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15156952Sume * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16156952Sume */ 17156952Sume 18156952Sume#if defined(LIBC_SCCS) && !defined(lint) 19174226Sumestatic const char rcsid[] = "$Id: res_data.c,v 1.3.18.2 2007/09/14 05:35:47 marka Exp $"; 20156952Sume#endif /* LIBC_SCCS and not lint */ 21156956Sume#include <sys/cdefs.h> 22156956Sume__FBSDID("$FreeBSD$"); 23156952Sume 24156952Sume#include "port_before.h" 25156952Sume 26156952Sume#include <sys/types.h> 27156952Sume#include <sys/param.h> 28156952Sume#include <sys/socket.h> 29156952Sume#include <sys/time.h> 30156952Sume 31156952Sume#include <netinet/in.h> 32156952Sume#include <arpa/inet.h> 33156952Sume#include <arpa/nameser.h> 34156952Sume 35156952Sume#include <ctype.h> 36156952Sume#include <netdb.h> 37156952Sume#include <resolv.h> 38156952Sume#include <res_update.h> 39156952Sume#include <stdio.h> 40156952Sume#include <stdlib.h> 41156952Sume#include <string.h> 42156952Sume#include <unistd.h> 43156952Sume 44156952Sume#include "port_after.h" 45156952Sume 46156952Sumeconst char *_res_opcodes[] = { 47156952Sume "QUERY", 48156952Sume "IQUERY", 49156952Sume "CQUERYM", 50170244Sume "CQUERYU", /*%< experimental */ 51170244Sume "NOTIFY", /*%< experimental */ 52156952Sume "UPDATE", 53156952Sume "6", 54156952Sume "7", 55156952Sume "8", 56156952Sume "9", 57156952Sume "10", 58156952Sume "11", 59156952Sume "12", 60156952Sume "13", 61156952Sume "ZONEINIT", 62156952Sume "ZONEREF", 63156952Sume}; 64156952Sume 65156952Sume#ifdef BIND_UPDATE 66156952Sumeconst char *_res_sectioncodes[] = { 67156952Sume "ZONE", 68156952Sume "PREREQUISITES", 69156952Sume "UPDATE", 70156952Sume "ADDITIONAL", 71156952Sume}; 72156952Sume#endif 73156952Sume 74156952Sume#ifndef __BIND_NOSTATIC 75156952Sume 76156952Sume/* Proto. */ 77156952Sume 78156952Sumeint res_ourserver_p(const res_state, const struct sockaddr_in *); 79156952Sume 80156952Sumeint 81156952Sumeres_init(void) { 82156952Sume extern int __res_vinit(res_state, int); 83156952Sume 84156952Sume /* 85156952Sume * These three fields used to be statically initialized. This made 86156952Sume * it hard to use this code in a shared library. It is necessary, 87156952Sume * now that we're doing dynamic initialization here, that we preserve 88156952Sume * the old semantics: if an application modifies one of these three 89156952Sume * fields of _res before res_init() is called, res_init() will not 90156952Sume * alter them. Of course, if an application is setting them to 91156952Sume * _zero_ before calling res_init(), hoping to override what used 92156952Sume * to be the static default, we can't detect it and unexpected results 93156952Sume * will follow. Zero for any of these fields would make no sense, 94156952Sume * so one can safely assume that the applications were already getting 95156952Sume * unexpected results. 96156952Sume * 97156952Sume * _res.options is tricky since some apps were known to diddle the bits 98156952Sume * before res_init() was first called. We can't replicate that semantic 99156952Sume * with dynamic initialization (they may have turned bits off that are 100156952Sume * set in RES_DEFAULT). Our solution is to declare such applications 101156952Sume * "broken". They could fool us by setting RES_INIT but none do (yet). 102156952Sume */ 103156952Sume if (!_res.retrans) 104156952Sume _res.retrans = RES_TIMEOUT; 105156952Sume if (!_res.retry) 106156956Sume _res.retry = RES_DFLRETRY; 107156952Sume if (!(_res.options & RES_INIT)) 108156952Sume _res.options = RES_DEFAULT; 109156952Sume 110156952Sume /* 111156952Sume * This one used to initialize implicitly to zero, so unless the app 112156952Sume * has set it to something in particular, we can randomize it now. 113156952Sume */ 114156952Sume if (!_res.id) 115156952Sume _res.id = res_randomid(); 116156952Sume 117156952Sume return (__res_vinit(&_res, 1)); 118156952Sume} 119156952Sume 120156952Sumevoid 121156952Sumep_query(const u_char *msg) { 122156952Sume fp_query(msg, stdout); 123156952Sume} 124156952Sume 125156952Sumevoid 126156952Sumefp_query(const u_char *msg, FILE *file) { 127156952Sume fp_nquery(msg, PACKETSZ, file); 128156952Sume} 129156952Sume 130156952Sumevoid 131156952Sumefp_nquery(const u_char *msg, int len, FILE *file) { 132156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) 133156952Sume return; 134156952Sume 135156952Sume res_pquery(&_res, msg, len, file); 136156952Sume} 137156952Sume 138156952Sumeint 139170244Sumeres_mkquery(int op, /*!< opcode of query */ 140170244Sume const char *dname, /*!< domain name */ 141170244Sume int class, int type, /*!< class and type of query */ 142170244Sume const u_char *data, /*!< resource record data */ 143170244Sume int datalen, /*!< length of data */ 144170244Sume const u_char *newrr_in, /*!< new rr for modify or append */ 145170244Sume u_char *buf, /*!< buffer to put query */ 146170244Sume int buflen) /*!< size of buffer */ 147156952Sume{ 148156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 149156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 150156952Sume return (-1); 151156952Sume } 152156952Sume return (res_nmkquery(&_res, op, dname, class, type, 153156952Sume data, datalen, 154156952Sume newrr_in, buf, buflen)); 155156952Sume} 156156952Sume 157156952Sumeint 158156952Sumeres_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { 159156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 160156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 161156952Sume return (-1); 162156952Sume } 163156952Sume 164156952Sume return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); 165156952Sume} 166156952Sume 167156952Sumeint 168170244Sumeres_query(const char *name, /*!< domain name */ 169170244Sume int class, int type, /*!< class and type of query */ 170170244Sume u_char *answer, /*!< buffer to put answer */ 171170244Sume int anslen) /*!< size of answer buffer */ 172156952Sume{ 173156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 174156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 175156952Sume return (-1); 176156952Sume } 177156952Sume return (res_nquery(&_res, name, class, type, answer, anslen)); 178156952Sume} 179156952Sume 180156956Sume#ifndef _LIBC 181156952Sumevoid 182156952Sumeres_send_setqhook(res_send_qhook hook) { 183156952Sume _res.qhook = hook; 184156952Sume} 185156952Sume 186156952Sumevoid 187156952Sumeres_send_setrhook(res_send_rhook hook) { 188156952Sume _res.rhook = hook; 189156952Sume} 190156956Sume#endif 191156952Sume 192156952Sumeint 193156952Sumeres_isourserver(const struct sockaddr_in *inp) { 194156952Sume return (res_ourserver_p(&_res, inp)); 195156952Sume} 196156952Sume 197156952Sumeint 198156952Sumeres_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { 199156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 200156952Sume /* errno should have been set by res_init() in this case. */ 201156952Sume return (-1); 202156952Sume } 203156952Sume 204156952Sume return (res_nsend(&_res, buf, buflen, ans, anssiz)); 205156952Sume} 206156952Sume 207156956Sume#ifndef _LIBC 208156952Sumeint 209156952Sumeres_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, 210156952Sume u_char *ans, int anssiz) 211156952Sume{ 212156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 213156952Sume /* errno should have been set by res_init() in this case. */ 214156952Sume return (-1); 215156952Sume } 216156952Sume 217156952Sume return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); 218156952Sume} 219156956Sume#endif 220156952Sume 221156952Sumevoid 222156952Sumeres_close(void) { 223156952Sume res_nclose(&_res); 224156952Sume} 225156952Sume 226156952Sumeint 227156952Sumeres_update(ns_updrec *rrecp_in) { 228156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 229156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 230156952Sume return (-1); 231156952Sume } 232156952Sume 233156952Sume return (res_nupdate(&_res, rrecp_in, NULL)); 234156952Sume} 235156952Sume 236156952Sumeint 237170244Sumeres_search(const char *name, /*!< domain name */ 238170244Sume int class, int type, /*!< class and type of query */ 239170244Sume u_char *answer, /*!< buffer to put answer */ 240170244Sume int anslen) /*!< size of answer */ 241156952Sume{ 242156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 243156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 244156952Sume return (-1); 245156952Sume } 246156952Sume 247156952Sume return (res_nsearch(&_res, name, class, type, answer, anslen)); 248156952Sume} 249156952Sume 250156952Sumeint 251156952Sumeres_querydomain(const char *name, 252156952Sume const char *domain, 253170244Sume int class, int type, /*!< class and type of query */ 254170244Sume u_char *answer, /*!< buffer to put answer */ 255170244Sume int anslen) /*!< size of answer */ 256156952Sume{ 257156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 258156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 259156952Sume return (-1); 260156952Sume } 261156952Sume 262156952Sume return (res_nquerydomain(&_res, name, domain, 263156952Sume class, type, 264156952Sume answer, anslen)); 265156952Sume} 266156952Sume 267156956Sumeint 268156956Sumeres_opt(int n0, u_char *buf, int buflen, int anslen) 269156956Sume{ 270156956Sume return (res_nopt(&_res, n0, buf, buflen, anslen)); 271156956Sume} 272156956Sume 273156952Sumeconst char * 274156952Sumehostalias(const char *name) { 275156952Sume static char abuf[MAXDNAME]; 276156952Sume 277156952Sume return (res_hostalias(&_res, name, abuf, sizeof abuf)); 278156952Sume} 279156952Sume 280156952Sume#ifdef ultrix 281156952Sumeint 282156952Sumelocal_hostname_length(const char *hostname) { 283156952Sume int len_host, len_domain; 284156952Sume 285156952Sume if (!*_res.defdname) 286156952Sume res_init(); 287156952Sume len_host = strlen(hostname); 288156952Sume len_domain = strlen(_res.defdname); 289156952Sume if (len_host > len_domain && 290156952Sume !strcasecmp(hostname + len_host - len_domain, _res.defdname) && 291156952Sume hostname[len_host - len_domain - 1] == '.') 292156952Sume return (len_host - len_domain - 1); 293156952Sume return (0); 294156952Sume} 295156952Sume#endif /*ultrix*/ 296156952Sume 297156956Sume/* 298156956Sume * Weak aliases for applications that use certain private entry points, 299156956Sume * and fail to include <resolv.h>. 300156956Sume */ 301156956Sume#undef res_init 302156956Sume__weak_reference(__res_init, res_init); 303156956Sume#undef p_query 304156956Sume__weak_reference(__p_query, p_query); 305156956Sume#undef res_mkquery 306156956Sume__weak_reference(__res_mkquery, res_mkquery); 307156956Sume#undef res_query 308156956Sume__weak_reference(__res_query, res_query); 309156956Sume#undef res_send 310156956Sume__weak_reference(__res_send, res_send); 311156956Sume#undef res_close 312156956Sume__weak_reference(__res_close, _res_close); 313156956Sume#undef res_search 314156956Sume__weak_reference(__res_search, res_search); 315156956Sume#undef res_querydomain 316156956Sume__weak_reference(__res_querydomain, res_querydomain); 317156956Sume 318156952Sume#endif 319170244Sume 320170244Sume/*! \file */ 321