17c478bd9Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 2*9525b14bSRao Shoaib static const char rcsid[] = "$Id: hesiod.c,v 1.7 2005/07/28 06:51:48 marka Exp $"; 37c478bd9Sstevel@tonic-gate #endif 47c478bd9Sstevel@tonic-gate 57c478bd9Sstevel@tonic-gate /* 6*9525b14bSRao Shoaib * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 77c478bd9Sstevel@tonic-gate * Copyright (c) 1996,1999 by Internet Software Consortium. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 107c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 117c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 127c478bd9Sstevel@tonic-gate * 13*9525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 14*9525b14bSRao Shoaib * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15*9525b14bSRao Shoaib * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 16*9525b14bSRao Shoaib * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17*9525b14bSRao Shoaib * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18*9525b14bSRao Shoaib * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 19*9525b14bSRao Shoaib * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate 23*9525b14bSRao Shoaib /*! \file 24*9525b14bSRao Shoaib * \brief 257c478bd9Sstevel@tonic-gate * hesiod.c --- the core portion of the hesiod resolver. 267c478bd9Sstevel@tonic-gate * 277c478bd9Sstevel@tonic-gate * This file is derived from the hesiod library from Project Athena; 287c478bd9Sstevel@tonic-gate * It has been extensively rewritten by Theodore Ts'o to have a more 297c478bd9Sstevel@tonic-gate * thread-safe interface. 30*9525b14bSRao Shoaib * \author 31*9525b14bSRao Shoaib * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* Imports */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include "port_before.h" 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <sys/types.h> 397c478bd9Sstevel@tonic-gate #include <netinet/in.h> 407c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include <errno.h> 437c478bd9Sstevel@tonic-gate #include <netdb.h> 447c478bd9Sstevel@tonic-gate #include <resolv.h> 457c478bd9Sstevel@tonic-gate #include <stdio.h> 467c478bd9Sstevel@tonic-gate #include <stdlib.h> 477c478bd9Sstevel@tonic-gate #include <string.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include "port_after.h" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #include "pathnames.h" 527c478bd9Sstevel@tonic-gate #include "hesiod.h" 537c478bd9Sstevel@tonic-gate #include "hesiod_p.h" 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* Forward */ 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate int hesiod_init(void **context); 587c478bd9Sstevel@tonic-gate void hesiod_end(void *context); 597c478bd9Sstevel@tonic-gate char * hesiod_to_bind(void *context, const char *name, 607c478bd9Sstevel@tonic-gate const char *type); 617c478bd9Sstevel@tonic-gate char ** hesiod_resolve(void *context, const char *name, 627c478bd9Sstevel@tonic-gate const char *type); 637c478bd9Sstevel@tonic-gate void hesiod_free_list(void *context, char **list); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static int parse_config_file(struct hesiod_p *ctx, const char *filename); 667c478bd9Sstevel@tonic-gate static char ** get_txt_records(struct hesiod_p *ctx, int class, 677c478bd9Sstevel@tonic-gate const char *name); 687c478bd9Sstevel@tonic-gate static int init(struct hesiod_p *ctx); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* Public */ 717c478bd9Sstevel@tonic-gate 72*9525b14bSRao Shoaib /*% 737c478bd9Sstevel@tonic-gate * This function is called to initialize a hesiod_p. 747c478bd9Sstevel@tonic-gate */ 757c478bd9Sstevel@tonic-gate int 767c478bd9Sstevel@tonic-gate hesiod_init(void **context) { 777c478bd9Sstevel@tonic-gate struct hesiod_p *ctx; 787c478bd9Sstevel@tonic-gate char *cp; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate ctx = malloc(sizeof(struct hesiod_p)); 817c478bd9Sstevel@tonic-gate if (ctx == 0) { 827c478bd9Sstevel@tonic-gate errno = ENOMEM; 837c478bd9Sstevel@tonic-gate return (-1); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate memset(ctx, 0, sizeof (*ctx)); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) { 897c478bd9Sstevel@tonic-gate #ifdef DEF_RHS 907c478bd9Sstevel@tonic-gate /* 917c478bd9Sstevel@tonic-gate * Use compiled in defaults. 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate ctx->LHS = malloc(strlen(DEF_LHS) + 1); 947c478bd9Sstevel@tonic-gate ctx->RHS = malloc(strlen(DEF_RHS) + 1); 95*9525b14bSRao Shoaib if (ctx->LHS == NULL || ctx->RHS == NULL) { 967c478bd9Sstevel@tonic-gate errno = ENOMEM; 977c478bd9Sstevel@tonic-gate goto cleanup; 987c478bd9Sstevel@tonic-gate } 99*9525b14bSRao Shoaib strcpy(ctx->LHS, DEF_LHS); /* (checked) */ 100*9525b14bSRao Shoaib strcpy(ctx->RHS, DEF_RHS); /* (checked) */ 1017c478bd9Sstevel@tonic-gate #else 1027c478bd9Sstevel@tonic-gate goto cleanup; 1037c478bd9Sstevel@tonic-gate #endif 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * The default RHS can be overridden by an environment 1077c478bd9Sstevel@tonic-gate * variable. 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate if ((cp = getenv("HES_DOMAIN")) != NULL) { 1107c478bd9Sstevel@tonic-gate size_t RHSlen = strlen(cp) + 2; 1117c478bd9Sstevel@tonic-gate if (ctx->RHS) 1127c478bd9Sstevel@tonic-gate free(ctx->RHS); 1137c478bd9Sstevel@tonic-gate ctx->RHS = malloc(RHSlen); 1147c478bd9Sstevel@tonic-gate if (!ctx->RHS) { 1157c478bd9Sstevel@tonic-gate errno = ENOMEM; 1167c478bd9Sstevel@tonic-gate goto cleanup; 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate if (cp[0] == '.') { 119*9525b14bSRao Shoaib strcpy(ctx->RHS, cp); /* (checked) */ 1207c478bd9Sstevel@tonic-gate } else { 121*9525b14bSRao Shoaib strcpy(ctx->RHS, "."); /* (checked) */ 122*9525b14bSRao Shoaib strcat(ctx->RHS, cp); /* (checked) */ 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * If there is no default hesiod realm set, we return an 1287c478bd9Sstevel@tonic-gate * error. 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate if (!ctx->RHS) { 1317c478bd9Sstevel@tonic-gate errno = ENOEXEC; 1327c478bd9Sstevel@tonic-gate goto cleanup; 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate #if 0 1367c478bd9Sstevel@tonic-gate if (res_ninit(ctx->res) < 0) 1377c478bd9Sstevel@tonic-gate goto cleanup; 1387c478bd9Sstevel@tonic-gate #endif 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate *context = ctx; 1417c478bd9Sstevel@tonic-gate return (0); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate cleanup: 1447c478bd9Sstevel@tonic-gate hesiod_end(ctx); 1457c478bd9Sstevel@tonic-gate return (-1); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 148*9525b14bSRao Shoaib /*% 1497c478bd9Sstevel@tonic-gate * This function deallocates the hesiod_p 1507c478bd9Sstevel@tonic-gate */ 1517c478bd9Sstevel@tonic-gate void 1527c478bd9Sstevel@tonic-gate hesiod_end(void *context) { 1537c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 1547c478bd9Sstevel@tonic-gate int save_errno = errno; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if (ctx->res) 1577c478bd9Sstevel@tonic-gate res_nclose(ctx->res); 1587c478bd9Sstevel@tonic-gate if (ctx->RHS) 1597c478bd9Sstevel@tonic-gate free(ctx->RHS); 1607c478bd9Sstevel@tonic-gate if (ctx->LHS) 1617c478bd9Sstevel@tonic-gate free(ctx->LHS); 1627c478bd9Sstevel@tonic-gate if (ctx->res && ctx->free_res) 1637c478bd9Sstevel@tonic-gate (*ctx->free_res)(ctx->res); 1647c478bd9Sstevel@tonic-gate free(ctx); 1657c478bd9Sstevel@tonic-gate errno = save_errno; 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 168*9525b14bSRao Shoaib /*% 1697c478bd9Sstevel@tonic-gate * This function takes a hesiod (name, type) and returns a DNS 1707c478bd9Sstevel@tonic-gate * name which is to be resolved. 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate char * 1737c478bd9Sstevel@tonic-gate hesiod_to_bind(void *context, const char *name, const char *type) { 1747c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 1757c478bd9Sstevel@tonic-gate char *bindname; 1767c478bd9Sstevel@tonic-gate char **rhs_list = NULL; 1777c478bd9Sstevel@tonic-gate const char *RHS, *cp; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* Decide what our RHS is, and set cp to the end of the actual name. */ 1807c478bd9Sstevel@tonic-gate if ((cp = strchr(name, '@')) != NULL) { 1817c478bd9Sstevel@tonic-gate if (strchr(cp + 1, '.')) 1827c478bd9Sstevel@tonic-gate RHS = cp + 1; 1837c478bd9Sstevel@tonic-gate else if ((rhs_list = hesiod_resolve(context, cp + 1, 1847c478bd9Sstevel@tonic-gate "rhs-extension")) != NULL) 1857c478bd9Sstevel@tonic-gate RHS = *rhs_list; 1867c478bd9Sstevel@tonic-gate else { 1877c478bd9Sstevel@tonic-gate errno = ENOENT; 1887c478bd9Sstevel@tonic-gate return (NULL); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate } else { 1917c478bd9Sstevel@tonic-gate RHS = ctx->RHS; 1927c478bd9Sstevel@tonic-gate cp = name + strlen(name); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Allocate the space we need, including up to three periods and 1977c478bd9Sstevel@tonic-gate * the terminating NUL. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) + 2007c478bd9Sstevel@tonic-gate (ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) { 2017c478bd9Sstevel@tonic-gate errno = ENOMEM; 2027c478bd9Sstevel@tonic-gate if (rhs_list) 2037c478bd9Sstevel@tonic-gate hesiod_free_list(context, rhs_list); 2047c478bd9Sstevel@tonic-gate return NULL; 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* Now put together the DNS name. */ 2087c478bd9Sstevel@tonic-gate memcpy(bindname, name, cp - name); 2097c478bd9Sstevel@tonic-gate bindname[cp - name] = '\0'; 2107c478bd9Sstevel@tonic-gate strcat(bindname, "."); 2117c478bd9Sstevel@tonic-gate strcat(bindname, type); 2127c478bd9Sstevel@tonic-gate if (ctx->LHS) { 2137c478bd9Sstevel@tonic-gate if (ctx->LHS[0] != '.') 2147c478bd9Sstevel@tonic-gate strcat(bindname, "."); 2157c478bd9Sstevel@tonic-gate strcat(bindname, ctx->LHS); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate if (RHS[0] != '.') 2187c478bd9Sstevel@tonic-gate strcat(bindname, "."); 2197c478bd9Sstevel@tonic-gate strcat(bindname, RHS); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (rhs_list) 2227c478bd9Sstevel@tonic-gate hesiod_free_list(context, rhs_list); 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate return (bindname); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 227*9525b14bSRao Shoaib /*% 2287c478bd9Sstevel@tonic-gate * This is the core function. Given a hesiod (name, type), it 2297c478bd9Sstevel@tonic-gate * returns an array of strings returned by the resolver. 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate char ** 2327c478bd9Sstevel@tonic-gate hesiod_resolve(void *context, const char *name, const char *type) { 2337c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = (struct hesiod_p *) context; 2347c478bd9Sstevel@tonic-gate char *bindname = hesiod_to_bind(context, name, type); 2357c478bd9Sstevel@tonic-gate char **retvec; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate if (bindname == NULL) 2387c478bd9Sstevel@tonic-gate return (NULL); 2397c478bd9Sstevel@tonic-gate if (init(ctx) == -1) { 2407c478bd9Sstevel@tonic-gate free(bindname); 2417c478bd9Sstevel@tonic-gate return (NULL); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if ((retvec = get_txt_records(ctx, C_IN, bindname))) { 2457c478bd9Sstevel@tonic-gate free(bindname); 2467c478bd9Sstevel@tonic-gate return (retvec); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if (errno != ENOENT) 2507c478bd9Sstevel@tonic-gate return (NULL); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate retvec = get_txt_records(ctx, C_HS, bindname); 2537c478bd9Sstevel@tonic-gate free(bindname); 2547c478bd9Sstevel@tonic-gate return (retvec); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate void 2587c478bd9Sstevel@tonic-gate hesiod_free_list(void *context, char **list) { 2597c478bd9Sstevel@tonic-gate char **p; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate UNUSED(context); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate for (p = list; *p; p++) 2647c478bd9Sstevel@tonic-gate free(*p); 2657c478bd9Sstevel@tonic-gate free(list); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 268*9525b14bSRao Shoaib /*% 2697c478bd9Sstevel@tonic-gate * This function parses the /etc/hesiod.conf file 2707c478bd9Sstevel@tonic-gate */ 2717c478bd9Sstevel@tonic-gate static int 2727c478bd9Sstevel@tonic-gate parse_config_file(struct hesiod_p *ctx, const char *filename) { 2737c478bd9Sstevel@tonic-gate char *key, *data, *cp, **cpp; 2747c478bd9Sstevel@tonic-gate char buf[MAXDNAME+7]; 2757c478bd9Sstevel@tonic-gate FILE *fp; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Clear the existing configuration variable, just in case 2797c478bd9Sstevel@tonic-gate * they're set. 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate if (ctx->RHS) 2827c478bd9Sstevel@tonic-gate free(ctx->RHS); 2837c478bd9Sstevel@tonic-gate if (ctx->LHS) 2847c478bd9Sstevel@tonic-gate free(ctx->LHS); 2857c478bd9Sstevel@tonic-gate ctx->RHS = ctx->LHS = 0; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* 2887c478bd9Sstevel@tonic-gate * Now open and parse the file... 2897c478bd9Sstevel@tonic-gate */ 2907c478bd9Sstevel@tonic-gate if (!(fp = fopen(filename, "r"))) 2917c478bd9Sstevel@tonic-gate return (-1); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof(buf), fp) != NULL) { 2947c478bd9Sstevel@tonic-gate cp = buf; 2957c478bd9Sstevel@tonic-gate if (*cp == '#' || *cp == '\n' || *cp == '\r') 2967c478bd9Sstevel@tonic-gate continue; 2977c478bd9Sstevel@tonic-gate while(*cp == ' ' || *cp == '\t') 2987c478bd9Sstevel@tonic-gate cp++; 2997c478bd9Sstevel@tonic-gate key = cp; 3007c478bd9Sstevel@tonic-gate while(*cp != ' ' && *cp != '\t' && *cp != '=') 3017c478bd9Sstevel@tonic-gate cp++; 3027c478bd9Sstevel@tonic-gate *cp++ = '\0'; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate while(*cp == ' ' || *cp == '\t' || *cp == '=') 3057c478bd9Sstevel@tonic-gate cp++; 3067c478bd9Sstevel@tonic-gate data = cp; 3077c478bd9Sstevel@tonic-gate while(*cp != ' ' && *cp != '\n' && *cp != '\r') 3087c478bd9Sstevel@tonic-gate cp++; 3097c478bd9Sstevel@tonic-gate *cp++ = '\0'; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if (strcmp(key, "lhs") == 0) 3127c478bd9Sstevel@tonic-gate cpp = &ctx->LHS; 3137c478bd9Sstevel@tonic-gate else if (strcmp(key, "rhs") == 0) 3147c478bd9Sstevel@tonic-gate cpp = &ctx->RHS; 3157c478bd9Sstevel@tonic-gate else 3167c478bd9Sstevel@tonic-gate continue; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate *cpp = malloc(strlen(data) + 1); 3197c478bd9Sstevel@tonic-gate if (!*cpp) { 3207c478bd9Sstevel@tonic-gate errno = ENOMEM; 3217c478bd9Sstevel@tonic-gate goto cleanup; 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate strcpy(*cpp, data); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate fclose(fp); 3267c478bd9Sstevel@tonic-gate return (0); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate cleanup: 3297c478bd9Sstevel@tonic-gate fclose(fp); 3307c478bd9Sstevel@tonic-gate if (ctx->RHS) 3317c478bd9Sstevel@tonic-gate free(ctx->RHS); 3327c478bd9Sstevel@tonic-gate if (ctx->LHS) 3337c478bd9Sstevel@tonic-gate free(ctx->LHS); 3347c478bd9Sstevel@tonic-gate ctx->RHS = ctx->LHS = 0; 3357c478bd9Sstevel@tonic-gate return (-1); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 338*9525b14bSRao Shoaib /*% 3397c478bd9Sstevel@tonic-gate * Given a DNS class and a DNS name, do a lookup for TXT records, and 3407c478bd9Sstevel@tonic-gate * return a list of them. 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate static char ** 3437c478bd9Sstevel@tonic-gate get_txt_records(struct hesiod_p *ctx, int class, const char *name) { 3447c478bd9Sstevel@tonic-gate struct { 345*9525b14bSRao Shoaib int type; /*%< RR type */ 346*9525b14bSRao Shoaib int class; /*%< RR class */ 347*9525b14bSRao Shoaib int dlen; /*%< len of data section */ 348*9525b14bSRao Shoaib u_char *data; /*%< pointer to data */ 3497c478bd9Sstevel@tonic-gate } rr; 3507c478bd9Sstevel@tonic-gate HEADER *hp; 3517c478bd9Sstevel@tonic-gate u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; 3527c478bd9Sstevel@tonic-gate u_char *cp, *erdata, *eom; 3537c478bd9Sstevel@tonic-gate char *dst, *edst, **list; 3547c478bd9Sstevel@tonic-gate int ancount, qdcount; 3557c478bd9Sstevel@tonic-gate int i, j, n, skip; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate /* 3587c478bd9Sstevel@tonic-gate * Construct the query and send it. 3597c478bd9Sstevel@tonic-gate */ 3607c478bd9Sstevel@tonic-gate n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0, 3617c478bd9Sstevel@tonic-gate NULL, qbuf, MAX_HESRESP); 3627c478bd9Sstevel@tonic-gate if (n < 0) { 3637c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3647c478bd9Sstevel@tonic-gate return (NULL); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP); 3677c478bd9Sstevel@tonic-gate if (n < 0) { 3687c478bd9Sstevel@tonic-gate errno = ECONNREFUSED; 3697c478bd9Sstevel@tonic-gate return (NULL); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate if (n < HFIXEDSZ) { 3727c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3737c478bd9Sstevel@tonic-gate return (NULL); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * OK, parse the result. 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate hp = (HEADER *) abuf; 3807c478bd9Sstevel@tonic-gate ancount = ntohs(hp->ancount); 3817c478bd9Sstevel@tonic-gate qdcount = ntohs(hp->qdcount); 3827c478bd9Sstevel@tonic-gate cp = abuf + sizeof(HEADER); 3837c478bd9Sstevel@tonic-gate eom = abuf + n; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* Skip query, trying to get to the answer section which follows. */ 3867c478bd9Sstevel@tonic-gate for (i = 0; i < qdcount; i++) { 3877c478bd9Sstevel@tonic-gate skip = dn_skipname(cp, eom); 3887c478bd9Sstevel@tonic-gate if (skip < 0 || cp + skip + QFIXEDSZ > eom) { 3897c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3907c478bd9Sstevel@tonic-gate return (NULL); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate cp += skip + QFIXEDSZ; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate list = malloc((ancount + 1) * sizeof(char *)); 3967c478bd9Sstevel@tonic-gate if (!list) { 3977c478bd9Sstevel@tonic-gate errno = ENOMEM; 3987c478bd9Sstevel@tonic-gate return (NULL); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate j = 0; 4017c478bd9Sstevel@tonic-gate for (i = 0; i < ancount; i++) { 4027c478bd9Sstevel@tonic-gate skip = dn_skipname(cp, eom); 4037c478bd9Sstevel@tonic-gate if (skip < 0) { 4047c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4057c478bd9Sstevel@tonic-gate goto cleanup; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate cp += skip; 4087c478bd9Sstevel@tonic-gate if (cp + 3 * INT16SZ + INT32SZ > eom) { 4097c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4107c478bd9Sstevel@tonic-gate goto cleanup; 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate rr.type = ns_get16(cp); 4137c478bd9Sstevel@tonic-gate cp += INT16SZ; 4147c478bd9Sstevel@tonic-gate rr.class = ns_get16(cp); 415*9525b14bSRao Shoaib cp += INT16SZ + INT32SZ; /*%< skip the ttl, too */ 4167c478bd9Sstevel@tonic-gate rr.dlen = ns_get16(cp); 4177c478bd9Sstevel@tonic-gate cp += INT16SZ; 4187c478bd9Sstevel@tonic-gate if (cp + rr.dlen > eom) { 4197c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4207c478bd9Sstevel@tonic-gate goto cleanup; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate rr.data = cp; 4237c478bd9Sstevel@tonic-gate cp += rr.dlen; 4247c478bd9Sstevel@tonic-gate if (rr.class != class || rr.type != T_TXT) 4257c478bd9Sstevel@tonic-gate continue; 4267c478bd9Sstevel@tonic-gate if (!(list[j] = malloc(rr.dlen))) 4277c478bd9Sstevel@tonic-gate goto cleanup; 4287c478bd9Sstevel@tonic-gate dst = list[j++]; 4297c478bd9Sstevel@tonic-gate edst = dst + rr.dlen; 4307c478bd9Sstevel@tonic-gate erdata = rr.data + rr.dlen; 4317c478bd9Sstevel@tonic-gate cp = rr.data; 4327c478bd9Sstevel@tonic-gate while (cp < erdata) { 4337c478bd9Sstevel@tonic-gate n = (unsigned char) *cp++; 4347c478bd9Sstevel@tonic-gate if (cp + n > eom || dst + n > edst) { 4357c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4367c478bd9Sstevel@tonic-gate goto cleanup; 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate memcpy(dst, cp, n); 4397c478bd9Sstevel@tonic-gate cp += n; 4407c478bd9Sstevel@tonic-gate dst += n; 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate if (cp != erdata) { 4437c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4447c478bd9Sstevel@tonic-gate goto cleanup; 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate *dst = '\0'; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate list[j] = NULL; 4497c478bd9Sstevel@tonic-gate if (j == 0) { 4507c478bd9Sstevel@tonic-gate errno = ENOENT; 4517c478bd9Sstevel@tonic-gate goto cleanup; 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate return (list); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate cleanup: 4567c478bd9Sstevel@tonic-gate for (i = 0; i < j; i++) 4577c478bd9Sstevel@tonic-gate free(list[i]); 4587c478bd9Sstevel@tonic-gate free(list); 4597c478bd9Sstevel@tonic-gate return (NULL); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate struct __res_state * 4637c478bd9Sstevel@tonic-gate __hesiod_res_get(void *context) { 4647c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = context; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (!ctx->res) { 4677c478bd9Sstevel@tonic-gate struct __res_state *res; 4687c478bd9Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 4697c478bd9Sstevel@tonic-gate if (res == NULL) { 4707c478bd9Sstevel@tonic-gate errno = ENOMEM; 4717c478bd9Sstevel@tonic-gate return (NULL); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate memset(res, 0, sizeof *res); 4747c478bd9Sstevel@tonic-gate __hesiod_res_set(ctx, res, free); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate return (ctx->res); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate void 4817c478bd9Sstevel@tonic-gate __hesiod_res_set(void *context, struct __res_state *res, 4827c478bd9Sstevel@tonic-gate void (*free_res)(void *)) { 4837c478bd9Sstevel@tonic-gate struct hesiod_p *ctx = context; 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate if (ctx->res && ctx->free_res) { 4867c478bd9Sstevel@tonic-gate res_nclose(ctx->res); 4877c478bd9Sstevel@tonic-gate (*ctx->free_res)(ctx->res); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate ctx->res = res; 4917c478bd9Sstevel@tonic-gate ctx->free_res = free_res; 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate static int 4957c478bd9Sstevel@tonic-gate init(struct hesiod_p *ctx) { 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate if (!ctx->res && !__hesiod_res_get(ctx)) 4987c478bd9Sstevel@tonic-gate return (-1); 4997c478bd9Sstevel@tonic-gate 500*9525b14bSRao Shoaib if (((ctx->res->options & RES_INIT) == 0U) && 5017c478bd9Sstevel@tonic-gate (res_ninit(ctx->res) == -1)) 5027c478bd9Sstevel@tonic-gate return (-1); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate return (0); 5057c478bd9Sstevel@tonic-gate } 506