summaryrefslogtreecommitdiffstats
path: root/contrib/bind/lib/irs/lcl_ho.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/lib/irs/lcl_ho.c')
-rw-r--r--contrib/bind/lib/irs/lcl_ho.c158
1 files changed, 129 insertions, 29 deletions
diff --git a/contrib/bind/lib/irs/lcl_ho.c b/contrib/bind/lib/irs/lcl_ho.c
index b285d1c..5939207 100644
--- a/contrib/bind/lib/irs/lcl_ho.c
+++ b/contrib/bind/lib/irs/lcl_ho.c
@@ -32,7 +32,7 @@
*/
/*
- * Portions Copyright (c) 1996 by Internet Software Consortium.
+ * Portions 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
@@ -52,7 +52,7 @@
/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id: lcl_ho.c,v 1.15 1997/12/04 04:57:56 halley Exp $";
+static const char rcsid[] = "$Id: lcl_ho.c,v 1.25 1999/10/13 17:11:19 vixie Exp $";
#endif /* LIBC_SCCS and not lint */
/* Imports. */
@@ -77,6 +77,7 @@ static char rcsid[] = "$Id: lcl_ho.c,v 1.15 1997/12/04 04:57:56 halley Exp $";
#include <string.h>
#include <irs.h>
+#include <isc/memcluster.h>
#include "port_after.h"
@@ -89,8 +90,6 @@ static char rcsid[] = "$Id: lcl_ho.c,v 1.15 1997/12/04 04:57:56 halley Exp $";
# define SPRINTF(x) sprintf x
#endif
-extern int h_errno;
-
/* Definitions. */
#define MAXALIASES 35
@@ -110,6 +109,8 @@ struct pvt {
char * host_aliases[MAXALIASES];
char hostbuf[8*1024];
u_char host_addr[16]; /* IPv4 or IPv6 */
+ struct __res_state *res;
+ void (*free_res)(void *);
};
typedef union {
@@ -131,8 +132,13 @@ static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
static struct hostent * ho_next(struct irs_ho *this);
static void ho_rewind(struct irs_ho *this);
static void ho_minimize(struct irs_ho *this);
+static struct __res_state * ho_res_get(struct irs_ho *this);
+static void ho_res_set(struct irs_ho *this,
+ struct __res_state *res,
+ void (*free_res)(void *));
static size_t ns_namelen(const char *);
+static int init(struct irs_ho *this);
/* Portability. */
@@ -147,12 +153,13 @@ irs_lcl_ho(struct irs_acc *this) {
struct irs_ho *ho;
struct pvt *pvt;
- if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) {
+ if (!(pvt = memget(sizeof *pvt))) {
errno = ENOMEM;
return (NULL);
}
memset(pvt, 0, sizeof *pvt);
- if (!(ho = malloc(sizeof *ho))) {
+ if (!(ho = memget(sizeof *ho))) {
+ memput(pvt, sizeof *pvt);
errno = ENOMEM;
return (NULL);
}
@@ -165,6 +172,8 @@ irs_lcl_ho(struct irs_acc *this) {
ho->next = ho_next;
ho->rewind = ho_rewind;
ho->minimize = ho_minimize;
+ ho->res_get = ho_res_get;
+ ho->res_set = ho_res_set;
return (ho);
}
@@ -174,19 +183,24 @@ static void
ho_close(struct irs_ho *this) {
struct pvt *pvt = (struct pvt *)this->private;
+ ho_minimize(this);
if (pvt->fp)
(void) fclose(pvt->fp);
- free(pvt);
- free(this);
+ if (pvt->res && pvt->free_res)
+ (*pvt->free_res)(pvt->res);
+ memput(pvt, sizeof *pvt);
+ memput(this, sizeof *this);
}
static struct hostent *
ho_byname(struct irs_ho *this, const char *name) {
+ struct pvt *pvt = (struct pvt *)this->private;
struct hostent *hp;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
- if (_res.options & RES_USE_INET6) {
+
+ if (pvt->res->options & RES_USE_INET6) {
hp = ho_byname2(this, name, AF_INET6);
if (hp)
return (hp);
@@ -196,12 +210,14 @@ ho_byname(struct irs_ho *this, const char *name) {
static struct hostent *
ho_byname2(struct irs_ho *this, const char *name, int af) {
+ struct pvt *pvt = (struct pvt *)this->private;
struct hostent *hp;
char **hap;
size_t n;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
+
ho_rewind(this);
n = ns_namelen(name);
while ((hp = ho_next(this)) != NULL) {
@@ -220,21 +236,23 @@ ho_byname2(struct irs_ho *this, const char *name, int af) {
}
found:
if (!hp) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
- h_errno = NETDB_SUCCESS;
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (hp);
}
static struct hostent *
ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
+ struct pvt *pvt = (struct pvt *)this->private;
const u_char *uaddr = addr;
struct hostent *hp;
int size;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (init(this) == -1)
return (NULL);
+
if (af == AF_INET6 && len == IN6ADDRSZ &&
(!memcmp(uaddr, mapped, sizeof mapped) ||
!memcmp(uaddr, tunnelled, sizeof tunnelled))) {
@@ -253,12 +271,12 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
break;
default:
errno = EAFNOSUPPORT;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
if (size > len) {
errno = EINVAL;
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
@@ -289,10 +307,10 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
}
found:
if (!hp) {
- h_errno = HOST_NOT_FOUND;
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
return (NULL);
}
- h_errno = NETDB_SUCCESS;
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (hp);
}
@@ -300,33 +318,67 @@ static struct hostent *
ho_next(struct irs_ho *this) {
struct pvt *pvt = (struct pvt *)this->private;
char *cp, **q, *p;
- int af, len;
+ char *bufp, *ndbuf, *dbuf = NULL;
+ int c, af, len, bufsiz, offset;
+
+ if (init(this) == -1)
+ return (NULL);
if (!pvt->fp)
ho_rewind(this);
if (!pvt->fp) {
- h_errno = NETDB_INTERNAL;
+ RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
return (NULL);
}
+ bufp = pvt->hostbuf;
+ bufsiz = sizeof pvt->hostbuf;
+ offset = 0;
again:
- if (!(p = fgets(pvt->hostbuf, sizeof pvt->hostbuf, pvt->fp))) {
- h_errno = HOST_NOT_FOUND;
+ if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) {
+ RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
+ if (dbuf)
+ free(dbuf);
return (NULL);
}
- if (*p == '#')
+ if (!strchr(p, '\n') && !feof(pvt->fp)) {
+#define GROWBUF 1024
+ /* allocate space for longer line */
+ if (dbuf == NULL) {
+ if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL)
+ strcpy(ndbuf, bufp);
+ } else
+ ndbuf = realloc(dbuf, bufsiz + GROWBUF);
+ if (ndbuf) {
+ dbuf = ndbuf;
+ bufp = dbuf;
+ bufsiz += GROWBUF;
+ offset = strlen(dbuf);
+ } else {
+ /* allocation failed; skip this long line */
+ while ((c = getc(pvt->fp)) != EOF)
+ if (c == '\n')
+ break;
+ if (c != EOF)
+ ungetc(c, pvt->fp);
+ }
goto again;
- if (!(cp = strpbrk(p, "#\n")))
+ }
+
+ p -= offset;
+ offset = 0;
+
+ if (*p == '#')
goto again;
- *cp = '\0';
+ if ((cp = strpbrk(p, "#\n")) != NULL)
+ *cp = '\0';
if (!(cp = strpbrk(p, " \t")))
goto again;
*cp++ = '\0';
- if ((_res.options & RES_USE_INET6) &&
- inet_pton(AF_INET6, p, pvt->host_addr) > 0) {
+ if (inet_pton(AF_INET6, p, pvt->host_addr) > 0) {
af = AF_INET6;
len = IN6ADDRSZ;
} else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) {
- if (_res.options & RES_USE_INET6) {
+ if (pvt->res->options & RES_USE_INET6) {
map_v4v6_address((char*)pvt->host_addr,
(char*)pvt->host_addr);
af = AF_INET6;
@@ -360,7 +412,9 @@ ho_next(struct irs_ho *this) {
*cp++ = '\0';
}
*q = NULL;
- h_errno = NETDB_SUCCESS;
+ if (dbuf)
+ free(dbuf);
+ RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (&pvt->host);
}
@@ -389,6 +443,40 @@ ho_minimize(struct irs_ho *this) {
(void)fclose(pvt->fp);
pvt->fp = NULL;
}
+ if (pvt->res)
+ res_nclose(pvt->res);
+}
+
+static struct __res_state *
+ho_res_get(struct irs_ho *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res) {
+ struct __res_state *res;
+ res = (struct __res_state *)malloc(sizeof *res);
+ if (!res) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ memset(res, 0, sizeof *res);
+ ho_res_set(this, res, free);
+ }
+
+ return (pvt->res);
+}
+
+static void
+ho_res_set(struct irs_ho *this, struct __res_state *res,
+ void (*free_res)(void *)) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (pvt->res && pvt->free_res) {
+ res_nclose(pvt->res);
+ (*pvt->free_res)(pvt->res);
+ }
+
+ pvt->res = res;
+ pvt->free_res = free_res;
}
/* Private. */
@@ -401,3 +489,15 @@ ns_namelen(const char *s) {
(void)NULL;
return ((size_t) i);
}
+
+static int
+init(struct irs_ho *this) {
+ struct pvt *pvt = (struct pvt *)this->private;
+
+ if (!pvt->res && !ho_res_get(this))
+ return (-1);
+ if (((pvt->res->options & RES_INIT) == 0) &&
+ res_ninit(pvt->res) == -1)
+ return (-1);
+ return (0);
+}
OpenPOWER on IntegriCloud