res_data.c revision 269867
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) 19269867Sumestatic const char rcsid[] = "$Id: res_data.c,v 1.7 2008/12/11 09:59:00 marka Exp $"; 20156952Sume#endif /* LIBC_SCCS and not lint */ 21156956Sume#include <sys/cdefs.h> 22156956Sume__FBSDID("$FreeBSD: head/lib/libc/resolv/res_data.c 269867 2014-08-12 12:36:06Z ume $"); 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 return (__res_vinit(&_res, 1)); 111156952Sume} 112156952Sume 113156952Sumevoid 114156952Sumep_query(const u_char *msg) { 115156952Sume fp_query(msg, stdout); 116156952Sume} 117156952Sume 118156952Sumevoid 119156952Sumefp_query(const u_char *msg, FILE *file) { 120156952Sume fp_nquery(msg, PACKETSZ, file); 121156952Sume} 122156952Sume 123156952Sumevoid 124156952Sumefp_nquery(const u_char *msg, int len, FILE *file) { 125156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) 126156952Sume return; 127156952Sume 128156952Sume res_pquery(&_res, msg, len, file); 129156952Sume} 130156952Sume 131156952Sumeint 132170244Sumeres_mkquery(int op, /*!< opcode of query */ 133170244Sume const char *dname, /*!< domain name */ 134170244Sume int class, int type, /*!< class and type of query */ 135170244Sume const u_char *data, /*!< resource record data */ 136170244Sume int datalen, /*!< length of data */ 137170244Sume const u_char *newrr_in, /*!< new rr for modify or append */ 138170244Sume u_char *buf, /*!< buffer to put query */ 139170244Sume int buflen) /*!< size of buffer */ 140156952Sume{ 141156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 142156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 143156952Sume return (-1); 144156952Sume } 145156952Sume return (res_nmkquery(&_res, op, dname, class, type, 146156952Sume data, datalen, 147156952Sume newrr_in, buf, buflen)); 148156952Sume} 149156952Sume 150156952Sumeint 151156952Sumeres_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { 152156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 153156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 154156952Sume return (-1); 155156952Sume } 156156952Sume 157156952Sume return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); 158156952Sume} 159156952Sume 160156952Sumeint 161170244Sumeres_query(const char *name, /*!< domain name */ 162170244Sume int class, int type, /*!< class and type of query */ 163170244Sume u_char *answer, /*!< buffer to put answer */ 164170244Sume int anslen) /*!< size of answer buffer */ 165156952Sume{ 166156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 167156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 168156952Sume return (-1); 169156952Sume } 170156952Sume return (res_nquery(&_res, name, class, type, answer, anslen)); 171156952Sume} 172156952Sume 173156956Sume#ifndef _LIBC 174156952Sumevoid 175156952Sumeres_send_setqhook(res_send_qhook hook) { 176156952Sume _res.qhook = hook; 177156952Sume} 178156952Sume 179156952Sumevoid 180156952Sumeres_send_setrhook(res_send_rhook hook) { 181156952Sume _res.rhook = hook; 182156952Sume} 183156956Sume#endif 184156952Sume 185156952Sumeint 186156952Sumeres_isourserver(const struct sockaddr_in *inp) { 187156952Sume return (res_ourserver_p(&_res, inp)); 188156952Sume} 189156952Sume 190156952Sumeint 191156952Sumeres_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { 192156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 193156952Sume /* errno should have been set by res_init() in this case. */ 194156952Sume return (-1); 195156952Sume } 196156952Sume 197156952Sume return (res_nsend(&_res, buf, buflen, ans, anssiz)); 198156952Sume} 199156952Sume 200156956Sume#ifndef _LIBC 201156952Sumeint 202156952Sumeres_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, 203156952Sume u_char *ans, int anssiz) 204156952Sume{ 205156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 206156952Sume /* errno should have been set by res_init() in this case. */ 207156952Sume return (-1); 208156952Sume } 209156952Sume 210156952Sume return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); 211156952Sume} 212156956Sume#endif 213156952Sume 214156952Sumevoid 215156952Sumeres_close(void) { 216156952Sume res_nclose(&_res); 217156952Sume} 218156952Sume 219156952Sumeint 220156952Sumeres_update(ns_updrec *rrecp_in) { 221156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 222156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 223156952Sume return (-1); 224156952Sume } 225156952Sume 226156952Sume return (res_nupdate(&_res, rrecp_in, NULL)); 227156952Sume} 228156952Sume 229156952Sumeint 230170244Sumeres_search(const char *name, /*!< domain name */ 231170244Sume int class, int type, /*!< class and type of query */ 232170244Sume u_char *answer, /*!< buffer to put answer */ 233170244Sume int anslen) /*!< size of answer */ 234156952Sume{ 235156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 236156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 237156952Sume return (-1); 238156952Sume } 239156952Sume 240156952Sume return (res_nsearch(&_res, name, class, type, answer, anslen)); 241156952Sume} 242156952Sume 243156952Sumeint 244156952Sumeres_querydomain(const char *name, 245156952Sume const char *domain, 246170244Sume int class, int type, /*!< class and type of query */ 247170244Sume u_char *answer, /*!< buffer to put answer */ 248170244Sume int anslen) /*!< size of answer */ 249156952Sume{ 250156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 251156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 252156952Sume return (-1); 253156952Sume } 254156952Sume 255156952Sume return (res_nquerydomain(&_res, name, domain, 256156952Sume class, type, 257156952Sume answer, anslen)); 258156952Sume} 259156952Sume 260269867Sumeu_int 261269867Sumeres_randomid(void) { 262269867Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 263269867Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 264269867Sume return (-1); 265269867Sume } 266269867Sume 267269867Sume return (res_nrandomid(&_res)); 268269867Sume} 269269867Sume 270156956Sumeint 271156956Sumeres_opt(int n0, u_char *buf, int buflen, int anslen) 272156956Sume{ 273156956Sume return (res_nopt(&_res, n0, buf, buflen, anslen)); 274156956Sume} 275156956Sume 276156952Sumeconst char * 277156952Sumehostalias(const char *name) { 278156952Sume static char abuf[MAXDNAME]; 279156952Sume 280156952Sume return (res_hostalias(&_res, name, abuf, sizeof abuf)); 281156952Sume} 282156952Sume 283156952Sume#ifdef ultrix 284156952Sumeint 285156952Sumelocal_hostname_length(const char *hostname) { 286156952Sume int len_host, len_domain; 287156952Sume 288156952Sume if (!*_res.defdname) 289156952Sume res_init(); 290156952Sume len_host = strlen(hostname); 291156952Sume len_domain = strlen(_res.defdname); 292156952Sume if (len_host > len_domain && 293156952Sume !strcasecmp(hostname + len_host - len_domain, _res.defdname) && 294156952Sume hostname[len_host - len_domain - 1] == '.') 295156952Sume return (len_host - len_domain - 1); 296156952Sume return (0); 297156952Sume} 298156952Sume#endif /*ultrix*/ 299156952Sume 300156956Sume/* 301156956Sume * Weak aliases for applications that use certain private entry points, 302156956Sume * and fail to include <resolv.h>. 303156956Sume */ 304156956Sume#undef res_init 305156956Sume__weak_reference(__res_init, res_init); 306156956Sume#undef p_query 307156956Sume__weak_reference(__p_query, p_query); 308156956Sume#undef res_mkquery 309156956Sume__weak_reference(__res_mkquery, res_mkquery); 310156956Sume#undef res_query 311156956Sume__weak_reference(__res_query, res_query); 312156956Sume#undef res_send 313156956Sume__weak_reference(__res_send, res_send); 314156956Sume#undef res_close 315156956Sume__weak_reference(__res_close, _res_close); 316156956Sume#undef res_search 317156956Sume__weak_reference(__res_search, res_search); 318156956Sume#undef res_querydomain 319156956Sume__weak_reference(__res_querydomain, res_querydomain); 320156956Sume 321156952Sume#endif 322170244Sume 323170244Sume/*! \file */ 324