diff options
Diffstat (limited to 'contrib/bind/lib/irs/hesiod.c')
-rw-r--r-- | contrib/bind/lib/irs/hesiod.c | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/contrib/bind/lib/irs/hesiod.c b/contrib/bind/lib/irs/hesiod.c index a56d213..54a6657 100644 --- a/contrib/bind/lib/irs/hesiod.c +++ b/contrib/bind/lib/irs/hesiod.c @@ -1,9 +1,9 @@ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: hesiod.c,v 1.15 1998/01/26 23:08:24 halley Exp $"; +static const char rcsid[] = "$Id: hesiod.c,v 1.20 1999/02/22 04:09:06 vixie Exp $"; #endif /* - * Copyright (c) 1996 by Internet Software Consortium. + * Copyright (c) 1996,1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -65,6 +65,7 @@ void hesiod_free_list(void *context, char **list); static int parse_config_file(struct hesiod_p *ctx, const char *filename); static char ** get_txt_records(struct hesiod_p *ctx, int class, const char *name); +static int init(struct hesiod_p *ctx); /* Public */ @@ -131,15 +132,16 @@ hesiod_init(void **context) { goto cleanup; } +#if 0 + if (res_ninit(ctx->res) < 0) + goto cleanup; +#endif + *context = ctx; return (0); cleanup: - if (ctx->LHS) - free(ctx->LHS); - if (ctx->RHS) - free(ctx->RHS); - free(ctx); + hesiod_end(ctx); return (-1); } @@ -149,12 +151,18 @@ hesiod_init(void **context) { void hesiod_end(void *context) { struct hesiod_p *ctx = (struct hesiod_p *) context; + int save_errno = errno; + if (ctx->res) + res_nclose(ctx->res); if (ctx->RHS) free(ctx->RHS); if (ctx->LHS) free(ctx->LHS); + if (ctx->res && ctx->free_res) + (*ctx->free_res)(ctx->res); free(ctx); + errno = save_errno; } /* @@ -226,11 +234,17 @@ hesiod_resolve(void *context, const char *name, const char *type) { char *bindname = hesiod_to_bind(context, name, type); char **retvec; - if (!bindname) + if (bindname == NULL) + return (NULL); + if (init(ctx) == -1) { + free(bindname); return (NULL); + } - if ((retvec = get_txt_records(ctx, C_IN, bindname))) + if ((retvec = get_txt_records(ctx, C_IN, bindname))) { + free(bindname); return (retvec); + } if (errno != ENOENT) return (NULL); @@ -322,8 +336,6 @@ parse_config_file(struct hesiod_p *ctx, const char *filename) { /* * Given a DNS class and a DNS name, do a lookup for TXT records, and * return a list of them. - * - * XXX we're still using the non-thread safe res_* routines. */ static char ** get_txt_records(struct hesiod_p *ctx, int class, const char *name) { @@ -333,7 +345,6 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) { int dlen; /* len of data section */ u_char *data; /* pointer to data */ } rr; - struct __res_state save_res; HEADER *hp; u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; u_char *cp, *erdata, *eom; @@ -342,22 +353,15 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) { int i, j, n, skip; /* - * Construct the query and send it. We play games with _res - * since we don't have our own resolver state. Once the - * resolver routines are rewritten to use their own context - * variable, we'll use it here. + * Construct the query and send it. */ - if ((_res.options & RES_INIT) == 0 && res_init() == -1) - return (NULL); - save_res = _res; - n = res_mkquery(QUERY, name, class, T_TXT, NULL, 0, - NULL, qbuf, MAX_HESRESP); + n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0, + NULL, qbuf, MAX_HESRESP); if (n < 0) { errno = EMSGSIZE; return (NULL); } - n = res_send(qbuf, n, abuf, MAX_HESRESP); - _res = save_res; + n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP); if (n < 0) { errno = ECONNREFUSED; return (NULL); @@ -452,3 +456,48 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) { free(list); return (NULL); } + +struct __res_state * +__hesiod_res_get(void *context) { + struct hesiod_p *ctx = context; + + if (!ctx->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + __hesiod_res_set(ctx, res, free); + } + + return (ctx->res); +} + +void +__hesiod_res_set(void *context, struct __res_state *res, + void (*free_res)(void *)) { + struct hesiod_p *ctx = context; + + if (ctx->res && ctx->free_res) { + res_nclose(ctx->res); + (*ctx->free_res)(ctx->res); + } + + ctx->res = res; + ctx->free_res = free_res; +} + +static int +init(struct hesiod_p *ctx) { + + if (!ctx->res && !__hesiod_res_get(ctx)) + return (-1); + + if (((ctx->res->options & RES_INIT) == 0) && + (res_ninit(ctx->res) == -1)) + return (-1); + + return (0); +} |