res_data.c revision 156956
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) 19156952Sumestatic const char rcsid[] = "$Id: res_data.c,v 1.1.206.2 2004/03/16 12:34:18 marka Exp $"; 20156952Sume#endif /* LIBC_SCCS and not lint */ 21156956Sume#include <sys/cdefs.h> 22156956Sume__FBSDID("$FreeBSD: head/lib/libc/resolv/res_data.c 156956 2006-03-21 15:37:16Z 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> 38156956Sume#ifndef _LIBC 39156952Sume#include <res_update.h> 40156956Sume#endif 41156952Sume#include <stdio.h> 42156952Sume#include <stdlib.h> 43156952Sume#include <string.h> 44156952Sume#include <unistd.h> 45156952Sume 46156952Sume#include "port_after.h" 47156952Sume 48156952Sumeconst char *_res_opcodes[] = { 49156952Sume "QUERY", 50156952Sume "IQUERY", 51156952Sume "CQUERYM", 52156952Sume "CQUERYU", /* experimental */ 53156952Sume "NOTIFY", /* experimental */ 54156952Sume "UPDATE", 55156952Sume "6", 56156952Sume "7", 57156952Sume "8", 58156952Sume "9", 59156952Sume "10", 60156952Sume "11", 61156952Sume "12", 62156952Sume "13", 63156952Sume "ZONEINIT", 64156952Sume "ZONEREF", 65156952Sume}; 66156952Sume 67156952Sume#ifdef BIND_UPDATE 68156952Sumeconst char *_res_sectioncodes[] = { 69156952Sume "ZONE", 70156952Sume "PREREQUISITES", 71156952Sume "UPDATE", 72156952Sume "ADDITIONAL", 73156952Sume}; 74156952Sume#endif 75156952Sume 76156952Sume#ifndef __BIND_NOSTATIC 77156952Sume 78156952Sume/* Proto. */ 79156952Sume 80156952Sumeint res_ourserver_p(const res_state, const struct sockaddr_in *); 81156952Sume 82156952Sumeint 83156952Sumeres_init(void) { 84156952Sume extern int __res_vinit(res_state, int); 85156952Sume 86156952Sume /* 87156952Sume * These three fields used to be statically initialized. This made 88156952Sume * it hard to use this code in a shared library. It is necessary, 89156952Sume * now that we're doing dynamic initialization here, that we preserve 90156952Sume * the old semantics: if an application modifies one of these three 91156952Sume * fields of _res before res_init() is called, res_init() will not 92156952Sume * alter them. Of course, if an application is setting them to 93156952Sume * _zero_ before calling res_init(), hoping to override what used 94156952Sume * to be the static default, we can't detect it and unexpected results 95156952Sume * will follow. Zero for any of these fields would make no sense, 96156952Sume * so one can safely assume that the applications were already getting 97156952Sume * unexpected results. 98156952Sume * 99156952Sume * _res.options is tricky since some apps were known to diddle the bits 100156952Sume * before res_init() was first called. We can't replicate that semantic 101156952Sume * with dynamic initialization (they may have turned bits off that are 102156952Sume * set in RES_DEFAULT). Our solution is to declare such applications 103156952Sume * "broken". They could fool us by setting RES_INIT but none do (yet). 104156952Sume */ 105156952Sume if (!_res.retrans) 106156952Sume _res.retrans = RES_TIMEOUT; 107156952Sume if (!_res.retry) 108156956Sume _res.retry = RES_DFLRETRY; 109156952Sume if (!(_res.options & RES_INIT)) 110156952Sume _res.options = RES_DEFAULT; 111156952Sume 112156952Sume /* 113156952Sume * This one used to initialize implicitly to zero, so unless the app 114156952Sume * has set it to something in particular, we can randomize it now. 115156952Sume */ 116156952Sume if (!_res.id) 117156952Sume _res.id = res_randomid(); 118156952Sume 119156952Sume return (__res_vinit(&_res, 1)); 120156952Sume} 121156952Sume 122156952Sumevoid 123156952Sumep_query(const u_char *msg) { 124156952Sume fp_query(msg, stdout); 125156952Sume} 126156952Sume 127156952Sumevoid 128156952Sumefp_query(const u_char *msg, FILE *file) { 129156952Sume fp_nquery(msg, PACKETSZ, file); 130156952Sume} 131156952Sume 132156952Sumevoid 133156952Sumefp_nquery(const u_char *msg, int len, FILE *file) { 134156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) 135156952Sume return; 136156952Sume 137156952Sume res_pquery(&_res, msg, len, file); 138156952Sume} 139156952Sume 140156952Sumeint 141156952Sumeres_mkquery(int op, /* opcode of query */ 142156952Sume const char *dname, /* domain name */ 143156952Sume int class, int type, /* class and type of query */ 144156952Sume const u_char *data, /* resource record data */ 145156952Sume int datalen, /* length of data */ 146156952Sume const u_char *newrr_in, /* new rr for modify or append */ 147156952Sume u_char *buf, /* buffer to put query */ 148156952Sume int buflen) /* size of buffer */ 149156952Sume{ 150156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 151156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 152156952Sume return (-1); 153156952Sume } 154156952Sume return (res_nmkquery(&_res, op, dname, class, type, 155156952Sume data, datalen, 156156952Sume newrr_in, buf, buflen)); 157156952Sume} 158156952Sume 159156956Sume#ifndef _LIBC 160156952Sumeint 161156952Sumeres_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { 162156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 163156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 164156952Sume return (-1); 165156952Sume } 166156952Sume 167156952Sume return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); 168156952Sume} 169156956Sume#endif 170156952Sume 171156952Sumeint 172156952Sumeres_query(const char *name, /* domain name */ 173156952Sume int class, int type, /* class and type of query */ 174156952Sume u_char *answer, /* buffer to put answer */ 175156952Sume int anslen) /* size of answer buffer */ 176156952Sume{ 177156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 178156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 179156952Sume return (-1); 180156952Sume } 181156952Sume return (res_nquery(&_res, name, class, type, answer, anslen)); 182156952Sume} 183156952Sume 184156956Sume#ifndef _LIBC 185156952Sumevoid 186156952Sumeres_send_setqhook(res_send_qhook hook) { 187156952Sume _res.qhook = hook; 188156952Sume} 189156952Sume 190156952Sumevoid 191156952Sumeres_send_setrhook(res_send_rhook hook) { 192156952Sume _res.rhook = hook; 193156952Sume} 194156956Sume#endif 195156952Sume 196156952Sumeint 197156952Sumeres_isourserver(const struct sockaddr_in *inp) { 198156952Sume return (res_ourserver_p(&_res, inp)); 199156952Sume} 200156952Sume 201156952Sumeint 202156952Sumeres_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { 203156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 204156952Sume /* errno should have been set by res_init() in this case. */ 205156952Sume return (-1); 206156952Sume } 207156952Sume 208156952Sume return (res_nsend(&_res, buf, buflen, ans, anssiz)); 209156952Sume} 210156952Sume 211156956Sume#ifndef _LIBC 212156952Sumeint 213156952Sumeres_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, 214156952Sume u_char *ans, int anssiz) 215156952Sume{ 216156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 217156952Sume /* errno should have been set by res_init() in this case. */ 218156952Sume return (-1); 219156952Sume } 220156952Sume 221156952Sume return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); 222156952Sume} 223156956Sume#endif 224156952Sume 225156952Sumevoid 226156952Sumeres_close(void) { 227156952Sume res_nclose(&_res); 228156952Sume} 229156952Sume 230156956Sume#ifndef _LIBC 231156952Sumeint 232156952Sumeres_update(ns_updrec *rrecp_in) { 233156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 234156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 235156952Sume return (-1); 236156952Sume } 237156952Sume 238156952Sume return (res_nupdate(&_res, rrecp_in, NULL)); 239156952Sume} 240156956Sume#endif 241156952Sume 242156952Sumeint 243156952Sumeres_search(const char *name, /* domain name */ 244156952Sume int class, int type, /* class and type of query */ 245156952Sume u_char *answer, /* buffer to put answer */ 246156952Sume int anslen) /* size of answer */ 247156952Sume{ 248156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 249156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 250156952Sume return (-1); 251156952Sume } 252156952Sume 253156952Sume return (res_nsearch(&_res, name, class, type, answer, anslen)); 254156952Sume} 255156952Sume 256156952Sumeint 257156952Sumeres_querydomain(const char *name, 258156952Sume const char *domain, 259156952Sume int class, int type, /* class and type of query */ 260156952Sume u_char *answer, /* buffer to put answer */ 261156952Sume int anslen) /* size of answer */ 262156952Sume{ 263156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 264156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 265156952Sume return (-1); 266156952Sume } 267156952Sume 268156952Sume return (res_nquerydomain(&_res, name, domain, 269156952Sume class, type, 270156952Sume answer, anslen)); 271156952Sume} 272156952Sume 273156956Sumeint 274156956Sumeres_opt(int n0, u_char *buf, int buflen, int anslen) 275156956Sume{ 276156956Sume return (res_nopt(&_res, n0, buf, buflen, anslen)); 277156956Sume} 278156956Sume 279156952Sumeconst char * 280156952Sumehostalias(const char *name) { 281156952Sume static char abuf[MAXDNAME]; 282156952Sume 283156952Sume return (res_hostalias(&_res, name, abuf, sizeof abuf)); 284156952Sume} 285156952Sume 286156952Sume#ifdef ultrix 287156952Sumeint 288156952Sumelocal_hostname_length(const char *hostname) { 289156952Sume int len_host, len_domain; 290156952Sume 291156952Sume if (!*_res.defdname) 292156952Sume res_init(); 293156952Sume len_host = strlen(hostname); 294156952Sume len_domain = strlen(_res.defdname); 295156952Sume if (len_host > len_domain && 296156952Sume !strcasecmp(hostname + len_host - len_domain, _res.defdname) && 297156952Sume hostname[len_host - len_domain - 1] == '.') 298156952Sume return (len_host - len_domain - 1); 299156952Sume return (0); 300156952Sume} 301156952Sume#endif /*ultrix*/ 302156952Sume 303156956Sume/* 304156956Sume * Weak aliases for applications that use certain private entry points, 305156956Sume * and fail to include <resolv.h>. 306156956Sume */ 307156956Sume#undef res_init 308156956Sume__weak_reference(__res_init, res_init); 309156956Sume#undef p_query 310156956Sume__weak_reference(__p_query, p_query); 311156956Sume#undef res_mkquery 312156956Sume__weak_reference(__res_mkquery, res_mkquery); 313156956Sume#undef res_query 314156956Sume__weak_reference(__res_query, res_query); 315156956Sume#undef res_send 316156956Sume__weak_reference(__res_send, res_send); 317156956Sume#undef res_close 318156956Sume__weak_reference(__res_close, _res_close); 319156956Sume#undef res_search 320156956Sume__weak_reference(__res_search, res_search); 321156956Sume#undef res_querydomain 322156956Sume__weak_reference(__res_querydomain, res_querydomain); 323156956Sume 324156952Sume#endif 325