1 /* $NetBSD: res_data.c,v 1.14 2009/10/24 05:35:37 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 1995-1999 by Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 #if defined(LIBC_SCCS) && !defined(lint) 22 #ifdef notdef 23 static const char rcsid[] = "Id: res_data.c,v 1.7 2008/12/11 09:59:00 marka Exp"; 24 #else 25 __RCSID("$NetBSD: res_data.c,v 1.14 2009/10/24 05:35:37 christos Exp $"); 26 #endif 27 #endif /* LIBC_SCCS and not lint */ 28 29 #include "port_before.h" 30 31 #include "namespace.h" 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/socket.h> 35 #include <sys/time.h> 36 37 #include <netinet/in.h> 38 #include <arpa/inet.h> 39 #include <arpa/nameser.h> 40 41 #include <ctype.h> 42 #include <netdb.h> 43 #include <resolv.h> 44 #include <res_update.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include "port_after.h" 51 52 #include "res_private.h" 53 54 #ifdef __weak_alias 55 __weak_alias(res_init,_res_init) 56 __weak_alias(res_mkquery,_res_mkquery) 57 __weak_alias(res_query,_res_query) 58 __weak_alias(res_search,_res_search) 59 __weak_alias(res_send,__res_send) 60 __weak_alias(res_close,__res_close) 61 /* XXX: these leaked in the old bind8 libc */ 62 __weak_alias(res_querydomain,__res_querydomain) 63 __weak_alias(res_send_setqhook,__res_send_setqhook) 64 __weak_alias(res_send_setrhook,__res_send_setrhook) 65 #if 0 66 __weak_alias(p_query,__p_query) 67 __weak_alias(fp_query,__fp_query) 68 __weak_alias(fp_nquery,__fp_nquery) 69 __weak_alias(res_isourserver,__res_isourserver) 70 __weak_alias(res_opt,_res_opt) 71 __weak_alias(hostalias,__hostalias) 72 #endif 73 #endif 74 75 const char *_res_opcodes[] = { 76 "QUERY", 77 "IQUERY", 78 "CQUERYM", 79 "CQUERYU", /*%< experimental */ 80 "NOTIFY", /*%< experimental */ 81 "UPDATE", 82 "6", 83 "7", 84 "8", 85 "9", 86 "10", 87 "11", 88 "12", 89 "13", 90 "ZONEINIT", 91 "ZONEREF", 92 }; 93 94 #ifdef BIND_UPDATE 95 const char *_res_sectioncodes[] = { 96 "ZONE", 97 "PREREQUISITES", 98 "UPDATE", 99 "ADDITIONAL", 100 }; 101 #endif 102 103 #ifndef __BIND_NOSTATIC 104 extern struct __res_state _nres; 105 106 /* Proto. */ 107 108 int res_ourserver_p(const res_state, const struct sockaddr *); 109 110 int 111 res_init(void) { 112 int rv; 113 #ifdef COMPAT__RES 114 /* 115 * Compatibility with program that were accessing _res directly 116 * to set options. We keep another struct res that is the same 117 * size as the original res structure, and then copy fields to 118 * it so that we achieve the same initialization 119 */ 120 extern void *__res_get_old_state(void); 121 extern void __res_put_old_state(void *); 122 res_state ores = __res_get_old_state(); 123 124 if (ores->options != 0) 125 _nres.options = ores->options; 126 if (ores->retrans != 0) 127 _nres.retrans = ores->retrans; 128 if (ores->retry != 0) 129 _nres.retry = ores->retry; 130 #endif 131 132 /* 133 * These three fields used to be statically initialized. This made 134 * it hard to use this code in a shared library. It is necessary, 135 * now that we're doing dynamic initialization here, that we preserve 136 * the old semantics: if an application modifies one of these three 137 * fields of _res before res_init() is called, res_init() will not 138 * alter them. Of course, if an application is setting them to 139 * _zero_ before calling res_init(), hoping to override what used 140 * to be the static default, we can't detect it and unexpected results 141 * will follow. Zero for any of these fields would make no sense, 142 * so one can safely assume that the applications were already getting 143 * unexpected results. 144 * 145 * _nres.options is tricky since some apps were known to diddle the bits 146 * before res_init() was first called. We can't replicate that semantic 147 * with dynamic initialization (they may have turned bits off that are 148 * set in RES_DEFAULT). Our solution is to declare such applications 149 * "broken". They could fool us by setting RES_INIT but none do (yet). 150 */ 151 if (!_nres.retrans) 152 _nres.retrans = RES_TIMEOUT; 153 if (!_nres.retry) 154 _nres.retry = 4; 155 if (!(_nres.options & RES_INIT)) 156 _nres.options = RES_DEFAULT; 157 158 /* 159 * This one used to initialize implicitly to zero, so unless the app 160 * has set it to something in particular, we can randomize it now. 161 */ 162 if (!_nres.id) 163 _nres.id = res_nrandomid(&_nres); 164 165 rv = __res_vinit(&_nres, 1); 166 #ifdef COMPAT__RES 167 __res_put_old_state(&_nres); 168 #endif 169 return rv; 170 } 171 172 void 173 p_query(const u_char *msg) { 174 fp_query(msg, stdout); 175 } 176 177 void 178 fp_query(const u_char *msg, FILE *file) { 179 fp_nquery(msg, PACKETSZ, file); 180 } 181 182 void 183 fp_nquery(const u_char *msg, int len, FILE *file) { 184 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) 185 return; 186 187 res_pquery(&_nres, msg, len, file); 188 } 189 190 int 191 res_mkquery(int op, /*!< opcode of query */ 192 const char *dname, /*!< domain name */ 193 int class, int type, /*!< class and type of query */ 194 const u_char *data, /*!< resource record data */ 195 int datalen, /*!< length of data */ 196 const u_char *newrr_in, /*!< new rr for modify or append */ 197 u_char *buf, /*!< buffer to put query */ 198 int buflen) /*!< size of buffer */ 199 { 200 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 201 RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); 202 return (-1); 203 } 204 return (res_nmkquery(&_nres, op, dname, class, type, 205 data, datalen, 206 newrr_in, buf, buflen)); 207 } 208 209 #ifdef _LIBRESOLV 210 int 211 res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { 212 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 213 RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); 214 return (-1); 215 } 216 217 return (res_nmkupdate(&_nres, rrecp_in, buf, buflen)); 218 } 219 #endif 220 221 int 222 res_query(const char *name, /*!< domain name */ 223 int class, int type, /*!< class and type of query */ 224 u_char *answer, /*!< buffer to put answer */ 225 int anslen) /*!< size of answer buffer */ 226 { 227 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 228 RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); 229 return (-1); 230 } 231 return (res_nquery(&_nres, name, class, type, answer, anslen)); 232 } 233 234 void 235 res_send_setqhook(res_send_qhook hook) { 236 _nres.qhook = hook; 237 } 238 239 void 240 res_send_setrhook(res_send_rhook hook) { 241 _nres.rhook = hook; 242 } 243 244 int 245 res_isourserver(const struct sockaddr_in *inp) { 246 return (res_ourserver_p(&_nres, (const struct sockaddr *)(const void *)inp)); 247 } 248 249 int 250 res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { 251 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 252 /* errno should have been set by res_init() in this case. */ 253 return (-1); 254 } 255 256 return (res_nsend(&_nres, buf, buflen, ans, anssiz)); 257 } 258 259 #ifdef _LIBRESOLV 260 int 261 res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, 262 u_char *ans, int anssiz) 263 { 264 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 265 /* errno should have been set by res_init() in this case. */ 266 return (-1); 267 } 268 269 return (res_nsendsigned(&_nres, buf, buflen, key, ans, anssiz)); 270 } 271 #endif 272 273 void 274 res_close(void) { 275 res_nclose(&_nres); 276 } 277 278 #ifdef _LIBRESOLV 279 int 280 res_update(ns_updrec *rrecp_in) { 281 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 282 RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); 283 return (-1); 284 } 285 286 return (res_nupdate(&_nres, rrecp_in, NULL)); 287 } 288 #endif 289 290 int 291 res_search(const char *name, /*!< domain name */ 292 int class, int type, /*!< class and type of query */ 293 u_char *answer, /*!< buffer to put answer */ 294 int anslen) /*!< size of answer */ 295 { 296 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 297 RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); 298 return (-1); 299 } 300 301 return (res_nsearch(&_nres, name, class, type, answer, anslen)); 302 } 303 304 int 305 res_querydomain(const char *name, 306 const char *domain, 307 int class, int type, /*!< class and type of query */ 308 u_char *answer, /*!< buffer to put answer */ 309 int anslen) /*!< size of answer */ 310 { 311 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 312 RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); 313 return (-1); 314 } 315 316 return (res_nquerydomain(&_nres, name, domain, 317 class, type, 318 answer, anslen)); 319 } 320 321 int 322 res_opt(int a, u_char *b, int c, int d) 323 { 324 return res_nopt(&_nres, a, b, c, d); 325 } 326 327 u_int 328 res_randomid(void) { 329 if ((_nres.options & RES_INIT) == 0U && res_init() == -1) { 330 RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); 331 return (u_int)-1; 332 } 333 334 return (res_nrandomid(&_nres)); 335 } 336 337 const char * 338 hostalias(const char *name) { 339 static char abuf[MAXDNAME]; 340 341 return (res_hostalias(&_nres, name, abuf, sizeof abuf)); 342 } 343 344 #ifdef ultrix 345 int 346 local_hostname_length(const char *hostname) { 347 int len_host, len_domain; 348 349 if (!*_nres.defdname) 350 res_init(); 351 len_host = strlen(hostname); 352 len_domain = strlen(_nres.defdname); 353 if (len_host > len_domain && 354 !strcasecmp(hostname + len_host - len_domain, _nres.defdname) && 355 hostname[len_host - len_domain - 1] == '.') 356 return (len_host - len_domain - 1); 357 return (0); 358 } 359 #endif /*ultrix*/ 360 361 #endif 362 363 /*! \file */ 364