3 # DP: Hack for some ordering in getaddrinfo lookups
6 echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
10 -patch) patch -d "$2" -f --no-backup-if-mismatch -p1 < $0;;
11 -unpatch) patch -d "$2" -f --no-backup-if-mismatch -R -p1 < $0;;
13 echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
18 --- glibc/sysdeps/posix/getaddrinfo.c~ 2000/11/18 08:30:02 1.34
19 +++ glibc/sysdeps/posix/getaddrinfo.c 2001/01/09 01:46:49
24 -#define gethosts(_family, _type) \
25 +#define gethosts(_family, _type, _name) \
32 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
33 - rc = __gethostbyname2_r (name, _family, &th, tmpbuf, \
34 + rc = __gethostbyname2_r (_name, _family, &th, tmpbuf, \
35 tmpbuflen, &h, &herrno); \
36 } while (rc == ERANGE && herrno == NETDB_INTERNAL); \
40 if (herrno == NETDB_INTERNAL) \
42 __set_h_errno (herrno); \
47 +/* If we are looking for both IPv4 and IPv6 address we don't
48 + want the lookup functions to automatically promote IPv4
49 + addresses to IPv6 addresses. Currently this is decided
50 + by setting the RES_USE_INET6 bit in _res.options. */
51 +#define tryname(__name) \
53 + succeeded = req->ai_family == AF_UNSPEC ? 2 : 1; \
54 + if (req->ai_family == AF_UNSPEC) \
55 + _res.options &= ~RES_USE_INET6; \
56 + if (req->ai_family == AF_UNSPEC || \
57 + req->ai_family == AF_INET6) \
58 + gethosts (AF_INET6, struct in6_addr, __name); \
59 + no_inet6_data = no_data; \
60 + if (req->ai_family == AF_UNSPEC) \
61 + _res.options = old_res_options; \
62 + if (req->ai_family == AF_UNSPEC || \
63 + req->ai_family == AF_INET) \
64 + gethosts (AF_INET, struct in_addr, __name); \
68 gaih_inet (const char *name, const struct gaih_service *service,
69 const struct addrinfo *req, struct addrinfo **pai)
71 struct gaih_addrtuple *at = NULL;
74 + /* Make sure we are initialized now */
75 + if (!(_res.options & RES_INIT))
78 if (req->ai_protocol || req->ai_socktype)
82 struct gaih_addrtuple **pat = &at;
86 int old_res_options = _res.options;
88 - /* If we are looking for both IPv4 and IPv6 address we don't
89 - want the lookup functions to automatically promote IPv4
90 - addresses to IPv6 addresses. Currently this is decided
91 - by setting the RES_USE_INET6 bit in _res.options. */
92 - if (req->ai_family == AF_UNSPEC)
93 - _res.options &= ~RES_USE_INET6;
95 - if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
96 - gethosts (AF_INET6, struct in6_addr);
97 - no_inet6_data = no_data;
98 + /* If we have a dotted name, first try an absolute lookup. This
99 + avoids problem where the resolver will try to search domains
100 + even though we may have a fqdn, which is bad since ipv6 lookups
101 + are performed first. */
102 + if (strchr(name, '.') != NULL)
104 + int namelen = strlen(name);
105 + char *newname = __alloca(namelen + 2);
107 - if (req->ai_family == AF_UNSPEC)
108 - _res.options = old_res_options;
109 + strcpy(newname, name);
110 + newname[namelen] = '.';
111 + newname[namelen+1] = '\0';
113 - if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
114 - gethosts (AF_INET, struct in_addr);
118 - if (no_data != 0 && no_inet6_data != 0)
119 + /* If the previous didn't work, or we don't have a dotted name,
120 + we try again like normal, letting the resolver manage domain
122 + if (succeeded <= 0)
124 - /* If both requests timed out report this. */
125 - if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
128 - /* We made requests but they turned out no data. The name
129 - is known, though. */
130 - return (GAIH_OKIFUNSPEC | -EAI_NODATA);
131 + _res.options = old_res_options;
133 + if (succeeded == 0) /* we've tried absolute, now try searches */
138 + if (no_data != 0 && no_inet6_data != 0)
140 + /* If both requests timed out report this. */
141 + if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
144 + /* We made requests but they turned out no data. The name
145 + is known, though. */
146 + return (GAIH_OKIFUNSPEC | -EAI_NODATA);