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>