00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifdef HAVE_NETINET_IN_H
00026 # include <netinet/in.h>
00027 #endif
00028 #ifdef HAVE_ARPA_INET_H
00029 # include <arpa/inet.h>
00030 #endif
00031 #ifdef HAVE_NET_IF_H
00032 # include <net/if.h>
00033 #endif
00034 #ifdef HAVE_SYS_IOCTL_H
00035 # include <sys/ioctl.h>
00036 #endif
00037 #ifdef HAVE_NETDB_H
00038 # include <netdb.h>
00039 #endif
00040 #ifdef HAVE_SYS_SOCKIO_H
00041 # include <sys/sockio.h>
00042 #endif
00043 #ifdef HAVE_IFADDRS_H
00044 # include <ifaddrs.h>
00045 #endif
00046 #ifdef HAVE_STROPTS_H
00047 # include <stropts.h>
00048 #endif
00049 #ifdef __VMS
00050 # include <inet.h>
00051 #endif
00052
00053 #include "inet_ntop.h"
00054 #include "strcase.h"
00055 #include "if2ip.h"
00056
00057 #include "curl_printf.h"
00058 #include "curl_memory.h"
00059 #include "memdebug.h"
00060
00061
00062
00063
00064 unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
00065 {
00066 #ifndef ENABLE_IPV6
00067 (void) sa;
00068 #else
00069 if(sa->sa_family == AF_INET6) {
00070 const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa;
00071 const unsigned char *b = sa6->sin6_addr.s6_addr;
00072 unsigned short w = (unsigned short) ((b[0] << 8) | b[1]);
00073
00074 switch(w & 0xFFC0) {
00075 case 0xFE80:
00076 return IPV6_SCOPE_LINKLOCAL;
00077 case 0xFEC0:
00078 return IPV6_SCOPE_SITELOCAL;
00079 case 0x0000:
00080 w = b[1] | b[2] | b[3] | b[4] | b[5] | b[6] | b[7] | b[8] | b[9] |
00081 b[10] | b[11] | b[12] | b[13] | b[14];
00082 if(w || b[15] != 0x01)
00083 break;
00084 return IPV6_SCOPE_NODELOCAL;
00085 default:
00086 break;
00087 }
00088 }
00089 #endif
00090
00091 return IPV6_SCOPE_GLOBAL;
00092 }
00093
00094
00095 #if defined(HAVE_GETIFADDRS)
00096
00097 bool Curl_if_is_interface_name(const char *interf)
00098 {
00099 bool result = FALSE;
00100
00101 struct ifaddrs *iface, *head;
00102
00103 if(getifaddrs(&head) >= 0) {
00104 for(iface=head; iface != NULL; iface=iface->ifa_next) {
00105 if(strcasecompare(iface->ifa_name, interf)) {
00106 result = TRUE;
00107 break;
00108 }
00109 }
00110 freeifaddrs(head);
00111 }
00112 return result;
00113 }
00114
00115 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
00116 unsigned int remote_scope_id, const char *interf,
00117 char *buf, int buf_size)
00118 {
00119 struct ifaddrs *iface, *head;
00120 if2ip_result_t res = IF2IP_NOT_FOUND;
00121
00122 #ifndef ENABLE_IPV6
00123 (void) remote_scope;
00124
00125 #ifndef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
00126 (void) remote_scope_id;
00127 #endif
00128
00129 #endif
00130
00131 if(getifaddrs(&head) >= 0) {
00132 for(iface = head; iface != NULL; iface=iface->ifa_next) {
00133 if(iface->ifa_addr != NULL) {
00134 if(iface->ifa_addr->sa_family == af) {
00135 if(strcasecompare(iface->ifa_name, interf)) {
00136 void *addr;
00137 char *ip;
00138 char scope[12] = "";
00139 char ipstr[64];
00140 #ifdef ENABLE_IPV6
00141 if(af == AF_INET6) {
00142 unsigned int scopeid = 0;
00143 unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr);
00144
00145 if(ifscope != remote_scope) {
00146
00147
00148
00149
00150 if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED;
00151 continue;
00152 }
00153
00154 addr =
00155 &((struct sockaddr_in6 *)(void *)iface->ifa_addr)->sin6_addr;
00156 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
00157
00158 scopeid = ((struct sockaddr_in6 *)(void *)iface->ifa_addr)
00159 ->sin6_scope_id;
00160
00161
00162 if(remote_scope_id && scopeid != remote_scope_id) {
00163 if(res == IF2IP_NOT_FOUND)
00164 res = IF2IP_AF_NOT_SUPPORTED;
00165
00166 continue;
00167 }
00168 #endif
00169 if(scopeid)
00170 snprintf(scope, sizeof(scope), "%%%u", scopeid);
00171 }
00172 else
00173 #endif
00174 addr =
00175 &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
00176 res = IF2IP_FOUND;
00177 ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
00178 snprintf(buf, buf_size, "%s%s", ip, scope);
00179 break;
00180 }
00181 }
00182 else if((res == IF2IP_NOT_FOUND) &&
00183 strcasecompare(iface->ifa_name, interf)) {
00184 res = IF2IP_AF_NOT_SUPPORTED;
00185 }
00186 }
00187 }
00188
00189 freeifaddrs(head);
00190 }
00191
00192 return res;
00193 }
00194
00195 #elif defined(HAVE_IOCTL_SIOCGIFADDR)
00196
00197 bool Curl_if_is_interface_name(const char *interf)
00198 {
00199
00200 char buf[256];
00201
00202 return (Curl_if2ip(AF_INET, 0 , 0, interf, buf, sizeof(buf)) ==
00203 IF2IP_NOT_FOUND) ? FALSE : TRUE;
00204 }
00205
00206 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
00207 unsigned int remote_scope_id, const char *interf,
00208 char *buf, int buf_size)
00209 {
00210 struct ifreq req;
00211 struct in_addr in;
00212 struct sockaddr_in *s;
00213 curl_socket_t dummy;
00214 size_t len;
00215
00216 (void)remote_scope;
00217 (void)remote_scope_id;
00218
00219 if(!interf || (af != AF_INET))
00220 return IF2IP_NOT_FOUND;
00221
00222 len = strlen(interf);
00223 if(len >= sizeof(req.ifr_name))
00224 return IF2IP_NOT_FOUND;
00225
00226 dummy = socket(AF_INET, SOCK_STREAM, 0);
00227 if(CURL_SOCKET_BAD == dummy)
00228 return IF2IP_NOT_FOUND;
00229
00230 memset(&req, 0, sizeof(req));
00231 memcpy(req.ifr_name, interf, len+1);
00232 req.ifr_addr.sa_family = AF_INET;
00233
00234 if(ioctl(dummy, SIOCGIFADDR, &req) < 0) {
00235 sclose(dummy);
00236
00237
00238
00239 return IF2IP_NOT_FOUND;
00240 }
00241
00242 s = (struct sockaddr_in *)&req.ifr_addr;
00243 memcpy(&in, &s->sin_addr, sizeof(in));
00244 Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
00245
00246 sclose(dummy);
00247 return IF2IP_FOUND;
00248 }
00249
00250 #else
00251
00252 bool Curl_if_is_interface_name(const char *interf)
00253 {
00254 (void) interf;
00255
00256 return FALSE;
00257 }
00258
00259 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
00260 unsigned int remote_scope_id, const char *interf,
00261 char *buf, int buf_size)
00262 {
00263 (void) af;
00264 (void) remote_scope;
00265 (void) remote_scope_id;
00266 (void) interf;
00267 (void) buf;
00268 (void) buf_size;
00269 return IF2IP_NOT_FOUND;
00270 }
00271
00272 #endif