mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-31 19:40:33 +08:00
* cygwin.din: Export gethostbyname2.
* net.cc: define _CYGWIN_IN_H and include resolv.h. (realloc_ent): New function. (dup_ent): Call realloc_ent. (memcpy4to6): New function. (dn_length1): New function. (gethostby_helper): New function. (gethostbyname2): New function. * posix.sgml: Add gethostbyname2. * include/cygwin/version.h: Bump API minor number. * libc/minires.c (get_options): Look for "inet6" and apply bounds to "retry" and "retrans". (res_ninit): Set the default options at the beginning. (dn_expand): Fix "off by one".
This commit is contained in:
parent
45e20e47ba
commit
6f57cb4a52
@ -1,3 +1,20 @@
|
|||||||
|
2009-03-06 Pierre A. Humblet <pierre@phumblet.no-ip.org>
|
||||||
|
|
||||||
|
* cygwin.din: Export gethostbyname2.
|
||||||
|
* net.cc: define _CYGWIN_IN_H and include resolv.h.
|
||||||
|
(realloc_ent): New function.
|
||||||
|
(dup_ent): Call realloc_ent.
|
||||||
|
(memcpy4to6): New function.
|
||||||
|
(dn_length1): New function.
|
||||||
|
(gethostby_helper): New function.
|
||||||
|
(gethostbyname2): New function.
|
||||||
|
* posix.sgml: Add gethostbyname2.
|
||||||
|
* include/cygwin/version.h: Bump API minor number.
|
||||||
|
* libc/minires.c (get_options): Look for "inet6" and apply bounds
|
||||||
|
to "retry" and "retrans".
|
||||||
|
(res_ninit): Set the default options at the beginning.
|
||||||
|
(dn_expand): Fix "off by one".
|
||||||
|
|
||||||
2009-03-06 Corinna Vinschen <corinna@vinschen.de>
|
2009-03-06 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* cygwin.din: Export wprintf, fwprintf, swprintf, vwprintf, vfwprintf,
|
* cygwin.din: Export wprintf, fwprintf, swprintf, vwprintf, vfwprintf,
|
||||||
|
@ -636,6 +636,7 @@ _getgroups = getgroups SIGFE
|
|||||||
_getgroups32 = getgroups32 SIGFE
|
_getgroups32 = getgroups32 SIGFE
|
||||||
gethostbyaddr = cygwin_gethostbyaddr SIGFE
|
gethostbyaddr = cygwin_gethostbyaddr SIGFE
|
||||||
gethostbyname = cygwin_gethostbyname SIGFE
|
gethostbyname = cygwin_gethostbyname SIGFE
|
||||||
|
gethostbyname2 SIGFE
|
||||||
gethostid SIGFE
|
gethostid SIGFE
|
||||||
gethostname = cygwin_gethostname SIGFE
|
gethostname = cygwin_gethostname SIGFE
|
||||||
_gethostname = cygwin_gethostname SIGFE
|
_gethostname = cygwin_gethostname SIGFE
|
||||||
|
@ -350,12 +350,13 @@ details. */
|
|||||||
199: Export open_wmemstream.
|
199: Export open_wmemstream.
|
||||||
200: Export mbsnrtowcs, wcsnrtombs.
|
200: Export mbsnrtowcs, wcsnrtombs.
|
||||||
201: Export wprintf, fwprintf, swprintf, vwprintf, vfwprintf, vswprintf.
|
201: Export wprintf, fwprintf, swprintf, vwprintf, vfwprintf, vswprintf.
|
||||||
|
202: Export gethostbyname2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
||||||
|
|
||||||
#define CYGWIN_VERSION_API_MAJOR 0
|
#define CYGWIN_VERSION_API_MAJOR 0
|
||||||
#define CYGWIN_VERSION_API_MINOR 201
|
#define CYGWIN_VERSION_API_MINOR 202
|
||||||
|
|
||||||
/* There is also a compatibity version number associated with the
|
/* There is also a compatibity version number associated with the
|
||||||
shared memory regions. It is incremented when incompatible
|
shared memory regions. It is incremented when incompatible
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* minires.c. Stub synchronous resolver for Cygwin.
|
/* minires.c. Stub synchronous resolver for Cygwin.
|
||||||
|
|
||||||
Copyright 2006, 2008 Red Hat, Inc.
|
Copyright 2006, 2008, 2009 Red Hat, Inc.
|
||||||
|
|
||||||
Written by Pierre A. Humblet <Pierre.Humblet@ieee.org>
|
Written by Pierre A. Humblet <Pierre.Humblet@ieee.org>
|
||||||
|
|
||||||
@ -99,6 +99,11 @@ static void get_options(res_state statp, int i, char **words)
|
|||||||
DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]);
|
DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcasecmp("inet6", words[i])) {
|
||||||
|
statp->options |= RES_USE_INET6;
|
||||||
|
DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcasecmp("osquery", words[i])) {
|
if (!strcasecmp("osquery", words[i])) {
|
||||||
statp->use_os = 1;
|
statp->use_os = 1;
|
||||||
DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]);
|
DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]);
|
||||||
@ -114,16 +119,22 @@ static void get_options(res_state statp, int i, char **words)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (!strcasecmp("retry", words[i])) {
|
if (!strcasecmp("retry", words[i])
|
||||||
|
|| !strcasecmp("attempts", words[i])) {
|
||||||
if (value < 1)
|
if (value < 1)
|
||||||
value = 1;
|
value = 1;
|
||||||
|
else if (value > RES_MAXRETRY)
|
||||||
|
value = RES_MAXRETRY;
|
||||||
statp->retry = value;
|
statp->retry = value;
|
||||||
DPRINTF(statp->options & RES_DEBUG, "%s: %d\n", words[i], value);
|
DPRINTF(statp->options & RES_DEBUG, "%s: %d\n", words[i], value);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcasecmp("retrans", words[i])) {
|
if (!strcasecmp("retrans", words[i])
|
||||||
|
|| !strcasecmp("timeout", words[i])) {
|
||||||
if (value < 1)
|
if (value < 1)
|
||||||
value = 1;
|
value = 1;
|
||||||
|
else if (value > RES_MAXRETRANS)
|
||||||
|
value = RES_MAXRETRANS;
|
||||||
statp->retrans = value;
|
statp->retrans = value;
|
||||||
DPRINTF(statp->options & RES_DEBUG, "%s: %d\n", words[i], value);
|
DPRINTF(statp->options & RES_DEBUG, "%s: %d\n", words[i], value);
|
||||||
continue;
|
continue;
|
||||||
@ -270,6 +281,9 @@ int res_ninit(res_state statp)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
statp->res_h_errno = NETDB_SUCCESS;
|
statp->res_h_errno = NETDB_SUCCESS;
|
||||||
|
/* Only debug may be set before calling init */
|
||||||
|
statp->options &= RES_DEBUG;
|
||||||
|
statp->options |= RES_INIT | RES_DEFAULT;
|
||||||
statp->nscount = 0;
|
statp->nscount = 0;
|
||||||
statp->os_query = NULL;
|
statp->os_query = NULL;
|
||||||
statp->retrans = RES_TIMEOUT; /* timeout in seconds */
|
statp->retrans = RES_TIMEOUT; /* timeout in seconds */
|
||||||
@ -299,9 +313,6 @@ int res_ninit(res_state statp)
|
|||||||
statp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
|
statp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
|
||||||
bzero(statp->nsaddr_list[i].sin_zero, sizeof(statp->nsaddr_list[i].sin_zero));
|
bzero(statp->nsaddr_list[i].sin_zero, sizeof(statp->nsaddr_list[i].sin_zero));
|
||||||
}
|
}
|
||||||
/* Only debug may be set before calling init */
|
|
||||||
statp->options &= RES_DEBUG;
|
|
||||||
statp->options |= RES_INIT | RES_DEFAULT;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -806,7 +817,7 @@ int dn_expand(const unsigned char *msg, const unsigned char *eomorig,
|
|||||||
exp_dn++;
|
exp_dn++;
|
||||||
else do {
|
else do {
|
||||||
if (len <= MAXLABEL) {
|
if (len <= MAXLABEL) {
|
||||||
if ((length -= (len + 1)) > 0 /* Need space for final . */
|
if ((length -= (len + 1)) >= 0 /* Need space for final . */
|
||||||
&& comp_dn + len <= eomorig) {
|
&& comp_dn + len <= eomorig) {
|
||||||
do { *exp_dn++ = *comp_dn++; } while (--len != 0);
|
do { *exp_dn++ = *comp_dn++; } while (--len != 0);
|
||||||
*exp_dn++ = '.';
|
*exp_dn++ = '.';
|
||||||
@ -836,7 +847,6 @@ expand_fail:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
*
|
*
|
||||||
dn_comp
|
dn_comp
|
||||||
@ -926,8 +936,7 @@ int dn_comp(const char * exp_dn, u_char * comp_dn, int length,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
*
|
* dn_skipname
|
||||||
dn_skipname
|
|
||||||
|
|
||||||
Measures the compressed domain name length and returns it.
|
Measures the compressed domain name length and returns it.
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
@ -949,3 +958,38 @@ int dn_skipname(const unsigned char *comp_dn, const unsigned char *eom)
|
|||||||
|
|
||||||
return comp_dn - comp_dn_orig;
|
return comp_dn - comp_dn_orig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
* dn_length1 For internal use
|
||||||
|
|
||||||
|
Return length of uncompressesed name incl final 0.
|
||||||
|
*****************************************************************/
|
||||||
|
|
||||||
|
int dn_length1(const unsigned char *msg, const unsigned char *eomorig,
|
||||||
|
const unsigned char *comp_dn)
|
||||||
|
{
|
||||||
|
unsigned int len, length = 0;
|
||||||
|
|
||||||
|
errno = EINVAL;
|
||||||
|
if (comp_dn >= eomorig)
|
||||||
|
goto expand_fail;
|
||||||
|
else while ((len = *comp_dn++) != 0) {
|
||||||
|
if (len <= MAXLABEL) {
|
||||||
|
if ((comp_dn += len) <= eomorig)
|
||||||
|
length += len + 1;
|
||||||
|
else
|
||||||
|
goto expand_fail;
|
||||||
|
}
|
||||||
|
else if (len >= (128+64)) {
|
||||||
|
comp_dn = msg + (((len & ~(128+64)) << 8) + *comp_dn);
|
||||||
|
if (comp_dn >= eomorig)
|
||||||
|
goto expand_fail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto expand_fail;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
|
||||||
|
expand_fail:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* net.cc: network-related routines.
|
/* net.cc: network-related routines.
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||||
2005, 2006, 2007 Red Hat, Inc.
|
2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
@ -43,6 +43,8 @@ details. */
|
|||||||
#include "cygwin/in6.h"
|
#include "cygwin/in6.h"
|
||||||
#include "ifaddrs.h"
|
#include "ifaddrs.h"
|
||||||
#include "tls_pbuf.h"
|
#include "tls_pbuf.h"
|
||||||
|
#define _CYGWIN_IN_H
|
||||||
|
#include <resolv.h>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -53,6 +55,9 @@ extern "C"
|
|||||||
int sscanf (const char *, const char *, ...);
|
int sscanf (const char *, const char *, ...);
|
||||||
int cygwin_inet_aton(const char *, struct in_addr *);
|
int cygwin_inet_aton(const char *, struct in_addr *);
|
||||||
const char *cygwin_inet_ntop (int, const void *, char *, socklen_t);
|
const char *cygwin_inet_ntop (int, const void *, char *, socklen_t);
|
||||||
|
int dn_length1(const unsigned char *, const unsigned char *,
|
||||||
|
const unsigned char *);
|
||||||
|
|
||||||
} /* End of "C" section */
|
} /* End of "C" section */
|
||||||
|
|
||||||
const struct in6_addr in6addr_any = {{IN6ADDR_ANY_INIT}};
|
const struct in6_addr in6addr_any = {{IN6ADDR_ANY_INIT}};
|
||||||
@ -264,6 +269,25 @@ struct pservent
|
|||||||
|
|
||||||
static const char *entnames[] = {"host", "proto", "serv"};
|
static const char *entnames[] = {"host", "proto", "serv"};
|
||||||
|
|
||||||
|
static unionent *
|
||||||
|
realloc_ent (unionent *&dst, int sz)
|
||||||
|
{
|
||||||
|
/* Allocate the storage needed. Allocate a rounded size to attempt to force
|
||||||
|
reuse of this buffer so that a poorly-written caller will not be using
|
||||||
|
a freed buffer. */
|
||||||
|
unsigned rsz = 256 * ((sz + 255) / 256);
|
||||||
|
unionent * ptr;
|
||||||
|
if ((ptr = (unionent *) realloc (dst, rsz)))
|
||||||
|
dst = ptr;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline hostent *
|
||||||
|
realloc_ent (int sz, hostent *)
|
||||||
|
{
|
||||||
|
return (hostent *) realloc_ent (_my_tls.locals.hostent_buf, sz);
|
||||||
|
}
|
||||||
|
|
||||||
/* Generic "dup a {host,proto,serv}ent structure" function.
|
/* Generic "dup a {host,proto,serv}ent structure" function.
|
||||||
This is complicated because we need to be able to free the
|
This is complicated because we need to be able to free the
|
||||||
structure at any point and we can't rely on the pointer contents
|
structure at any point and we can't rely on the pointer contents
|
||||||
@ -310,7 +334,7 @@ dup_ent (unionent *&dst, unionent *src, unionent::struct_type type)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Every *ent begins with a name. Calculate it's length. */
|
/* Every *ent begins with a name. Calculate its length. */
|
||||||
int namelen = strlen_round (src->name);
|
int namelen = strlen_round (src->name);
|
||||||
sz = struct_sz + namelen;
|
sz = struct_sz + namelen;
|
||||||
|
|
||||||
@ -355,13 +379,8 @@ dup_ent (unionent *&dst, unionent *src, unionent::struct_type type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the storage needed. Allocate a rounded size to attempt to force
|
/* Allocate the storage needed. */
|
||||||
reuse of this buffer so that a poorly-written caller will not be using
|
if (realloc_ent (dst, sz))
|
||||||
a freed buffer. */
|
|
||||||
unsigned rsz = 256 * ((sz + 255) / 256);
|
|
||||||
dst = (unionent *) realloc (dst, rsz);
|
|
||||||
|
|
||||||
if (dst)
|
|
||||||
{
|
{
|
||||||
memset (dst, 0, sz);
|
memset (dst, 0, sz);
|
||||||
/* This field is common to all *ent structures but named differently
|
/* This field is common to all *ent structures but named differently
|
||||||
@ -857,6 +876,287 @@ cygwin_gethostbyaddr (const char *addr, int len, int type)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
memcpy4to6 (char *dst, const u_char *src)
|
||||||
|
{
|
||||||
|
const unsigned int h[] = {0, 0, htonl (0xFFFF)};
|
||||||
|
memcpy (dst, h, 12);
|
||||||
|
memcpy (dst + 12, src, NS_INADDRSZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
static hostent *
|
||||||
|
gethostby_helper (const char *name, const int af, const int type,
|
||||||
|
const int addrsize_in, const int addrsize_out)
|
||||||
|
{
|
||||||
|
/* Get the data from the name server */
|
||||||
|
const int maxcount = 3;
|
||||||
|
int old_errno, ancount = 0, anlen = 1024, msgsize = 0;
|
||||||
|
u_char *ptr, *msg = NULL;
|
||||||
|
int sz;
|
||||||
|
hostent *ret;
|
||||||
|
char *string_ptr;
|
||||||
|
|
||||||
|
while ((anlen > msgsize) && (ancount++ < maxcount))
|
||||||
|
{
|
||||||
|
msgsize = anlen;
|
||||||
|
ptr = (u_char *) realloc (msg, msgsize);
|
||||||
|
if (ptr == NULL )
|
||||||
|
{
|
||||||
|
old_errno = errno;
|
||||||
|
free (msg);
|
||||||
|
set_errno (old_errno);
|
||||||
|
h_errno = NETDB_INTERNAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
msg = ptr;
|
||||||
|
anlen = res_search (name, ns_c_in, type, msg, msgsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ancount >= maxcount)
|
||||||
|
{
|
||||||
|
free (msg);
|
||||||
|
h_errno = NO_RECOVERY;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (anlen < 0) /* errno and h_errno are set */
|
||||||
|
{
|
||||||
|
old_errno = errno;
|
||||||
|
free (msg);
|
||||||
|
set_errno (old_errno);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
u_char *eomsg = msg + anlen - 1;
|
||||||
|
|
||||||
|
|
||||||
|
/* We scan the answer records to determine the required memory size.
|
||||||
|
They can be corrupted and we don't fully trust that the message
|
||||||
|
follows the standard exactly. glibc applies some checks that
|
||||||
|
we emulate.
|
||||||
|
The answers are copied in the hostent structure in a second scan.
|
||||||
|
To simplify the second scan we store information as follows:
|
||||||
|
- "class" is replaced by the compressed name size
|
||||||
|
- the first 16 bits of the "ttl" store the expanded name size + 1
|
||||||
|
- the last 16 bits of the "ttl" store the offset to the next valid record.
|
||||||
|
Note that "type" is rewritten in host byte order. */
|
||||||
|
|
||||||
|
class record {
|
||||||
|
public:
|
||||||
|
unsigned type: 16; // type
|
||||||
|
unsigned complen: 16; // class or compressed length
|
||||||
|
unsigned namelen1: 16; // expanded length (with final 0)
|
||||||
|
unsigned next_o: 16; // offset to next valid
|
||||||
|
unsigned size: 16; // data size
|
||||||
|
u_char data[]; // data
|
||||||
|
record * next () { return (record *) (((char *) this) + next_o); }
|
||||||
|
void set_next ( record * nxt) { next_o = ((char *) nxt) - ((char *) this); }
|
||||||
|
u_char * name () { return (u_char *) (((char *) this) - complen); }
|
||||||
|
};
|
||||||
|
|
||||||
|
record * anptr = NULL, * prevptr = NULL, * curptr;
|
||||||
|
int i, alias_count = 0, string_size = 0, address_count = 0;
|
||||||
|
int complen, namelen1 = 0, address_len = 0, antype, anclass, ansize;
|
||||||
|
|
||||||
|
/* Get the count of answers */
|
||||||
|
ancount = ntohs (((HEADER *) msg)->ancount);
|
||||||
|
|
||||||
|
/* Skip the question, it was verified by res_send */
|
||||||
|
ptr = msg + sizeof (HEADER);
|
||||||
|
if ((complen = dn_skipname (ptr, eomsg)) < 0)
|
||||||
|
goto corrupted;
|
||||||
|
/* Point to the beginning of the answer section */
|
||||||
|
ptr += complen + NS_QFIXEDSZ;
|
||||||
|
|
||||||
|
/* Scan the answer records to determine the sizes */
|
||||||
|
for (i = 0; i < ancount; i++, ptr = curptr->data + ansize)
|
||||||
|
{
|
||||||
|
if ((complen = dn_skipname (ptr, eomsg)) < 0)
|
||||||
|
goto corrupted;
|
||||||
|
|
||||||
|
curptr = (record *) (ptr + complen);
|
||||||
|
antype = ntohs (curptr->type);
|
||||||
|
anclass = ntohs (curptr->complen);
|
||||||
|
ansize = ntohs (curptr->size);
|
||||||
|
/* Class must be internet */
|
||||||
|
if (anclass != ns_c_in)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
curptr->complen = complen;
|
||||||
|
if ((namelen1 = dn_length1 (msg, eomsg, curptr-> name())) <= 0)
|
||||||
|
goto corrupted;
|
||||||
|
|
||||||
|
if (antype == ns_t_cname)
|
||||||
|
{
|
||||||
|
alias_count++;
|
||||||
|
string_size += namelen1;
|
||||||
|
}
|
||||||
|
else if (antype == type)
|
||||||
|
{
|
||||||
|
ansize = ntohs (curptr->size);
|
||||||
|
if (ansize != addrsize_in)
|
||||||
|
continue;
|
||||||
|
if (address_count == 0)
|
||||||
|
{
|
||||||
|
address_len = namelen1;
|
||||||
|
string_size += namelen1;
|
||||||
|
}
|
||||||
|
else if (address_len != namelen1)
|
||||||
|
continue;
|
||||||
|
address_count++;
|
||||||
|
}
|
||||||
|
/* Update the records */
|
||||||
|
curptr->type = antype; /* Host byte order */
|
||||||
|
curptr->namelen1 = namelen1;
|
||||||
|
if (! anptr)
|
||||||
|
anptr = prevptr = curptr;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prevptr->set_next (curptr);
|
||||||
|
prevptr = curptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is no address, quit */
|
||||||
|
if (address_count == 0)
|
||||||
|
{
|
||||||
|
free (msg);
|
||||||
|
h_errno = NO_DATA;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine the total size */
|
||||||
|
sz = DWORD_round (sizeof(hostent))
|
||||||
|
+ sizeof (char *) * (alias_count + address_count + 2)
|
||||||
|
+ string_size
|
||||||
|
+ address_count * addrsize_out;
|
||||||
|
|
||||||
|
ret = realloc_ent (sz, (hostent *) NULL);
|
||||||
|
if (! ret)
|
||||||
|
{
|
||||||
|
old_errno = errno;
|
||||||
|
free (msg);
|
||||||
|
set_errno (old_errno);
|
||||||
|
h_errno = NETDB_INTERNAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->h_addrtype = af;
|
||||||
|
ret->h_length = addrsize_out;
|
||||||
|
ret->h_aliases = (char **) (((char *) ret) + DWORD_round (sizeof(hostent)));
|
||||||
|
ret->h_addr_list = ret->h_aliases + alias_count + 1;
|
||||||
|
string_ptr = (char *) (ret->h_addr_list + address_count + 1);
|
||||||
|
|
||||||
|
/* Rescan the answers */
|
||||||
|
ancount = alias_count + address_count; /* Valid records */
|
||||||
|
alias_count = address_count = 0;
|
||||||
|
|
||||||
|
for (i = 0, curptr = anptr; i < ancount; i++, curptr = curptr->next ())
|
||||||
|
{
|
||||||
|
antype = curptr->type;
|
||||||
|
if (antype == ns_t_cname)
|
||||||
|
{
|
||||||
|
complen = dn_expand (msg, eomsg, curptr->name (), string_ptr, string_size);
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
if (complen != curptr->complen)
|
||||||
|
go to debugging;
|
||||||
|
#endif
|
||||||
|
ret->h_aliases[alias_count++] = string_ptr;
|
||||||
|
namelen1 = curptr->namelen1;
|
||||||
|
string_ptr += namelen1;
|
||||||
|
string_size -= namelen1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (antype == type)
|
||||||
|
{
|
||||||
|
if (address_count == 0)
|
||||||
|
{
|
||||||
|
complen = dn_expand (msg, eomsg, curptr->name(), string_ptr, string_size);
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
if (complen != curptr->complen)
|
||||||
|
go to debugging;
|
||||||
|
#endif
|
||||||
|
ret->h_name = string_ptr;
|
||||||
|
namelen1 = curptr->namelen1;
|
||||||
|
string_ptr += namelen1;
|
||||||
|
string_size -= namelen1;
|
||||||
|
}
|
||||||
|
ret->h_addr_list[address_count++] = string_ptr;
|
||||||
|
if (addrsize_in != addrsize_out)
|
||||||
|
memcpy4to6 (string_ptr, curptr->data);
|
||||||
|
else
|
||||||
|
memcpy (string_ptr, curptr->data, addrsize_in);
|
||||||
|
string_ptr += addrsize_out;
|
||||||
|
string_size -= addrsize_out;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
/* Should not get here */
|
||||||
|
go to debugging;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
if (string_size < 0)
|
||||||
|
go to debugging;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free (msg);
|
||||||
|
|
||||||
|
ret->h_aliases[alias_count] = NULL;
|
||||||
|
ret->h_addr_list[address_count] = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
corrupted:
|
||||||
|
free (msg);
|
||||||
|
/* Hopefully message corruption errors are temporary.
|
||||||
|
Should it be NO_RECOVERY ? */
|
||||||
|
h_errno = TRY_AGAIN;
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
debugging:
|
||||||
|
system_printf ("Please debug.");
|
||||||
|
free (msg);
|
||||||
|
free (ret);
|
||||||
|
h_errno = NO_RECOVERY;
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* gethostbyname2: standards? */
|
||||||
|
extern "C" struct hostent *
|
||||||
|
gethostbyname2 (const char *name, int af)
|
||||||
|
{
|
||||||
|
sig_dispatch_pending ();
|
||||||
|
myfault efault;
|
||||||
|
if (efault.faulted (EFAULT))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(_res.options & RES_INIT))
|
||||||
|
res_init();
|
||||||
|
bool v4to6 = _res.options & RES_USE_INET6;
|
||||||
|
|
||||||
|
int type, addrsize_in, addrsize_out;
|
||||||
|
switch (af)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
addrsize_in = NS_INADDRSZ;
|
||||||
|
addrsize_out = (v4to6) ? NS_IN6ADDRSZ : NS_INADDRSZ;
|
||||||
|
type = ns_t_a;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
addrsize_in = addrsize_out = NS_IN6ADDRSZ;
|
||||||
|
type = ns_t_aaaa;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
set_errno (EAFNOSUPPORT);
|
||||||
|
h_errno = NETDB_INTERNAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gethostby_helper (name, af, type, addrsize_in, addrsize_out);
|
||||||
|
}
|
||||||
|
|
||||||
/* exported as accept: standards? */
|
/* exported as accept: standards? */
|
||||||
extern "C" int
|
extern "C" int
|
||||||
cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len)
|
cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len)
|
||||||
@ -2486,10 +2786,6 @@ cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define IN6ADDRSZ 16
|
|
||||||
#define INADDRSZ 4
|
|
||||||
#define INT16SZ 2
|
|
||||||
|
|
||||||
/* int
|
/* int
|
||||||
* inet_pton4(src, dst)
|
* inet_pton4(src, dst)
|
||||||
* like inet_aton() but without all the hexadecimal and shorthand.
|
* like inet_aton() but without all the hexadecimal and shorthand.
|
||||||
|
@ -1067,6 +1067,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
|
|||||||
gcvt (SUSv3)
|
gcvt (SUSv3)
|
||||||
gethostbyaddr (SUSv3)
|
gethostbyaddr (SUSv3)
|
||||||
gethostbyname (SUSv3)
|
gethostbyname (SUSv3)
|
||||||
|
gethostbyname2 (first defined in BIND 4.9.4)
|
||||||
getpass (SUSv2)
|
getpass (SUSv2)
|
||||||
getutent (XPG2)
|
getutent (XPG2)
|
||||||
getutid (XPG2)
|
getutid (XPG2)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user