if2ip.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
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 /* The last 3 #include files should be in this order */
00057 #include "curl_printf.h"
00058 #include "curl_memory.h"
00059 #include "memdebug.h"
00060 
00061 /* ------------------------------------------------------------------ */
00062 
00063 /* Return the scope of the given address. */
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                 /* We are interested only in interface addresses whose
00147                    scope matches the remote address we want to
00148                    connect to: global for global, link-local for
00149                    link-local, etc... */
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               /* Include the scope of this interface as part of the address */
00158               scopeid = ((struct sockaddr_in6 *)(void *)iface->ifa_addr)
00159                             ->sin6_scope_id;
00160 
00161               /* If given, scope id should match. */
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   /* This is here just to support the old interfaces */
00200   char buf[256];
00201 
00202   return (Curl_if2ip(AF_INET, 0 /* unused */, 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     /* With SIOCGIFADDR, we cannot tell the difference between an interface
00237        that does not exist and an interface that has no address of the
00238        correct family. Assume the interface does not exist */
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


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:04