10Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 2*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: hesiod.c,v 1.7 2005/07/28 06:51:48 marka Exp $"; 30Sstevel@tonic-gate #endif 40Sstevel@tonic-gate 50Sstevel@tonic-gate /* 6*11038SRao.Shoaib@Sun.COM * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 70Sstevel@tonic-gate * Copyright (c) 1996,1999 by Internet Software Consortium. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 100Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 110Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 120Sstevel@tonic-gate * 13*11038SRao.Shoaib@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 14*11038SRao.Shoaib@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15*11038SRao.Shoaib@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 16*11038SRao.Shoaib@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17*11038SRao.Shoaib@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18*11038SRao.Shoaib@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 19*11038SRao.Shoaib@Sun.COM * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate 220Sstevel@tonic-gate 23*11038SRao.Shoaib@Sun.COM /*! \file 24*11038SRao.Shoaib@Sun.COM * \brief 250Sstevel@tonic-gate * hesiod.c --- the core portion of the hesiod resolver. 260Sstevel@tonic-gate * 270Sstevel@tonic-gate * This file is derived from the hesiod library from Project Athena; 280Sstevel@tonic-gate * It has been extensively rewritten by Theodore Ts'o to have a more 290Sstevel@tonic-gate * thread-safe interface. 30*11038SRao.Shoaib@Sun.COM * \author 31*11038SRao.Shoaib@Sun.COM * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. 320Sstevel@tonic-gate */ 330Sstevel@tonic-gate 340Sstevel@tonic-gate /* Imports */ 350Sstevel@tonic-gate 360Sstevel@tonic-gate #include "port_before.h" 370Sstevel@tonic-gate 380Sstevel@tonic-gate #include <sys/types.h> 390Sstevel@tonic-gate #include <netinet/in.h> 400Sstevel@tonic-gate #include <arpa/nameser.h> 410Sstevel@tonic-gate 420Sstevel@tonic-gate #include <errno.h> 430Sstevel@tonic-gate #include <netdb.h> 440Sstevel@tonic-gate #include <resolv.h> 450Sstevel@tonic-gate #include <stdio.h> 460Sstevel@tonic-gate #include <stdlib.h> 470Sstevel@tonic-gate #include <string.h> 480Sstevel@tonic-gate 490Sstevel@tonic-gate #include "port_after.h" 500Sstevel@tonic-gate 510Sstevel@tonic-gate #include "pathnames.h" 520Sstevel@tonic-gate #include "hesiod.h" 530Sstevel@tonic-gate #include "hesiod_p.h" 540Sstevel@tonic-gate 550Sstevel@tonic-gate /* Forward */ 560Sstevel@tonic-gate 570Sstevel@tonic-gate int hesiod_init(void **context); 580Sstevel@tonic-gate void hesiod_end(void *context); 590Sstevel@tonic-gate char * hesiod_to_bind(void *context, const char *name, 600Sstevel@tonic-gate const char *type); 610Sstevel@tonic-gate char ** hesiod_resolve(void *context, const char *name, 620Sstevel@tonic-gate const char *type); 630Sstevel@tonic-gate void hesiod_free_list(void *context, char **list); 640Sstevel@tonic-gate 650Sstevel@tonic-gate static int parse_config_file(struct hesiod_p *ctx, const char *filename); 660Sstevel@tonic-gate static char ** get_txt_records(struct hesiod_p *ctx, int class, 670Sstevel@tonic-gate const char *name); 680Sstevel@tonic-gate static int init(struct hesiod_p *ctx); 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* Public */ 710Sstevel@tonic-gate 72*11038SRao.Shoaib@Sun.COM /*% 730Sstevel@tonic-gate * This function is called to initialize a hesiod_p. 740Sstevel@tonic-gate */ 750Sstevel@tonic-gate int 760Sstevel@tonic-gate hesiod_init(void **context) { 770Sstevel@tonic-gate struct hesiod_p *ctx; 780Sstevel@tonic-gate char *cp; 790Sstevel@tonic-gate 800Sstevel@tonic-gate ctx = malloc(sizeof(struct hesiod_p)); 810Sstevel@tonic-gate if (ctx == 0) { 820Sstevel@tonic-gate errno = ENOMEM; 830Sstevel@tonic-gate return (-1); 840Sstevel@tonic-gate } 850Sstevel@tonic-gate 860Sstevel@tonic-gate memset(ctx, 0, sizeof (*ctx)); 870Sstevel@tonic-gate 880Sstevel@tonic-gate if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) { 890Sstevel@tonic-gate #ifdef DEF_RHS 900Sstevel@tonic-gate /* 910Sstevel@tonic-gate * Use compiled in defaults. 920Sstevel@tonic-gate */ 93*11038SRao.Shoaib@Sun.COM ctx->LHS = malloc(strlen(DEF_LHS) + 1); 94*11038SRao.Shoaib@Sun.COM ctx->RHS = malloc(strlen(DEF_RHS) + 1); 95*11038SRao.Shoaib@Sun.COM if (ctx->LHS == NULL || ctx->RHS == NULL) { 960Sstevel@tonic-gate errno = ENOMEM; 970Sstevel@tonic-gate goto cleanup; 980Sstevel@tonic-gate } 99*11038SRao.Shoaib@Sun.COM strcpy(ctx->LHS, DEF_LHS); /* (checked) */ 100*11038SRao.Shoaib@Sun.COM strcpy(ctx->RHS, DEF_RHS); /* (checked) */ 1010Sstevel@tonic-gate #else 1020Sstevel@tonic-gate goto cleanup; 1030Sstevel@tonic-gate #endif 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate /* 1060Sstevel@tonic-gate * The default RHS can be overridden by an environment 1070Sstevel@tonic-gate * variable. 1080Sstevel@tonic-gate */ 1090Sstevel@tonic-gate if ((cp = getenv("HES_DOMAIN")) != NULL) { 1100Sstevel@tonic-gate size_t RHSlen = strlen(cp) + 2; 1110Sstevel@tonic-gate if (ctx->RHS) 1120Sstevel@tonic-gate free(ctx->RHS); 1130Sstevel@tonic-gate ctx->RHS = malloc(RHSlen); 1140Sstevel@tonic-gate if (!ctx->RHS) { 1150Sstevel@tonic-gate errno = ENOMEM; 1160Sstevel@tonic-gate goto cleanup; 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate if (cp[0] == '.') { 119*11038SRao.Shoaib@Sun.COM strcpy(ctx->RHS, cp); /* (checked) */ 1200Sstevel@tonic-gate } else { 121*11038SRao.Shoaib@Sun.COM strcpy(ctx->RHS, "."); /* (checked) */ 122*11038SRao.Shoaib@Sun.COM strcat(ctx->RHS, cp); /* (checked) */ 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate /* 1270Sstevel@tonic-gate * If there is no default hesiod realm set, we return an 1280Sstevel@tonic-gate * error. 1290Sstevel@tonic-gate */ 1300Sstevel@tonic-gate if (!ctx->RHS) { 1310Sstevel@tonic-gate errno = ENOEXEC; 1320Sstevel@tonic-gate goto cleanup; 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate #if 0 1360Sstevel@tonic-gate if (res_ninit(ctx->res) < 0) 1370Sstevel@tonic-gate goto cleanup; 1380Sstevel@tonic-gate #endif 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate *context = ctx; 1410Sstevel@tonic-gate return (0); 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate cleanup: 1440Sstevel@tonic-gate hesiod_end(ctx); 1450Sstevel@tonic-gate return (-1); 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 148*11038SRao.Shoaib@Sun.COM /*% 1490Sstevel@tonic-gate * This function deallocates the hesiod_p 1500Sstevel@tonic-gate */ 1510Sstevel@tonic-gate void 1520Sstevel@tonic-gate hesiod_end(void *context) { 1530Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 1540Sstevel@tonic-gate int save_errno = errno; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate if (ctx->res) 1570Sstevel@tonic-gate res_nclose(ctx->res); 1580Sstevel@tonic-gate if (ctx->RHS) 1590Sstevel@tonic-gate free(ctx->RHS); 1600Sstevel@tonic-gate if (ctx->LHS) 1610Sstevel@tonic-gate free(ctx->LHS); 1620Sstevel@tonic-gate if (ctx->res && ctx->free_res) 1630Sstevel@tonic-gate (*ctx->free_res)(ctx->res); 1640Sstevel@tonic-gate free(ctx); 1650Sstevel@tonic-gate errno = save_errno; 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 168*11038SRao.Shoaib@Sun.COM /*% 1690Sstevel@tonic-gate * This function takes a hesiod (name, type) and returns a DNS 1700Sstevel@tonic-gate * name which is to be resolved. 1710Sstevel@tonic-gate */ 1720Sstevel@tonic-gate char * 1730Sstevel@tonic-gate hesiod_to_bind(void *context, const char *name, const char *type) { 1740Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 1750Sstevel@tonic-gate char *bindname; 1760Sstevel@tonic-gate char **rhs_list = NULL; 1770Sstevel@tonic-gate const char *RHS, *cp; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* Decide what our RHS is, and set cp to the end of the actual name. */ 1800Sstevel@tonic-gate if ((cp = strchr(name, '@')) != NULL) { 1810Sstevel@tonic-gate if (strchr(cp + 1, '.')) 1820Sstevel@tonic-gate RHS = cp + 1; 1830Sstevel@tonic-gate else if ((rhs_list = hesiod_resolve(context, cp + 1, 1840Sstevel@tonic-gate "rhs-extension")) != NULL) 1850Sstevel@tonic-gate RHS = *rhs_list; 1860Sstevel@tonic-gate else { 1870Sstevel@tonic-gate errno = ENOENT; 1880Sstevel@tonic-gate return (NULL); 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate } else { 1910Sstevel@tonic-gate RHS = ctx->RHS; 1920Sstevel@tonic-gate cp = name + strlen(name); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate /* 1960Sstevel@tonic-gate * Allocate the space we need, including up to three periods and 1970Sstevel@tonic-gate * the terminating NUL. 1980Sstevel@tonic-gate */ 1990Sstevel@tonic-gate if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) + 2000Sstevel@tonic-gate (ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) { 2010Sstevel@tonic-gate errno = ENOMEM; 2020Sstevel@tonic-gate if (rhs_list) 2030Sstevel@tonic-gate hesiod_free_list(context, rhs_list); 2040Sstevel@tonic-gate return NULL; 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate /* Now put together the DNS name. */ 2080Sstevel@tonic-gate memcpy(bindname, name, cp - name); 2090Sstevel@tonic-gate bindname[cp - name] = '\0'; 2100Sstevel@tonic-gate strcat(bindname, "."); 2110Sstevel@tonic-gate strcat(bindname, type); 2120Sstevel@tonic-gate if (ctx->LHS) { 2130Sstevel@tonic-gate if (ctx->LHS[0] != '.') 2140Sstevel@tonic-gate strcat(bindname, "."); 2150Sstevel@tonic-gate strcat(bindname, ctx->LHS); 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate if (RHS[0] != '.') 2180Sstevel@tonic-gate strcat(bindname, "."); 2190Sstevel@tonic-gate strcat(bindname, RHS); 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate if (rhs_list) 2220Sstevel@tonic-gate hesiod_free_list(context, rhs_list); 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate return (bindname); 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate 227*11038SRao.Shoaib@Sun.COM /*% 2280Sstevel@tonic-gate * This is the core function. Given a hesiod (name, type), it 2290Sstevel@tonic-gate * returns an array of strings returned by the resolver. 2300Sstevel@tonic-gate */ 2310Sstevel@tonic-gate char ** 2320Sstevel@tonic-gate hesiod_resolve(void *context, const char *name, const char *type) { 2330Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 2340Sstevel@tonic-gate char *bindname = hesiod_to_bind(context, name, type); 2350Sstevel@tonic-gate char **retvec; 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate if (bindname == NULL) 2380Sstevel@tonic-gate return (NULL); 2390Sstevel@tonic-gate if (init(ctx) == -1) { 2400Sstevel@tonic-gate free(bindname); 2410Sstevel@tonic-gate return (NULL); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate if ((retvec = get_txt_records(ctx, C_IN, bindname))) { 2450Sstevel@tonic-gate free(bindname); 2460Sstevel@tonic-gate return (retvec); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate if (errno != ENOENT) 2500Sstevel@tonic-gate return (NULL); 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate retvec = get_txt_records(ctx, C_HS, bindname); 2530Sstevel@tonic-gate free(bindname); 2540Sstevel@tonic-gate return (retvec); 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate void 2580Sstevel@tonic-gate hesiod_free_list(void *context, char **list) { 2590Sstevel@tonic-gate char **p; 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate UNUSED(context); 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate for (p = list; *p; p++) 2640Sstevel@tonic-gate free(*p); 2650Sstevel@tonic-gate free(list); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 268*11038SRao.Shoaib@Sun.COM /*% 2690Sstevel@tonic-gate * This function parses the /etc/hesiod.conf file 2700Sstevel@tonic-gate */ 2710Sstevel@tonic-gate static int 2720Sstevel@tonic-gate parse_config_file(struct hesiod_p *ctx, const char *filename) { 2730Sstevel@tonic-gate char *key, *data, *cp, **cpp; 2740Sstevel@tonic-gate char buf[MAXDNAME+7]; 2750Sstevel@tonic-gate FILE *fp; 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate /* 2780Sstevel@tonic-gate * Clear the existing configuration variable, just in case 2790Sstevel@tonic-gate * they're set. 2800Sstevel@tonic-gate */ 2810Sstevel@tonic-gate if (ctx->RHS) 2820Sstevel@tonic-gate free(ctx->RHS); 2830Sstevel@tonic-gate if (ctx->LHS) 2840Sstevel@tonic-gate free(ctx->LHS); 2850Sstevel@tonic-gate ctx->RHS = ctx->LHS = 0; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* 2880Sstevel@tonic-gate * Now open and parse the file... 2890Sstevel@tonic-gate */ 2900Sstevel@tonic-gate if (!(fp = fopen(filename, "r"))) 2910Sstevel@tonic-gate return (-1); 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate while (fgets(buf, sizeof(buf), fp) != NULL) { 2940Sstevel@tonic-gate cp = buf; 2950Sstevel@tonic-gate if (*cp == '#' || *cp == '\n' || *cp == '\r') 2960Sstevel@tonic-gate continue; 2970Sstevel@tonic-gate while(*cp == ' ' || *cp == '\t') 2980Sstevel@tonic-gate cp++; 2990Sstevel@tonic-gate key = cp; 3000Sstevel@tonic-gate while(*cp != ' ' && *cp != '\t' && *cp != '=') 3010Sstevel@tonic-gate cp++; 3020Sstevel@tonic-gate *cp++ = '\0'; 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate while(*cp == ' ' || *cp == '\t' || *cp == '=') 3050Sstevel@tonic-gate cp++; 3060Sstevel@tonic-gate data = cp; 3070Sstevel@tonic-gate while(*cp != ' ' && *cp != '\n' && *cp != '\r') 3080Sstevel@tonic-gate cp++; 3090Sstevel@tonic-gate *cp++ = '\0'; 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate if (strcmp(key, "lhs") == 0) 3120Sstevel@tonic-gate cpp = &ctx->LHS; 3130Sstevel@tonic-gate else if (strcmp(key, "rhs") == 0) 3140Sstevel@tonic-gate cpp = &ctx->RHS; 3150Sstevel@tonic-gate else 3160Sstevel@tonic-gate continue; 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate *cpp = malloc(strlen(data) + 1); 3190Sstevel@tonic-gate if (!*cpp) { 3200Sstevel@tonic-gate errno = ENOMEM; 3210Sstevel@tonic-gate goto cleanup; 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate strcpy(*cpp, data); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate fclose(fp); 3260Sstevel@tonic-gate return (0); 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate cleanup: 3290Sstevel@tonic-gate fclose(fp); 3300Sstevel@tonic-gate if (ctx->RHS) 3310Sstevel@tonic-gate free(ctx->RHS); 3320Sstevel@tonic-gate if (ctx->LHS) 3330Sstevel@tonic-gate free(ctx->LHS); 3340Sstevel@tonic-gate ctx->RHS = ctx->LHS = 0; 3350Sstevel@tonic-gate return (-1); 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 338*11038SRao.Shoaib@Sun.COM /*% 3390Sstevel@tonic-gate * Given a DNS class and a DNS name, do a lookup for TXT records, and 3400Sstevel@tonic-gate * return a list of them. 3410Sstevel@tonic-gate */ 3420Sstevel@tonic-gate static char ** 3430Sstevel@tonic-gate get_txt_records(struct hesiod_p *ctx, int class, const char *name) { 3440Sstevel@tonic-gate struct { 345*11038SRao.Shoaib@Sun.COM int type; /*%< RR type */ 346*11038SRao.Shoaib@Sun.COM int class; /*%< RR class */ 347*11038SRao.Shoaib@Sun.COM int dlen; /*%< len of data section */ 348*11038SRao.Shoaib@Sun.COM u_char *data; /*%< pointer to data */ 3490Sstevel@tonic-gate } rr; 3500Sstevel@tonic-gate HEADER *hp; 3510Sstevel@tonic-gate u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; 3520Sstevel@tonic-gate u_char *cp, *erdata, *eom; 3530Sstevel@tonic-gate char *dst, *edst, **list; 3540Sstevel@tonic-gate int ancount, qdcount; 3550Sstevel@tonic-gate int i, j, n, skip; 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate /* 3580Sstevel@tonic-gate * Construct the query and send it. 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0, 3610Sstevel@tonic-gate NULL, qbuf, MAX_HESRESP); 3620Sstevel@tonic-gate if (n < 0) { 3630Sstevel@tonic-gate errno = EMSGSIZE; 3640Sstevel@tonic-gate return (NULL); 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP); 3670Sstevel@tonic-gate if (n < 0) { 3680Sstevel@tonic-gate errno = ECONNREFUSED; 3690Sstevel@tonic-gate return (NULL); 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate if (n < HFIXEDSZ) { 3720Sstevel@tonic-gate errno = EMSGSIZE; 3730Sstevel@tonic-gate return (NULL); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate /* 3770Sstevel@tonic-gate * OK, parse the result. 3780Sstevel@tonic-gate */ 3790Sstevel@tonic-gate hp = (HEADER *) abuf; 3800Sstevel@tonic-gate ancount = ntohs(hp->ancount); 3810Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 3820Sstevel@tonic-gate cp = abuf + sizeof(HEADER); 3830Sstevel@tonic-gate eom = abuf + n; 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate /* Skip query, trying to get to the answer section which follows. */ 3860Sstevel@tonic-gate for (i = 0; i < qdcount; i++) { 3870Sstevel@tonic-gate skip = dn_skipname(cp, eom); 3880Sstevel@tonic-gate if (skip < 0 || cp + skip + QFIXEDSZ > eom) { 3890Sstevel@tonic-gate errno = EMSGSIZE; 3900Sstevel@tonic-gate return (NULL); 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate cp += skip + QFIXEDSZ; 3930Sstevel@tonic-gate } 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate list = malloc((ancount + 1) * sizeof(char *)); 3960Sstevel@tonic-gate if (!list) { 3970Sstevel@tonic-gate errno = ENOMEM; 3980Sstevel@tonic-gate return (NULL); 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate j = 0; 4010Sstevel@tonic-gate for (i = 0; i < ancount; i++) { 4020Sstevel@tonic-gate skip = dn_skipname(cp, eom); 4030Sstevel@tonic-gate if (skip < 0) { 4040Sstevel@tonic-gate errno = EMSGSIZE; 4050Sstevel@tonic-gate goto cleanup; 4060Sstevel@tonic-gate } 4070Sstevel@tonic-gate cp += skip; 4080Sstevel@tonic-gate if (cp + 3 * INT16SZ + INT32SZ > eom) { 4090Sstevel@tonic-gate errno = EMSGSIZE; 4100Sstevel@tonic-gate goto cleanup; 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate rr.type = ns_get16(cp); 4130Sstevel@tonic-gate cp += INT16SZ; 4140Sstevel@tonic-gate rr.class = ns_get16(cp); 415*11038SRao.Shoaib@Sun.COM cp += INT16SZ + INT32SZ; /*%< skip the ttl, too */ 4160Sstevel@tonic-gate rr.dlen = ns_get16(cp); 4170Sstevel@tonic-gate cp += INT16SZ; 4180Sstevel@tonic-gate if (cp + rr.dlen > eom) { 4190Sstevel@tonic-gate errno = EMSGSIZE; 4200Sstevel@tonic-gate goto cleanup; 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate rr.data = cp; 4230Sstevel@tonic-gate cp += rr.dlen; 4240Sstevel@tonic-gate if (rr.class != class || rr.type != T_TXT) 4250Sstevel@tonic-gate continue; 4260Sstevel@tonic-gate if (!(list[j] = malloc(rr.dlen))) 4270Sstevel@tonic-gate goto cleanup; 4280Sstevel@tonic-gate dst = list[j++]; 4290Sstevel@tonic-gate edst = dst + rr.dlen; 4300Sstevel@tonic-gate erdata = rr.data + rr.dlen; 4310Sstevel@tonic-gate cp = rr.data; 4320Sstevel@tonic-gate while (cp < erdata) { 4330Sstevel@tonic-gate n = (unsigned char) *cp++; 4340Sstevel@tonic-gate if (cp + n > eom || dst + n > edst) { 4350Sstevel@tonic-gate errno = EMSGSIZE; 4360Sstevel@tonic-gate goto cleanup; 4370Sstevel@tonic-gate } 4380Sstevel@tonic-gate memcpy(dst, cp, n); 4390Sstevel@tonic-gate cp += n; 4400Sstevel@tonic-gate dst += n; 4410Sstevel@tonic-gate } 4420Sstevel@tonic-gate if (cp != erdata) { 4430Sstevel@tonic-gate errno = EMSGSIZE; 4440Sstevel@tonic-gate goto cleanup; 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate *dst = '\0'; 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate list[j] = NULL; 4490Sstevel@tonic-gate if (j == 0) { 4500Sstevel@tonic-gate errno = ENOENT; 4510Sstevel@tonic-gate goto cleanup; 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate return (list); 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate cleanup: 4560Sstevel@tonic-gate for (i = 0; i < j; i++) 4570Sstevel@tonic-gate free(list[i]); 4580Sstevel@tonic-gate free(list); 4590Sstevel@tonic-gate return (NULL); 4600Sstevel@tonic-gate } 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate struct __res_state * 4630Sstevel@tonic-gate __hesiod_res_get(void *context) { 4640Sstevel@tonic-gate struct hesiod_p *ctx = context; 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate if (!ctx->res) { 4670Sstevel@tonic-gate struct __res_state *res; 4680Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 4690Sstevel@tonic-gate if (res == NULL) { 4700Sstevel@tonic-gate errno = ENOMEM; 4710Sstevel@tonic-gate return (NULL); 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate memset(res, 0, sizeof *res); 4740Sstevel@tonic-gate __hesiod_res_set(ctx, res, free); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate return (ctx->res); 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate void 4810Sstevel@tonic-gate __hesiod_res_set(void *context, struct __res_state *res, 4820Sstevel@tonic-gate void (*free_res)(void *)) { 4830Sstevel@tonic-gate struct hesiod_p *ctx = context; 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate if (ctx->res && ctx->free_res) { 4860Sstevel@tonic-gate res_nclose(ctx->res); 4870Sstevel@tonic-gate (*ctx->free_res)(ctx->res); 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate ctx->res = res; 4910Sstevel@tonic-gate ctx->free_res = free_res; 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate static int 4950Sstevel@tonic-gate init(struct hesiod_p *ctx) { 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate if (!ctx->res && !__hesiod_res_get(ctx)) 4980Sstevel@tonic-gate return (-1); 4990Sstevel@tonic-gate 500*11038SRao.Shoaib@Sun.COM if (((ctx->res->options & RES_INIT) == 0U) && 5010Sstevel@tonic-gate (res_ninit(ctx->res) == -1)) 5020Sstevel@tonic-gate return (-1); 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate return (0); 5050Sstevel@tonic-gate } 506