diff options
author | pyr <> | 2009-06-04 18:06:35 +0000 |
---|---|---|
committer | pyr <> | 2009-06-04 18:06:35 +0000 |
commit | 4b01f04f286ab99a26e81be53e43f8bf46f9496d (patch) | |
tree | c301aa1483a5f910be174da6bb5af7acbafd0609 /src | |
parent | ba53e391e204926a7a71b5a9848b928a56af0062 (diff) | |
download | openbsd-4b01f04f286ab99a26e81be53e43f8bf46f9496d.tar.gz openbsd-4b01f04f286ab99a26e81be53e43f8bf46f9496d.tar.bz2 openbsd-4b01f04f286ab99a26e81be53e43f8bf46f9496d.zip |
Add a resolv.conf option to specify the order in which getaddrinfo
PF_UNSPEC queries are made. While there change the default from inet6
first then inet4 to inet4 first then inet6, this prevents the many
people with IPv4 only connectivity from constantly trying to contact
IPv6 addresses, and also unbreaks many ports who don't use getaddrinfo
right.
ok deraadt@, plenty of cheering in the room wrt the idea, not loud
enough complaining from the v6 crowd.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/net/getaddrinfo.c | 41 | ||||
-rw-r--r-- | src/lib/libc/net/res_init.c | 30 |
2 files changed, 63 insertions, 8 deletions
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c index 0f3b6319f4..87125c89cc 100644 --- a/src/lib/libc/net/getaddrinfo.c +++ b/src/lib/libc/net/getaddrinfo.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: getaddrinfo.c,v 1.67 2007/05/20 03:54:52 ray Exp $ */ | 1 | /* $OpenBSD: getaddrinfo.c,v 1.68 2009/06/04 18:06:35 pyr Exp $ */ |
2 | /* $KAME: getaddrinfo.c,v 1.31 2000/08/31 17:36:43 itojun Exp $ */ | 2 | /* $KAME: getaddrinfo.c,v 1.31 2000/08/31 17:36:43 itojun Exp $ */ |
3 | 3 | ||
4 | /* | 4 | /* |
@@ -233,7 +233,8 @@ static struct addrinfo *getanswer(const querybuf *, int, const char *, int, | |||
233 | static int res_queryN(const char *, struct res_target *); | 233 | static int res_queryN(const char *, struct res_target *); |
234 | static int res_searchN(const char *, struct res_target *); | 234 | static int res_searchN(const char *, struct res_target *); |
235 | static int res_querydomainN(const char *, const char *, struct res_target *); | 235 | static int res_querydomainN(const char *, const char *, struct res_target *); |
236 | static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *); | 236 | static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *, |
237 | const struct __res_state *); | ||
237 | 238 | ||
238 | 239 | ||
239 | /* XXX macros that make external reference is BAD. */ | 240 | /* XXX macros that make external reference is BAD. */ |
@@ -517,7 +518,7 @@ explore_fqdn(const struct addrinfo *pai, const char *hostname, | |||
517 | break; | 518 | break; |
518 | #endif | 519 | #endif |
519 | case 'b': | 520 | case 'b': |
520 | result = _dns_getaddrinfo(hostname, pai); | 521 | result = _dns_getaddrinfo(hostname, pai, _resp); |
521 | break; | 522 | break; |
522 | case 'f': | 523 | case 'f': |
523 | result = _files_getaddrinfo(hostname, pai); | 524 | result = _files_getaddrinfo(hostname, pai); |
@@ -1142,7 +1143,8 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, | |||
1142 | 1143 | ||
1143 | /*ARGSUSED*/ | 1144 | /*ARGSUSED*/ |
1144 | static struct addrinfo * | 1145 | static struct addrinfo * |
1145 | _dns_getaddrinfo(const char *name, const struct addrinfo *pai) | 1146 | _dns_getaddrinfo(const char *name, const struct addrinfo *pai, |
1147 | const struct __res_state *_resp) | ||
1146 | { | 1148 | { |
1147 | struct addrinfo *ai; | 1149 | struct addrinfo *ai; |
1148 | querybuf *buf, *buf2; | 1150 | querybuf *buf, *buf2; |
@@ -1168,14 +1170,39 @@ _dns_getaddrinfo(const char *name, const struct addrinfo *pai) | |||
1168 | 1170 | ||
1169 | switch (pai->ai_family) { | 1171 | switch (pai->ai_family) { |
1170 | case AF_UNSPEC: | 1172 | case AF_UNSPEC: |
1171 | /* prefer IPv6 */ | 1173 | if (_resp->family[0] == -1) { |
1174 | /* prefer IPv4 by default*/ | ||
1175 | q.qclass = C_IN; | ||
1176 | q.qtype = T_A; | ||
1177 | q.answer = buf->buf; | ||
1178 | q.anslen = sizeof(buf->buf); | ||
1179 | q.next = &q2; | ||
1180 | q2.qclass = C_IN; | ||
1181 | q2.qtype = T_AAAA; | ||
1182 | q2.answer = buf2->buf; | ||
1183 | q2.anslen = sizeof(buf2->buf); | ||
1184 | break; | ||
1185 | } | ||
1186 | |||
1187 | /* respect user supplied order */ | ||
1172 | q.qclass = C_IN; | 1188 | q.qclass = C_IN; |
1173 | q.qtype = T_AAAA; | 1189 | if (_resp->family[0] == AF_INET6) |
1190 | q.qtype = T_AAAA; | ||
1191 | else | ||
1192 | q.qtype = T_A; | ||
1174 | q.answer = buf->buf; | 1193 | q.answer = buf->buf; |
1175 | q.anslen = sizeof(buf->buf); | 1194 | q.anslen = sizeof(buf->buf); |
1195 | if (_resp->family[1] == -1) { | ||
1196 | q.next = NULL; | ||
1197 | break; | ||
1198 | } | ||
1176 | q.next = &q2; | 1199 | q.next = &q2; |
1200 | |||
1177 | q2.qclass = C_IN; | 1201 | q2.qclass = C_IN; |
1178 | q2.qtype = T_A; | 1202 | if (_resp->family[1] == AF_INET6) |
1203 | q2.qtype = T_AAAA; | ||
1204 | else | ||
1205 | q2.qtype = T_A; | ||
1179 | q2.answer = buf2->buf; | 1206 | q2.answer = buf2->buf; |
1180 | q2.anslen = sizeof(buf2->buf); | 1207 | q2.anslen = sizeof(buf2->buf); |
1181 | break; | 1208 | break; |
diff --git a/src/lib/libc/net/res_init.c b/src/lib/libc/net/res_init.c index 42d3b3ca1e..5cb597dad8 100644 --- a/src/lib/libc/net/res_init.c +++ b/src/lib/libc/net/res_init.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: res_init.c,v 1.37 2008/08/15 14:57:20 djm Exp $ */ | 1 | /* $OpenBSD: res_init.c,v 1.38 2009/06/04 18:06:35 pyr Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * ++Copyright++ 1985, 1989, 1993 | 4 | * ++Copyright++ 1985, 1989, 1993 |
@@ -165,6 +165,7 @@ _res_init(int usercall) | |||
165 | FILE *fp; | 165 | FILE *fp; |
166 | char *cp, **pp; | 166 | char *cp, **pp; |
167 | int n; | 167 | int n; |
168 | int findex; | ||
168 | char buf[BUFSIZ]; | 169 | char buf[BUFSIZ]; |
169 | int nserv = 0; /* number of nameserver records read from file */ | 170 | int nserv = 0; /* number of nameserver records read from file */ |
170 | int haveenv = 0; | 171 | int haveenv = 0; |
@@ -296,6 +297,33 @@ _res_init(int usercall) | |||
296 | *cp = '\0'; | 297 | *cp = '\0'; |
297 | if (buf[0] == '\0') | 298 | if (buf[0] == '\0') |
298 | continue; | 299 | continue; |
300 | /* set family lookup order */ | ||
301 | if (MATCH(buf, "family")) { | ||
302 | cp = buf + sizeof("family") - 1; | ||
303 | cp += strspn(cp, " \t"); | ||
304 | cp[strcspn(cp, "\n")] = '\0'; | ||
305 | findex = 0; | ||
306 | _resp->family[0] = _resp->family[1] = -1; | ||
307 | while (*cp != '\0' && findex < 2) { | ||
308 | if (!strncmp(cp, "inet6", strlen("inet6"))) { | ||
309 | _resp->family[findex] = AF_INET6; | ||
310 | cp += strlen("inet6"); | ||
311 | } else if (!strncmp(cp, "inet4", | ||
312 | strlen("inet4"))) { | ||
313 | _resp->family[findex] = AF_INET; | ||
314 | cp += strlen("inet4"); | ||
315 | } | ||
316 | if (*cp != ' ' && *cp != '\t' && *cp != '\0') { | ||
317 | _resp->family[findex] = -1; | ||
318 | break; | ||
319 | } | ||
320 | findex++; | ||
321 | cp += strspn(cp, " \t"); | ||
322 | } | ||
323 | |||
324 | if (_resp->family[0] == _resp->family[1]) | ||
325 | _resp->family[1] = -1; | ||
326 | } | ||
299 | /* read default domain name */ | 327 | /* read default domain name */ |
300 | if (MATCH(buf, "domain")) { | 328 | if (MATCH(buf, "domain")) { |
301 | if (haveenv) /* skip if have from environ */ | 329 | if (haveenv) /* skip if have from environ */ |