summaryrefslogtreecommitdiff
path: root/lib/libc/asr/gethostnamadr_async.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/asr/gethostnamadr_async.c')
-rw-r--r--lib/libc/asr/gethostnamadr_async.c89
1 files changed, 42 insertions, 47 deletions
diff --git a/lib/libc/asr/gethostnamadr_async.c b/lib/libc/asr/gethostnamadr_async.c
index 47fecca10da..bc338d71776 100644
--- a/lib/libc/asr/gethostnamadr_async.c
+++ b/lib/libc/asr/gethostnamadr_async.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gethostnamadr_async.c,v 1.5 2012/07/12 13:03:34 eric Exp $ */
+/* $OpenBSD: gethostnamadr_async.c,v 1.6 2012/08/19 16:17:40 eric Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
@@ -34,6 +34,11 @@
#define MAXALIASES 16
#define MAXADDRS 16
+#define HOSTENT_PTR(h) ((char**)(((char*)h) + sizeof (*h)))
+#define HOSTENT_POS(h) HOSTENT_PTR(h)[0]
+#define HOSTENT_STOP(h) HOSTENT_PTR(h)[1]
+#define HOSTENT_LEFT(h) (HOSTENT_STOP(h) - HOSTENT_POS(h))
+
ssize_t addr_as_fqdn(const char *, int, char *, size_t);
static int gethostnamadr_async_run(struct async *, struct async_res *);
@@ -291,7 +296,7 @@ gethostnamadr_async_run(struct async *as, struct async_res *ar)
if (hostent_add_addr(ar->ar_hostent,
as->as.hostnamadr.addr,
as->as.hostnamadr.addrlen) == -1) {
- freehostent(ar->ar_hostent);
+ free(ar->ar_hostent);
ar->ar_errno = errno;
ar->ar_h_errno = NETDB_INTERNAL;
async_set_state(as, ASR_STATE_HALT);
@@ -305,7 +310,7 @@ gethostnamadr_async_run(struct async *as, struct async_res *ar)
*/
if (as->as_type == ASR_GETHOSTBYNAME &&
ar->ar_hostent->h_addr_list[0] == NULL) {
- freehostent(ar->ar_hostent);
+ free(ar->ar_hostent);
async_set_state(as, ASR_STATE_NEXT_DB);
break;
}
@@ -381,7 +386,7 @@ found:
goto fail;
return (h);
fail:
- freehostent(h);
+ free(h);
return (NULL);
}
@@ -454,7 +459,7 @@ hostent_from_packet(int reqtype, int family, char *pkt, size_t pktlen)
return (h);
fail:
- freehostent(h);
+ free(h);
return (NULL);
}
@@ -462,19 +467,19 @@ static struct hostent *
hostent_alloc(int family)
{
struct hostent *h;
+ size_t alloc;
- h = calloc(1, sizeof *h);
- if (h == NULL)
+ alloc = sizeof(*h) + (2 + MAXALIASES + MAXADDRS) * sizeof(char*) + 1024;
+ if ((h = calloc(1, alloc)) == NULL)
return (NULL);
- h->h_aliases = calloc(MAXALIASES, sizeof *h->h_aliases);
- h->h_addr_list = calloc(MAXADDRS, sizeof *h->h_addr_list);
- if (h->h_aliases == NULL || h->h_addr_list == NULL) {
- freehostent(h);
- return (NULL);
- }
h->h_addrtype = family;
h->h_length = (family == AF_INET) ? 4 : 16;
+ h->h_aliases = HOSTENT_PTR(h) + 2;
+ h->h_addr_list = h->h_aliases + MAXALIASES;
+
+ HOSTENT_STOP(h) = (char*)(h) + alloc;
+ HOSTENT_POS(h) = (char*)(h->h_addr_list + MAXADDRS);
return (h);
}
@@ -490,12 +495,14 @@ hostent_set_cname(struct hostent *h, const char *name, int isdname)
if (isdname) {
asr_strdname(name, buf, sizeof buf);
buf[strlen(buf) - 1] = '\0';
- h->h_name = strdup(buf);
- } else {
- h->h_name = strdup(name);
+ name = buf;
}
- if (h->h_name == NULL)
- return (-1);
+ if (strlen(name) + 1 >= HOSTENT_LEFT(h))
+ return (1);
+
+ strlcpy(HOSTENT_POS(h), name, HOSTENT_LEFT(h));
+ h->h_name = HOSTENT_POS(h);
+ HOSTENT_POS(h) += strlen(name) + 1;
return (0);
}
@@ -506,21 +513,23 @@ hostent_add_alias(struct hostent *h, const char *name, int isdname)
char buf[MAXDNAME];
size_t i;
- for (i = 0; i < MAXALIASES; i++)
+ for (i = 0; i < MAXALIASES - 1; i++)
if (h->h_aliases[i] == NULL)
break;
- if (i == MAXALIASES)
+ if (i == MAXALIASES - 1)
return (0);
if (isdname) {
asr_strdname(name, buf, sizeof buf);
buf[strlen(buf)-1] = '\0';
- h->h_aliases[i] = strdup(buf);
- } else {
- h->h_aliases[i] = strdup(name);
+ name = buf;
}
- if (h->h_aliases[i] == NULL)
- return (-1);
+ if (strlen(name) + 1 >= HOSTENT_LEFT(h))
+ return (1);
+
+ strlcpy(HOSTENT_POS(h), name, HOSTENT_LEFT(h));
+ h->h_aliases[i] = HOSTENT_POS(h);
+ HOSTENT_POS(h) += strlen(name) + 1;
return (0);
}
@@ -530,36 +539,22 @@ hostent_add_addr(struct hostent *h, const void *addr, int size)
{
int i;
- for (i = 0; i < MAXADDRS; i++)
+ for (i = 0; i < MAXADDRS - 1; i++)
if (h->h_addr_list[i] == NULL)
break;
- if (i == MAXADDRS)
+ if (i == MAXADDRS - 1)
return (0);
- h->h_addr_list[i] = malloc(size);
- if (h->h_addr_list[i] == NULL)
- return (-1);
- memmove(h->h_addr_list[i], addr, size);
+ if (size >= HOSTENT_LEFT(h))
+ return (1);
- return (0);
-}
+ memmove(HOSTENT_POS(h), addr, size);
+ h->h_addr_list[i] = HOSTENT_POS(h);
+ HOSTENT_POS(h) += size;
-void
-freehostent(struct hostent *h)
-{
- char **c;
-
- free(h->h_name);
- for (c = h->h_aliases; *c; c++)
- free(*c);
- free(h->h_aliases);
- for (c = h->h_addr_list; *c; c++)
- free(*c);
- free(h->h_addr_list);
- free(h);
+ return (0);
}
-
ssize_t
addr_as_fqdn(const char *addr, int family, char *dst, size_t max)
{