summaryrefslogtreecommitdiff
path: root/lib/if2ip.c
diff options
context:
space:
mode:
authorDan Fandrich <dan@coneharvesters.com>2008-10-09 19:23:50 +0000
committerDan Fandrich <dan@coneharvesters.com>2008-10-09 19:23:50 +0000
commitfad3288d20fba6af71fa9bdfb851fe92c3aa2f04 (patch)
tree16b44ad8c9bfa7780292a744fc43462d16e24b1e /lib/if2ip.c
parent5ecff1e4c3f92976371634ef40072758d1a17426 (diff)
downloadcurl-fad3288d20fba6af71fa9bdfb851fe92c3aa2f04.tar.gz
Fixed the --interface option to work with IPv6 connections on glibc
systems supporting getifaddrs(). Also fixed a problem where an IPv6 address could be chosen instead of an IPv4 one for --interface when it involved a name lookup.
Diffstat (limited to 'lib/if2ip.c')
-rw-r--r--lib/if2ip.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/lib/if2ip.c b/lib/if2ip.c
index 94a09c11e..a54050040 100644
--- a/lib/if2ip.c
+++ b/lib/if2ip.c
@@ -42,6 +42,60 @@
!defined(__AMIGA__) && !defined(__minix) && !defined(__SYMBIAN32__) && \
!defined(__WATCOMC__)
+#if defined(HAVE_GETIFADDRS)
+
+/*
+ * glibc provides getifaddrs() to provide a list of all interfaces and their
+ * addresses.
+ */
+
+#include <ifaddrs.h>
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "inet_ntop.h"
+#include "strequal.h"
+
+char *Curl_if2ip(int af, const char *interface, char *buf, int buf_size)
+{
+ struct ifaddrs *iface, *head;
+ char *ip=NULL;
+
+ if (getifaddrs(&head) >= 0) {
+ for (iface=head; iface != NULL; iface=iface->ifa_next) {
+ if ((iface->ifa_addr->sa_family == af) &&
+ curl_strequal(iface->ifa_name, interface)) {
+ void *addr;
+ char scope[12]="";
+ if (af == AF_INET6) {
+ unsigned int scopeid;
+ addr = &((struct sockaddr_in6 *)iface->ifa_addr)->sin6_addr;
+ /* Include the scope of this interface as part of the address */
+ scopeid = ((struct sockaddr_in6 *)iface->ifa_addr)->sin6_scope_id;
+ if (scopeid)
+ snprintf(scope, sizeof(scope), "%%%u", scopeid);
+ } else
+ addr = &((struct sockaddr_in *)iface->ifa_addr)->sin_addr;
+ ip = (char *) Curl_inet_ntop(af, addr, buf, buf_size);
+ Curl_strlcat(buf, scope, buf_size);
+ break;
+ }
+ }
+ freeifaddrs(head);
+ }
+ return ip;
+}
+
+#else
+
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -83,12 +137,12 @@
#define SYS_ERROR -1
-char *Curl_if2ip(const char *interface, char *buf, int buf_size)
+char *Curl_if2ip(int af, const char *interface, char *buf, int buf_size)
{
int dummy;
char *ip=NULL;
- if(!interface)
+ if(!interface || (af != AF_INET))
return NULL;
dummy = socket(AF_INET, SOCK_STREAM, 0);
@@ -124,11 +178,13 @@ char *Curl_if2ip(const char *interface, char *buf, int buf_size)
}
return ip;
}
+#endif
/* -- end of if2ip() -- */
#else
-char *Curl_if2ip(const char *interf, char *buf, int buf_size)
+char *Curl_if2ip(int af, const char *interf, char *buf, int buf_size)
{
+ (void) af;
(void) interf;
(void) buf;
(void) buf_size;