summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpyr <>2009-06-04 18:06:35 +0000
committerpyr <>2009-06-04 18:06:35 +0000
commit4b01f04f286ab99a26e81be53e43f8bf46f9496d (patch)
treec301aa1483a5f910be174da6bb5af7acbafd0609 /src
parentba53e391e204926a7a71b5a9848b928a56af0062 (diff)
downloadopenbsd-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.c41
-rw-r--r--src/lib/libc/net/res_init.c30
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,
233static int res_queryN(const char *, struct res_target *); 233static int res_queryN(const char *, struct res_target *);
234static int res_searchN(const char *, struct res_target *); 234static int res_searchN(const char *, struct res_target *);
235static int res_querydomainN(const char *, const char *, struct res_target *); 235static int res_querydomainN(const char *, const char *, struct res_target *);
236static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *); 236static 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*/
1144static struct addrinfo * 1145static 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 */