Annotation of embedaddon/curl/lib/if2ip.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
                      9:  *
                     10:  * This software is licensed as described in the file COPYING, which
                     11:  * you should have received as part of this distribution. The terms
                     12:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     13:  *
                     14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     15:  * copies of the Software, and permit persons to whom the Software is
                     16:  * furnished to do so, under the terms of the COPYING file.
                     17:  *
                     18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     19:  * KIND, either express or implied.
                     20:  *
                     21:  ***************************************************************************/
                     22: 
                     23: #include "curl_setup.h"
                     24: 
                     25: #ifdef HAVE_NETINET_IN_H
                     26: #  include <netinet/in.h>
                     27: #endif
                     28: #ifdef HAVE_ARPA_INET_H
                     29: #  include <arpa/inet.h>
                     30: #endif
                     31: #ifdef HAVE_NET_IF_H
                     32: #  include <net/if.h>
                     33: #endif
                     34: #ifdef HAVE_SYS_IOCTL_H
                     35: #  include <sys/ioctl.h>
                     36: #endif
                     37: #ifdef HAVE_NETDB_H
                     38: #  include <netdb.h>
                     39: #endif
                     40: #ifdef HAVE_SYS_SOCKIO_H
                     41: #  include <sys/sockio.h>
                     42: #endif
                     43: #ifdef HAVE_IFADDRS_H
                     44: #  include <ifaddrs.h>
                     45: #endif
                     46: #ifdef HAVE_STROPTS_H
                     47: #  include <stropts.h>
                     48: #endif
                     49: #ifdef __VMS
                     50: #  include <inet.h>
                     51: #endif
                     52: 
                     53: #include "inet_ntop.h"
                     54: #include "strcase.h"
                     55: #include "if2ip.h"
                     56: /* The last 3 #include files should be in this order */
                     57: #include "curl_printf.h"
                     58: #include "curl_memory.h"
                     59: #include "memdebug.h"
                     60: 
                     61: /* ------------------------------------------------------------------ */
                     62: 
                     63: /* Return the scope of the given address. */
                     64: unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
                     65: {
                     66: #ifndef ENABLE_IPV6
                     67:   (void) sa;
                     68: #else
                     69:   if(sa->sa_family == AF_INET6) {
                     70:     const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa;
                     71:     const unsigned char *b = sa6->sin6_addr.s6_addr;
                     72:     unsigned short w = (unsigned short) ((b[0] << 8) | b[1]);
                     73: 
                     74:     if((b[0] & 0xFE) == 0xFC) /* Handle ULAs */
                     75:       return IPV6_SCOPE_UNIQUELOCAL;
                     76:     switch(w & 0xFFC0) {
                     77:     case 0xFE80:
                     78:       return IPV6_SCOPE_LINKLOCAL;
                     79:     case 0xFEC0:
                     80:       return IPV6_SCOPE_SITELOCAL;
                     81:     case 0x0000:
                     82:       w = b[1] | b[2] | b[3] | b[4] | b[5] | b[6] | b[7] | b[8] | b[9] |
                     83:           b[10] | b[11] | b[12] | b[13] | b[14];
                     84:       if(w || b[15] != 0x01)
                     85:         break;
                     86:       return IPV6_SCOPE_NODELOCAL;
                     87:     default:
                     88:       break;
                     89:     }
                     90:   }
                     91: #endif
                     92: 
                     93:   return IPV6_SCOPE_GLOBAL;
                     94: }
                     95: 
                     96: 
                     97: #if defined(HAVE_GETIFADDRS)
                     98: 
                     99: if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                    100:                           unsigned int local_scope_id, const char *interf,
                    101:                           char *buf, int buf_size)
                    102: {
                    103:   struct ifaddrs *iface, *head;
                    104:   if2ip_result_t res = IF2IP_NOT_FOUND;
                    105: 
                    106: #ifndef ENABLE_IPV6
                    107:   (void) remote_scope;
                    108: #endif
                    109: 
                    110: #if !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) || \
                    111:     !defined(ENABLE_IPV6)
                    112:   (void) local_scope_id;
                    113: #endif
                    114: 
                    115:   if(getifaddrs(&head) >= 0) {
                    116:     for(iface = head; iface != NULL; iface = iface->ifa_next) {
                    117:       if(iface->ifa_addr != NULL) {
                    118:         if(iface->ifa_addr->sa_family == af) {
                    119:           if(strcasecompare(iface->ifa_name, interf)) {
                    120:             void *addr;
                    121:             char *ip;
                    122:             char scope[12] = "";
                    123:             char ipstr[64];
                    124: #ifdef ENABLE_IPV6
                    125:             if(af == AF_INET6) {
                    126: #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
                    127:               unsigned int scopeid = 0;
                    128: #endif
                    129:               unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr);
                    130: 
                    131:               if(ifscope != remote_scope) {
                    132:                 /* We are interested only in interface addresses whose scope
                    133:                    matches the remote address we want to connect to: global
                    134:                    for global, link-local for link-local, etc... */
                    135:                 if(res == IF2IP_NOT_FOUND)
                    136:                   res = IF2IP_AF_NOT_SUPPORTED;
                    137:                 continue;
                    138:               }
                    139: 
                    140:               addr =
                    141:                 &((struct sockaddr_in6 *)(void *)iface->ifa_addr)->sin6_addr;
                    142: #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
                    143:               /* Include the scope of this interface as part of the address */
                    144:               scopeid = ((struct sockaddr_in6 *)(void *)iface->ifa_addr)
                    145:                             ->sin6_scope_id;
                    146: 
                    147:               /* If given, scope id should match. */
                    148:               if(local_scope_id && scopeid != local_scope_id) {
                    149:                 if(res == IF2IP_NOT_FOUND)
                    150:                   res = IF2IP_AF_NOT_SUPPORTED;
                    151: 
                    152:                 continue;
                    153:               }
                    154: 
                    155:               if(scopeid)
                    156:                   msnprintf(scope, sizeof(scope), "%%%u", scopeid);
                    157: #endif
                    158:             }
                    159:             else
                    160: #endif
                    161:               addr =
                    162:                   &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
                    163:             res = IF2IP_FOUND;
                    164:             ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
                    165:             msnprintf(buf, buf_size, "%s%s", ip, scope);
                    166:             break;
                    167:           }
                    168:         }
                    169:         else if((res == IF2IP_NOT_FOUND) &&
                    170:                 strcasecompare(iface->ifa_name, interf)) {
                    171:           res = IF2IP_AF_NOT_SUPPORTED;
                    172:         }
                    173:       }
                    174:     }
                    175: 
                    176:     freeifaddrs(head);
                    177:   }
                    178: 
                    179:   return res;
                    180: }
                    181: 
                    182: #elif defined(HAVE_IOCTL_SIOCGIFADDR)
                    183: 
                    184: if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                    185:                           unsigned int local_scope_id, const char *interf,
                    186:                           char *buf, int buf_size)
                    187: {
                    188:   struct ifreq req;
                    189:   struct in_addr in;
                    190:   struct sockaddr_in *s;
                    191:   curl_socket_t dummy;
                    192:   size_t len;
                    193: 
                    194:   (void)remote_scope;
                    195:   (void)local_scope_id;
                    196: 
                    197:   if(!interf || (af != AF_INET))
                    198:     return IF2IP_NOT_FOUND;
                    199: 
                    200:   len = strlen(interf);
                    201:   if(len >= sizeof(req.ifr_name))
                    202:     return IF2IP_NOT_FOUND;
                    203: 
                    204:   dummy = socket(AF_INET, SOCK_STREAM, 0);
                    205:   if(CURL_SOCKET_BAD == dummy)
                    206:     return IF2IP_NOT_FOUND;
                    207: 
                    208:   memset(&req, 0, sizeof(req));
                    209:   memcpy(req.ifr_name, interf, len + 1);
                    210:   req.ifr_addr.sa_family = AF_INET;
                    211: 
                    212:   if(ioctl(dummy, SIOCGIFADDR, &req) < 0) {
                    213:     sclose(dummy);
                    214:     /* With SIOCGIFADDR, we cannot tell the difference between an interface
                    215:        that does not exist and an interface that has no address of the
                    216:        correct family. Assume the interface does not exist */
                    217:     return IF2IP_NOT_FOUND;
                    218:   }
                    219: 
                    220:   s = (struct sockaddr_in *)(void *)&req.ifr_addr;
                    221:   memcpy(&in, &s->sin_addr, sizeof(in));
                    222:   Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
                    223: 
                    224:   sclose(dummy);
                    225:   return IF2IP_FOUND;
                    226: }
                    227: 
                    228: #else
                    229: 
                    230: if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                    231:                           unsigned int local_scope_id, const char *interf,
                    232:                           char *buf, int buf_size)
                    233: {
                    234:     (void) af;
                    235:     (void) remote_scope;
                    236:     (void) local_scope_id;
                    237:     (void) interf;
                    238:     (void) buf;
                    239:     (void) buf_size;
                    240:     return IF2IP_NOT_FOUND;
                    241: }
                    242: 
                    243: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>