diff options
author | Dan Fandrich <dan@coneharvesters.com> | 2008-10-09 19:23:50 +0000 |
---|---|---|
committer | Dan Fandrich <dan@coneharvesters.com> | 2008-10-09 19:23:50 +0000 |
commit | fad3288d20fba6af71fa9bdfb851fe92c3aa2f04 (patch) | |
tree | 16b44ad8c9bfa7780292a744fc43462d16e24b1e /lib/if2ip.c | |
parent | 5ecff1e4c3f92976371634ef40072758d1a17426 (diff) | |
download | curl-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.c | 62 |
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; |