1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 7*7c478bd9Sstevel@tonic-gate static const char rcsid[] = "$Id: hesiod.c,v 1.23 2002/07/18 02:07:45 marka Exp $"; 8*7c478bd9Sstevel@tonic-gate #endif 9*7c478bd9Sstevel@tonic-gate 10*7c478bd9Sstevel@tonic-gate /* 11*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996,1999 by Internet Software Consortium. 12*7c478bd9Sstevel@tonic-gate * 13*7c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 14*7c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 15*7c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 16*7c478bd9Sstevel@tonic-gate * 17*7c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 18*7c478bd9Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 19*7c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 20*7c478bd9Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 21*7c478bd9Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 22*7c478bd9Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 23*7c478bd9Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 24*7c478bd9Sstevel@tonic-gate * SOFTWARE. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * hesiod.c --- the core portion of the hesiod resolver. 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * This file is derived from the hesiod library from Project Athena; 37*7c478bd9Sstevel@tonic-gate * It has been extensively rewritten by Theodore Ts'o to have a more 38*7c478bd9Sstevel@tonic-gate * thread-safe interface. 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* Imports */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include "port_before.h" 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 46*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 47*7c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <errno.h> 50*7c478bd9Sstevel@tonic-gate #include <netdb.h> 51*7c478bd9Sstevel@tonic-gate #include <resolv.h> 52*7c478bd9Sstevel@tonic-gate #include <stdio.h> 53*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 54*7c478bd9Sstevel@tonic-gate #include <string.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include "port_after.h" 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #include "pathnames.h" 59*7c478bd9Sstevel@tonic-gate #include "hesiod.h" 60*7c478bd9Sstevel@tonic-gate #include "hesiod_p.h" 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate /* Forward */ 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate int hesiod_init(void **context); 65*7c478bd9Sstevel@tonic-gate void hesiod_end(void *context); 66*7c478bd9Sstevel@tonic-gate char * hesiod_to_bind(void *context, const char *name, 67*7c478bd9Sstevel@tonic-gate const char *type); 68*7c478bd9Sstevel@tonic-gate char ** hesiod_resolve(void *context, const char *name, 69*7c478bd9Sstevel@tonic-gate const char *type); 70*7c478bd9Sstevel@tonic-gate void hesiod_free_list(void *context, char **list); 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate static int parse_config_file(struct hesiod_p *ctx, const char *filename); 73*7c478bd9Sstevel@tonic-gate static char ** get_txt_records(struct hesiod_p *ctx, int class, 74*7c478bd9Sstevel@tonic-gate const char *name); 75*7c478bd9Sstevel@tonic-gate static int init(struct hesiod_p *ctx); 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate /* Public */ 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate /* 80*7c478bd9Sstevel@tonic-gate * This function is called to initialize a hesiod_p. 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate int 83*7c478bd9Sstevel@tonic-gate hesiod_init(void **context) { 84*7c478bd9Sstevel@tonic-gate struct hesiod_p *ctx; 85*7c478bd9Sstevel@tonic-gate char *cp; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate ctx = malloc(sizeof(struct hesiod_p)); 88*7c478bd9Sstevel@tonic-gate if (ctx == 0) { 89*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 90*7c478bd9Sstevel@tonic-gate return (-1); 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate #ifdef ORIGINAL_ISC_CODE 94*7c478bd9Sstevel@tonic-gate ctx->LHS = NULL; 95*7c478bd9Sstevel@tonic-gate ctx->RHS = NULL; 96*7c478bd9Sstevel@tonic-gate ctx->res = NULL; 97*7c478bd9Sstevel@tonic-gate #else 98*7c478bd9Sstevel@tonic-gate memset(ctx, 0, sizeof (*ctx)); 99*7c478bd9Sstevel@tonic-gate #endif /* ORIGINAL_ISC_CODE */ 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) { 102*7c478bd9Sstevel@tonic-gate #ifdef DEF_RHS 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * Use compiled in defaults. 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate ctx->LHS = malloc(strlen(DEF_LHS)+1); 107*7c478bd9Sstevel@tonic-gate ctx->RHS = malloc(strlen(DEF_RHS)+1); 108*7c478bd9Sstevel@tonic-gate if (ctx->LHS == 0 || ctx->RHS == 0) { 109*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 110*7c478bd9Sstevel@tonic-gate goto cleanup; 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate #ifdef HAVE_STRLCPY 113*7c478bd9Sstevel@tonic-gate strlcpy(ctx->LHS, DEF_LHS, strlen(DEF_LHS) + 1); 114*7c478bd9Sstevel@tonic-gate strlcpy(ctx->RHS, DEF_RHS, strlen(DEF_RHS) + 1); 115*7c478bd9Sstevel@tonic-gate #else 116*7c478bd9Sstevel@tonic-gate strcpy(ctx->LHS, DEF_LHS); 117*7c478bd9Sstevel@tonic-gate strcpy(ctx->RHS, DEF_RHS); 118*7c478bd9Sstevel@tonic-gate #endif 119*7c478bd9Sstevel@tonic-gate #else 120*7c478bd9Sstevel@tonic-gate goto cleanup; 121*7c478bd9Sstevel@tonic-gate #endif 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * The default RHS can be overridden by an environment 125*7c478bd9Sstevel@tonic-gate * variable. 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate if ((cp = getenv("HES_DOMAIN")) != NULL) { 128*7c478bd9Sstevel@tonic-gate size_t RHSlen = strlen(cp) + 2; 129*7c478bd9Sstevel@tonic-gate if (ctx->RHS) 130*7c478bd9Sstevel@tonic-gate free(ctx->RHS); 131*7c478bd9Sstevel@tonic-gate ctx->RHS = malloc(RHSlen); 132*7c478bd9Sstevel@tonic-gate if (!ctx->RHS) { 133*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 134*7c478bd9Sstevel@tonic-gate goto cleanup; 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate if (cp[0] == '.') { 137*7c478bd9Sstevel@tonic-gate #ifdef HAVE_STRLCPY 138*7c478bd9Sstevel@tonic-gate strlcpy(ctx->RHS, cp, RHSlen); 139*7c478bd9Sstevel@tonic-gate #else 140*7c478bd9Sstevel@tonic-gate strcpy(ctx->RHS, cp); 141*7c478bd9Sstevel@tonic-gate #endif 142*7c478bd9Sstevel@tonic-gate } else { 143*7c478bd9Sstevel@tonic-gate #ifdef HAVE_STRLCPY 144*7c478bd9Sstevel@tonic-gate strlcpy(ctx->RHS, ".", RHSlen); 145*7c478bd9Sstevel@tonic-gate #else 146*7c478bd9Sstevel@tonic-gate strcpy(ctx->RHS, "."); 147*7c478bd9Sstevel@tonic-gate #endif 148*7c478bd9Sstevel@tonic-gate #ifdef HAVE_STRLCAT 149*7c478bd9Sstevel@tonic-gate strlcat(ctx->RHS, cp, RHSlen); 150*7c478bd9Sstevel@tonic-gate #else 151*7c478bd9Sstevel@tonic-gate strcat(ctx->RHS, cp); 152*7c478bd9Sstevel@tonic-gate #endif 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* 157*7c478bd9Sstevel@tonic-gate * If there is no default hesiod realm set, we return an 158*7c478bd9Sstevel@tonic-gate * error. 159*7c478bd9Sstevel@tonic-gate */ 160*7c478bd9Sstevel@tonic-gate if (!ctx->RHS) { 161*7c478bd9Sstevel@tonic-gate errno = ENOEXEC; 162*7c478bd9Sstevel@tonic-gate goto cleanup; 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate #if 0 166*7c478bd9Sstevel@tonic-gate if (res_ninit(ctx->res) < 0) 167*7c478bd9Sstevel@tonic-gate goto cleanup; 168*7c478bd9Sstevel@tonic-gate #endif 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate *context = ctx; 171*7c478bd9Sstevel@tonic-gate return (0); 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate cleanup: 174*7c478bd9Sstevel@tonic-gate hesiod_end(ctx); 175*7c478bd9Sstevel@tonic-gate return (-1); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate /* 179*7c478bd9Sstevel@tonic-gate * This function deallocates the hesiod_p 180*7c478bd9Sstevel@tonic-gate */ 181*7c478bd9Sstevel@tonic-gate void 182*7c478bd9Sstevel@tonic-gate hesiod_end(void *context) { 183*7c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 184*7c478bd9Sstevel@tonic-gate int save_errno = errno; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate if (ctx->res) 187*7c478bd9Sstevel@tonic-gate res_nclose(ctx->res); 188*7c478bd9Sstevel@tonic-gate if (ctx->RHS) 189*7c478bd9Sstevel@tonic-gate free(ctx->RHS); 190*7c478bd9Sstevel@tonic-gate if (ctx->LHS) 191*7c478bd9Sstevel@tonic-gate free(ctx->LHS); 192*7c478bd9Sstevel@tonic-gate if (ctx->res && ctx->free_res) 193*7c478bd9Sstevel@tonic-gate (*ctx->free_res)(ctx->res); 194*7c478bd9Sstevel@tonic-gate free(ctx); 195*7c478bd9Sstevel@tonic-gate errno = save_errno; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * This function takes a hesiod (name, type) and returns a DNS 200*7c478bd9Sstevel@tonic-gate * name which is to be resolved. 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate char * 203*7c478bd9Sstevel@tonic-gate hesiod_to_bind(void *context, const char *name, const char *type) { 204*7c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 205*7c478bd9Sstevel@tonic-gate char *bindname; 206*7c478bd9Sstevel@tonic-gate char **rhs_list = NULL; 207*7c478bd9Sstevel@tonic-gate const char *RHS, *cp; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate /* Decide what our RHS is, and set cp to the end of the actual name. */ 210*7c478bd9Sstevel@tonic-gate if ((cp = strchr(name, '@')) != NULL) { 211*7c478bd9Sstevel@tonic-gate if (strchr(cp + 1, '.')) 212*7c478bd9Sstevel@tonic-gate RHS = cp + 1; 213*7c478bd9Sstevel@tonic-gate else if ((rhs_list = hesiod_resolve(context, cp + 1, 214*7c478bd9Sstevel@tonic-gate "rhs-extension")) != NULL) 215*7c478bd9Sstevel@tonic-gate RHS = *rhs_list; 216*7c478bd9Sstevel@tonic-gate else { 217*7c478bd9Sstevel@tonic-gate errno = ENOENT; 218*7c478bd9Sstevel@tonic-gate return (NULL); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate } else { 221*7c478bd9Sstevel@tonic-gate RHS = ctx->RHS; 222*7c478bd9Sstevel@tonic-gate cp = name + strlen(name); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * Allocate the space we need, including up to three periods and 227*7c478bd9Sstevel@tonic-gate * the terminating NUL. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) + 230*7c478bd9Sstevel@tonic-gate (ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) { 231*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 232*7c478bd9Sstevel@tonic-gate if (rhs_list) 233*7c478bd9Sstevel@tonic-gate hesiod_free_list(context, rhs_list); 234*7c478bd9Sstevel@tonic-gate return NULL; 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate /* Now put together the DNS name. */ 238*7c478bd9Sstevel@tonic-gate memcpy(bindname, name, cp - name); 239*7c478bd9Sstevel@tonic-gate bindname[cp - name] = '\0'; 240*7c478bd9Sstevel@tonic-gate strcat(bindname, "."); 241*7c478bd9Sstevel@tonic-gate strcat(bindname, type); 242*7c478bd9Sstevel@tonic-gate if (ctx->LHS) { 243*7c478bd9Sstevel@tonic-gate if (ctx->LHS[0] != '.') 244*7c478bd9Sstevel@tonic-gate strcat(bindname, "."); 245*7c478bd9Sstevel@tonic-gate strcat(bindname, ctx->LHS); 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate if (RHS[0] != '.') 248*7c478bd9Sstevel@tonic-gate strcat(bindname, "."); 249*7c478bd9Sstevel@tonic-gate strcat(bindname, RHS); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate if (rhs_list) 252*7c478bd9Sstevel@tonic-gate hesiod_free_list(context, rhs_list); 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate return (bindname); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * This is the core function. Given a hesiod (name, type), it 259*7c478bd9Sstevel@tonic-gate * returns an array of strings returned by the resolver. 260*7c478bd9Sstevel@tonic-gate */ 261*7c478bd9Sstevel@tonic-gate char ** 262*7c478bd9Sstevel@tonic-gate hesiod_resolve(void *context, const char *name, const char *type) { 263*7c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 264*7c478bd9Sstevel@tonic-gate char *bindname = hesiod_to_bind(context, name, type); 265*7c478bd9Sstevel@tonic-gate char **retvec; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate if (bindname == NULL) 268*7c478bd9Sstevel@tonic-gate return (NULL); 269*7c478bd9Sstevel@tonic-gate if (init(ctx) == -1) { 270*7c478bd9Sstevel@tonic-gate free(bindname); 271*7c478bd9Sstevel@tonic-gate return (NULL); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate if ((retvec = get_txt_records(ctx, C_IN, bindname))) { 275*7c478bd9Sstevel@tonic-gate free(bindname); 276*7c478bd9Sstevel@tonic-gate return (retvec); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate if (errno != ENOENT) 280*7c478bd9Sstevel@tonic-gate return (NULL); 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate retvec = get_txt_records(ctx, C_HS, bindname); 283*7c478bd9Sstevel@tonic-gate free(bindname); 284*7c478bd9Sstevel@tonic-gate return (retvec); 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate void 288*7c478bd9Sstevel@tonic-gate hesiod_free_list(void *context, char **list) { 289*7c478bd9Sstevel@tonic-gate char **p; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate UNUSED(context); 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate for (p = list; *p; p++) 294*7c478bd9Sstevel@tonic-gate free(*p); 295*7c478bd9Sstevel@tonic-gate free(list); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * This function parses the /etc/hesiod.conf file 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate static int 302*7c478bd9Sstevel@tonic-gate parse_config_file(struct hesiod_p *ctx, const char *filename) { 303*7c478bd9Sstevel@tonic-gate char *key, *data, *cp, **cpp; 304*7c478bd9Sstevel@tonic-gate char buf[MAXDNAME+7]; 305*7c478bd9Sstevel@tonic-gate FILE *fp; 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* 308*7c478bd9Sstevel@tonic-gate * Clear the existing configuration variable, just in case 309*7c478bd9Sstevel@tonic-gate * they're set. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate if (ctx->RHS) 312*7c478bd9Sstevel@tonic-gate free(ctx->RHS); 313*7c478bd9Sstevel@tonic-gate if (ctx->LHS) 314*7c478bd9Sstevel@tonic-gate free(ctx->LHS); 315*7c478bd9Sstevel@tonic-gate ctx->RHS = ctx->LHS = 0; 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate /* 318*7c478bd9Sstevel@tonic-gate * Now open and parse the file... 319*7c478bd9Sstevel@tonic-gate */ 320*7c478bd9Sstevel@tonic-gate if (!(fp = fopen(filename, "r"))) 321*7c478bd9Sstevel@tonic-gate return (-1); 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof(buf), fp) != NULL) { 324*7c478bd9Sstevel@tonic-gate cp = buf; 325*7c478bd9Sstevel@tonic-gate if (*cp == '#' || *cp == '\n' || *cp == '\r') 326*7c478bd9Sstevel@tonic-gate continue; 327*7c478bd9Sstevel@tonic-gate while(*cp == ' ' || *cp == '\t') 328*7c478bd9Sstevel@tonic-gate cp++; 329*7c478bd9Sstevel@tonic-gate key = cp; 330*7c478bd9Sstevel@tonic-gate while(*cp != ' ' && *cp != '\t' && *cp != '=') 331*7c478bd9Sstevel@tonic-gate cp++; 332*7c478bd9Sstevel@tonic-gate *cp++ = '\0'; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate while(*cp == ' ' || *cp == '\t' || *cp == '=') 335*7c478bd9Sstevel@tonic-gate cp++; 336*7c478bd9Sstevel@tonic-gate data = cp; 337*7c478bd9Sstevel@tonic-gate while(*cp != ' ' && *cp != '\n' && *cp != '\r') 338*7c478bd9Sstevel@tonic-gate cp++; 339*7c478bd9Sstevel@tonic-gate *cp++ = '\0'; 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate if (strcmp(key, "lhs") == 0) 342*7c478bd9Sstevel@tonic-gate cpp = &ctx->LHS; 343*7c478bd9Sstevel@tonic-gate else if (strcmp(key, "rhs") == 0) 344*7c478bd9Sstevel@tonic-gate cpp = &ctx->RHS; 345*7c478bd9Sstevel@tonic-gate else 346*7c478bd9Sstevel@tonic-gate continue; 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate *cpp = malloc(strlen(data) + 1); 349*7c478bd9Sstevel@tonic-gate if (!*cpp) { 350*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 351*7c478bd9Sstevel@tonic-gate goto cleanup; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate strcpy(*cpp, data); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate fclose(fp); 356*7c478bd9Sstevel@tonic-gate return (0); 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate cleanup: 359*7c478bd9Sstevel@tonic-gate fclose(fp); 360*7c478bd9Sstevel@tonic-gate if (ctx->RHS) 361*7c478bd9Sstevel@tonic-gate free(ctx->RHS); 362*7c478bd9Sstevel@tonic-gate if (ctx->LHS) 363*7c478bd9Sstevel@tonic-gate free(ctx->LHS); 364*7c478bd9Sstevel@tonic-gate ctx->RHS = ctx->LHS = 0; 365*7c478bd9Sstevel@tonic-gate return (-1); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate /* 369*7c478bd9Sstevel@tonic-gate * Given a DNS class and a DNS name, do a lookup for TXT records, and 370*7c478bd9Sstevel@tonic-gate * return a list of them. 371*7c478bd9Sstevel@tonic-gate */ 372*7c478bd9Sstevel@tonic-gate static char ** 373*7c478bd9Sstevel@tonic-gate get_txt_records(struct hesiod_p *ctx, int class, const char *name) { 374*7c478bd9Sstevel@tonic-gate struct { 375*7c478bd9Sstevel@tonic-gate int type; /* RR type */ 376*7c478bd9Sstevel@tonic-gate int class; /* RR class */ 377*7c478bd9Sstevel@tonic-gate int dlen; /* len of data section */ 378*7c478bd9Sstevel@tonic-gate u_char *data; /* pointer to data */ 379*7c478bd9Sstevel@tonic-gate } rr; 380*7c478bd9Sstevel@tonic-gate HEADER *hp; 381*7c478bd9Sstevel@tonic-gate u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; 382*7c478bd9Sstevel@tonic-gate u_char *cp, *erdata, *eom; 383*7c478bd9Sstevel@tonic-gate char *dst, *edst, **list; 384*7c478bd9Sstevel@tonic-gate int ancount, qdcount; 385*7c478bd9Sstevel@tonic-gate int i, j, n, skip; 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * Construct the query and send it. 389*7c478bd9Sstevel@tonic-gate */ 390*7c478bd9Sstevel@tonic-gate n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0, 391*7c478bd9Sstevel@tonic-gate NULL, qbuf, MAX_HESRESP); 392*7c478bd9Sstevel@tonic-gate if (n < 0) { 393*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 394*7c478bd9Sstevel@tonic-gate return (NULL); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP); 397*7c478bd9Sstevel@tonic-gate if (n < 0) { 398*7c478bd9Sstevel@tonic-gate errno = ECONNREFUSED; 399*7c478bd9Sstevel@tonic-gate return (NULL); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate if (n < HFIXEDSZ) { 402*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 403*7c478bd9Sstevel@tonic-gate return (NULL); 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* 407*7c478bd9Sstevel@tonic-gate * OK, parse the result. 408*7c478bd9Sstevel@tonic-gate */ 409*7c478bd9Sstevel@tonic-gate hp = (HEADER *) abuf; 410*7c478bd9Sstevel@tonic-gate ancount = ntohs(hp->ancount); 411*7c478bd9Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 412*7c478bd9Sstevel@tonic-gate cp = abuf + sizeof(HEADER); 413*7c478bd9Sstevel@tonic-gate eom = abuf + n; 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate /* Skip query, trying to get to the answer section which follows. */ 416*7c478bd9Sstevel@tonic-gate for (i = 0; i < qdcount; i++) { 417*7c478bd9Sstevel@tonic-gate skip = dn_skipname(cp, eom); 418*7c478bd9Sstevel@tonic-gate if (skip < 0 || cp + skip + QFIXEDSZ > eom) { 419*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 420*7c478bd9Sstevel@tonic-gate return (NULL); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate cp += skip + QFIXEDSZ; 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate list = malloc((ancount + 1) * sizeof(char *)); 426*7c478bd9Sstevel@tonic-gate if (!list) { 427*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 428*7c478bd9Sstevel@tonic-gate return (NULL); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate j = 0; 431*7c478bd9Sstevel@tonic-gate for (i = 0; i < ancount; i++) { 432*7c478bd9Sstevel@tonic-gate skip = dn_skipname(cp, eom); 433*7c478bd9Sstevel@tonic-gate if (skip < 0) { 434*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 435*7c478bd9Sstevel@tonic-gate goto cleanup; 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate cp += skip; 438*7c478bd9Sstevel@tonic-gate if (cp + 3 * INT16SZ + INT32SZ > eom) { 439*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 440*7c478bd9Sstevel@tonic-gate goto cleanup; 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate rr.type = ns_get16(cp); 443*7c478bd9Sstevel@tonic-gate cp += INT16SZ; 444*7c478bd9Sstevel@tonic-gate rr.class = ns_get16(cp); 445*7c478bd9Sstevel@tonic-gate cp += INT16SZ + INT32SZ; /* skip the ttl, too */ 446*7c478bd9Sstevel@tonic-gate rr.dlen = ns_get16(cp); 447*7c478bd9Sstevel@tonic-gate cp += INT16SZ; 448*7c478bd9Sstevel@tonic-gate if (cp + rr.dlen > eom) { 449*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 450*7c478bd9Sstevel@tonic-gate goto cleanup; 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate rr.data = cp; 453*7c478bd9Sstevel@tonic-gate cp += rr.dlen; 454*7c478bd9Sstevel@tonic-gate if (rr.class != class || rr.type != T_TXT) 455*7c478bd9Sstevel@tonic-gate continue; 456*7c478bd9Sstevel@tonic-gate if (!(list[j] = malloc(rr.dlen))) 457*7c478bd9Sstevel@tonic-gate goto cleanup; 458*7c478bd9Sstevel@tonic-gate dst = list[j++]; 459*7c478bd9Sstevel@tonic-gate edst = dst + rr.dlen; 460*7c478bd9Sstevel@tonic-gate erdata = rr.data + rr.dlen; 461*7c478bd9Sstevel@tonic-gate cp = rr.data; 462*7c478bd9Sstevel@tonic-gate while (cp < erdata) { 463*7c478bd9Sstevel@tonic-gate n = (unsigned char) *cp++; 464*7c478bd9Sstevel@tonic-gate if (cp + n > eom || dst + n > edst) { 465*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 466*7c478bd9Sstevel@tonic-gate goto cleanup; 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate memcpy(dst, cp, n); 469*7c478bd9Sstevel@tonic-gate cp += n; 470*7c478bd9Sstevel@tonic-gate dst += n; 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate if (cp != erdata) { 473*7c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 474*7c478bd9Sstevel@tonic-gate goto cleanup; 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate *dst = '\0'; 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate list[j] = NULL; 479*7c478bd9Sstevel@tonic-gate if (j == 0) { 480*7c478bd9Sstevel@tonic-gate errno = ENOENT; 481*7c478bd9Sstevel@tonic-gate goto cleanup; 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate return (list); 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate cleanup: 486*7c478bd9Sstevel@tonic-gate for (i = 0; i < j; i++) 487*7c478bd9Sstevel@tonic-gate free(list[i]); 488*7c478bd9Sstevel@tonic-gate free(list); 489*7c478bd9Sstevel@tonic-gate return (NULL); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate struct __res_state * 493*7c478bd9Sstevel@tonic-gate __hesiod_res_get(void *context) { 494*7c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = context; 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate if (!ctx->res) { 497*7c478bd9Sstevel@tonic-gate struct __res_state *res; 498*7c478bd9Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 499*7c478bd9Sstevel@tonic-gate if (res == NULL) { 500*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 501*7c478bd9Sstevel@tonic-gate return (NULL); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate memset(res, 0, sizeof *res); 504*7c478bd9Sstevel@tonic-gate __hesiod_res_set(ctx, res, free); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate return (ctx->res); 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate void 511*7c478bd9Sstevel@tonic-gate __hesiod_res_set(void *context, struct __res_state *res, 512*7c478bd9Sstevel@tonic-gate void (*free_res)(void *)) { 513*7c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = context; 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate if (ctx->res && ctx->free_res) { 516*7c478bd9Sstevel@tonic-gate res_nclose(ctx->res); 517*7c478bd9Sstevel@tonic-gate (*ctx->free_res)(ctx->res); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate ctx->res = res; 521*7c478bd9Sstevel@tonic-gate ctx->free_res = free_res; 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate static int 525*7c478bd9Sstevel@tonic-gate init(struct hesiod_p *ctx) { 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate if (!ctx->res && !__hesiod_res_get(ctx)) 528*7c478bd9Sstevel@tonic-gate return (-1); 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate if (((ctx->res->options & RES_INIT) == 0) && 531*7c478bd9Sstevel@tonic-gate (res_ninit(ctx->res) == -1)) 532*7c478bd9Sstevel@tonic-gate return (-1); 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate return (0); 535*7c478bd9Sstevel@tonic-gate } 536