]> git.pld-linux.org Git - packages/glibc.git/blame - glibc-getaddrinfo-workaround.patch
- unhide some stuff needed by nss_db
[packages/glibc.git] / glibc-getaddrinfo-workaround.patch
CommitLineData
ef28628d
AM
1#! /bin/sh -e
2
3# DP: Hack for some ordering in getaddrinfo lookups
4
5if [ $# -ne 2 ]; then
6 echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
7 exit 1
8fi
9case "$1" in
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;;
12 *)
13 echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
14 exit 1
15esac
16exit 0
17
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
20@@ -264,7 +264,7 @@
21 return 0;
22 }
23
24-#define gethosts(_family, _type) \
25+#define gethosts(_family, _type, _name) \
26 { \
27 int i, herrno; \
28 size_t tmpbuflen; \
29@@ -275,11 +275,12 @@
30 do { \
31 tmpbuflen *= 2; \
e841f13b 32 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
ef28628d
AM
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); \
37 if (rc != 0) \
38 { \
39+ succeeded--; \
40 if (herrno == NETDB_INTERNAL) \
41 { \
42 __set_h_errno (herrno); \
43@@ -307,6 +308,26 @@
44 } \
45 }
46
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) \
52+ { \
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); \
65+ }
66+
67 static int
68 gaih_inet (const char *name, const struct gaih_service *service,
69 const struct addrinfo *req, struct addrinfo **pai)
70@@ -316,6 +337,10 @@
71 struct gaih_addrtuple *at = NULL;
72 int rc;
73
74+ /* Make sure we are initialized now */
75+ if (!(_res.options & RES_INIT))
76+ res_ninit(&_res);
77+
78 if (req->ai_protocol || req->ai_socktype)
79 {
80 ++tp;
81@@ -489,34 +514,47 @@
82 struct gaih_addrtuple **pat = &at;
83 int no_data = 0;
84 int no_inet6_data;
85+ int succeeded = -1;
86 int old_res_options = _res.options;
87
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;
94-
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)
103+ {
104+ int namelen = strlen(name);
105+ char *newname = __alloca(namelen + 2);
106
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';
112
113- if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
114- gethosts (AF_INET, struct in_addr);
115+ tryname(newname);
116+ }
117
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
121+ searching. */
122+ if (succeeded <= 0)
123 {
124- /* If both requests timed out report this. */
125- if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
126- return -EAI_AGAIN;
127-
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;
132+
133+ if (succeeded == 0) /* we've tried absolute, now try searches */
134+ _res.ndots = 99;
135+
136+ tryname(name);
137+
138+ if (no_data != 0 && no_inet6_data != 0)
139+ {
140+ /* If both requests timed out report this. */
141+ if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
142+ return -EAI_AGAIN;
143+
144+ /* We made requests but they turned out no data. The name
145+ is known, though. */
146+ return (GAIH_OKIFUNSPEC | -EAI_NODATA);
147+ }
148 }
149 }
150
This page took 0.053436 seconds and 4 git commands to generate.