summaryrefslogtreecommitdiff
path: root/net.c
diff options
context:
space:
mode:
authorViktor Söderqvist <viktor.soderqvist@est.tech>2022-09-01 12:04:59 +0200
committerMichael Grunder <michael.grunder@gmail.com>2022-09-01 10:42:36 -0700
commit10c78c6e179a32b3e1f9cd99bf18dcf0c37d295e (patch)
tree36ea03abf4c9351a374e92a201c3c8cdc60788a3 /net.c
parent1abe0c8285100e31a4688b3b09023eb3ad942394 (diff)
Add possibility to prefer IPv6, IPv4 or unspecified
Diffstat (limited to 'net.c')
-rw-r--r--net.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/net.c b/net.c
index 8378c28..8cd3d71 100644
--- a/net.c
+++ b/net.c
@@ -439,17 +439,25 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
- /* Try with IPv6 if no IPv4 address was found. We do it in this order since
- * in a Redis client you can't afford to test if you have IPv6 connectivity
- * as this would add latency to every connect. Otherwise a more sensible
- * route could be: Use IPv6 if both addresses are available and there is IPv6
- * connectivity. */
- if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) {
- hints.ai_family = AF_INET6;
- if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
- __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
- return REDIS_ERR;
- }
+ /* DNS lookup. To use dual stack, set both flags to prefer both IPv4 and
+ * IPv6. By default, for historical reasons, we try IPv4 first and then we
+ * try IPv6 only if no IPv4 address was found. */
+ if (c->flags & REDIS_PREFER_IPV6 && c->flags & REDIS_PREFER_IPV4)
+ hints.ai_family = AF_UNSPEC;
+ else if (c->flags & REDIS_PREFER_IPV6)
+ hints.ai_family = AF_INET6;
+ else
+ hints.ai_family = AF_INET;
+
+ rv = getaddrinfo(c->tcp.host, _port, &hints, &servinfo);
+ if (rv != 0 && hints.ai_family != AF_UNSPEC) {
+ /* Try again with the other IP version. */
+ hints.ai_family = (hints.ai_family == AF_INET) ? AF_INET6 : AF_INET;
+ rv = getaddrinfo(c->tcp.host, _port, &hints, &servinfo);
+ }
+ if (rv != 0) {
+ __redisSetError(c, REDIS_ERR_OTHER, gai_strerror(rv));
+ return REDIS_ERR;
}
for (p = servinfo; p != NULL; p = p->ai_next) {
addrretry: