Annotation of embedaddon/curl/lib/if2ip.c, revision 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>