res_data.c revision 156952
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 */ 21156952Sume 22156952Sume#include "port_before.h" 23156952Sume 24156952Sume#include <sys/types.h> 25156952Sume#include <sys/param.h> 26156952Sume#include <sys/socket.h> 27156952Sume#include <sys/time.h> 28156952Sume 29156952Sume#include <netinet/in.h> 30156952Sume#include <arpa/inet.h> 31156952Sume#include <arpa/nameser.h> 32156952Sume 33156952Sume#include <ctype.h> 34156952Sume#include <netdb.h> 35156952Sume#include <resolv.h> 36156952Sume#include <res_update.h> 37156952Sume#include <stdio.h> 38156952Sume#include <stdlib.h> 39156952Sume#include <string.h> 40156952Sume#include <unistd.h> 41156952Sume 42156952Sume#include "port_after.h" 43156952Sume#undef _res 44156952Sume 45156952Sumeconst char *_res_opcodes[] = { 46156952Sume "QUERY", 47156952Sume "IQUERY", 48156952Sume "CQUERYM", 49156952Sume "CQUERYU", /* experimental */ 50156952Sume "NOTIFY", /* experimental */ 51156952Sume "UPDATE", 52156952Sume "6", 53156952Sume "7", 54156952Sume "8", 55156952Sume "9", 56156952Sume "10", 57156952Sume "11", 58156952Sume "12", 59156952Sume "13", 60156952Sume "ZONEINIT", 61156952Sume "ZONEREF", 62156952Sume}; 63156952Sume 64156952Sume#ifdef BIND_UPDATE 65156952Sumeconst char *_res_sectioncodes[] = { 66156952Sume "ZONE", 67156952Sume "PREREQUISITES", 68156952Sume "UPDATE", 69156952Sume "ADDITIONAL", 70156952Sume}; 71156952Sume#endif 72156952Sume 73156952Sume#ifndef __BIND_NOSTATIC 74156952Sumestruct __res_state _res 75156952Sume# if defined(__BIND_RES_TEXT) 76156952Sume = { RES_TIMEOUT, } /* Motorola, et al. */ 77156952Sume# endif 78156952Sume ; 79156952Sume 80156952Sume/* Proto. */ 81156952Sume 82156952Sumeint res_ourserver_p(const res_state, const struct sockaddr_in *); 83156952Sume 84156952Sumeint 85156952Sumeres_init(void) { 86156952Sume extern int __res_vinit(res_state, int); 87156952Sume 88156952Sume /* 89156952Sume * These three fields used to be statically initialized. This made 90156952Sume * it hard to use this code in a shared library. It is necessary, 91156952Sume * now that we're doing dynamic initialization here, that we preserve 92156952Sume * the old semantics: if an application modifies one of these three 93156952Sume * fields of _res before res_init() is called, res_init() will not 94156952Sume * alter them. Of course, if an application is setting them to 95156952Sume * _zero_ before calling res_init(), hoping to override what used 96156952Sume * to be the static default, we can't detect it and unexpected results 97156952Sume * will follow. Zero for any of these fields would make no sense, 98156952Sume * so one can safely assume that the applications were already getting 99156952Sume * unexpected results. 100156952Sume * 101156952Sume * _res.options is tricky since some apps were known to diddle the bits 102156952Sume * before res_init() was first called. We can't replicate that semantic 103156952Sume * with dynamic initialization (they may have turned bits off that are 104156952Sume * set in RES_DEFAULT). Our solution is to declare such applications 105156952Sume * "broken". They could fool us by setting RES_INIT but none do (yet). 106156952Sume */ 107156952Sume if (!_res.retrans) 108156952Sume _res.retrans = RES_TIMEOUT; 109156952Sume if (!_res.retry) 110156952Sume _res.retry = 4; 111156952Sume if (!(_res.options & RES_INIT)) 112156952Sume _res.options = RES_DEFAULT; 113156952Sume 114156952Sume /* 115156952Sume * This one used to initialize implicitly to zero, so unless the app 116156952Sume * has set it to something in particular, we can randomize it now. 117156952Sume */ 118156952Sume if (!_res.id) 119156952Sume _res.id = res_randomid(); 120156952Sume 121156952Sume return (__res_vinit(&_res, 1)); 122156952Sume} 123156952Sume 124156952Sumevoid 125156952Sumep_query(const u_char *msg) { 126156952Sume fp_query(msg, stdout); 127156952Sume} 128156952Sume 129156952Sumevoid 130156952Sumefp_query(const u_char *msg, FILE *file) { 131156952Sume fp_nquery(msg, PACKETSZ, file); 132156952Sume} 133156952Sume 134156952Sumevoid 135156952Sumefp_nquery(const u_char *msg, int len, FILE *file) { 136156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) 137156952Sume return; 138156952Sume 139156952Sume res_pquery(&_res, msg, len, file); 140156952Sume} 141156952Sume 142156952Sumeint 143156952Sumeres_mkquery(int op, /* opcode of query */ 144156952Sume const char *dname, /* domain name */ 145156952Sume int class, int type, /* class and type of query */ 146156952Sume const u_char *data, /* resource record data */ 147156952Sume int datalen, /* length of data */ 148156952Sume const u_char *newrr_in, /* new rr for modify or append */ 149156952Sume u_char *buf, /* buffer to put query */ 150156952Sume int buflen) /* size of buffer */ 151156952Sume{ 152156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 153156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 154156952Sume return (-1); 155156952Sume } 156156952Sume return (res_nmkquery(&_res, op, dname, class, type, 157156952Sume data, datalen, 158156952Sume newrr_in, buf, buflen)); 159156952Sume} 160156952Sume 161156952Sumeint 162156952Sumeres_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { 163156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 164156952Sume RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 165156952Sume return (-1); 166156952Sume } 167156952Sume 168156952Sume return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); 169156952Sume} 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 184156952Sumevoid 185156952Sumeres_send_setqhook(res_send_qhook hook) { 186156952Sume _res.qhook = hook; 187156952Sume} 188156952Sume 189156952Sumevoid 190156952Sumeres_send_setrhook(res_send_rhook hook) { 191156952Sume _res.rhook = hook; 192156952Sume} 193156952Sume 194156952Sumeint 195156952Sumeres_isourserver(const struct sockaddr_in *inp) { 196156952Sume return (res_ourserver_p(&_res, inp)); 197156952Sume} 198156952Sume 199156952Sumeint 200156952Sumeres_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { 201156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 202156952Sume /* errno should have been set by res_init() in this case. */ 203156952Sume return (-1); 204156952Sume } 205156952Sume 206156952Sume return (res_nsend(&_res, buf, buflen, ans, anssiz)); 207156952Sume} 208156952Sume 209156952Sumeint 210156952Sumeres_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, 211156952Sume u_char *ans, int anssiz) 212156952Sume{ 213156952Sume if ((_res.options & RES_INIT) == 0U && res_init() == -1) { 214156952Sume /* errno should have been set by res_init() in this case. */ 215156952Sume return (-1); 216156952Sume } 217156952Sume 218156952Sume return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); 219156952Sume} 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 237156952Sumeres_search(const char *name, /* domain name */ 238156952Sume int class, int type, /* class and type of query */ 239156952Sume u_char *answer, /* buffer to put answer */ 240156952Sume 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, 253156952Sume int class, int type, /* class and type of query */ 254156952Sume u_char *answer, /* buffer to put answer */ 255156952Sume 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 267156952Sumeconst char * 268156952Sumehostalias(const char *name) { 269156952Sume static char abuf[MAXDNAME]; 270156952Sume 271156952Sume return (res_hostalias(&_res, name, abuf, sizeof abuf)); 272156952Sume} 273156952Sume 274156952Sume#ifdef ultrix 275156952Sumeint 276156952Sumelocal_hostname_length(const char *hostname) { 277156952Sume int len_host, len_domain; 278156952Sume 279156952Sume if (!*_res.defdname) 280156952Sume res_init(); 281156952Sume len_host = strlen(hostname); 282156952Sume len_domain = strlen(_res.defdname); 283156952Sume if (len_host > len_domain && 284156952Sume !strcasecmp(hostname + len_host - len_domain, _res.defdname) && 285156952Sume hostname[len_host - len_domain - 1] == '.') 286156952Sume return (len_host - len_domain - 1); 287156952Sume return (0); 288156952Sume} 289156952Sume#endif /*ultrix*/ 290156952Sume 291156952Sume#endif 292