if2ip.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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 */
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 bool Curl_if_is_interface_name(const char *interf)
100 {
101  bool result = FALSE;
102 
103  struct ifaddrs *iface, *head;
104 
105  if(getifaddrs(&head) >= 0) {
106  for(iface = head; iface != NULL; iface = iface->ifa_next) {
107  if(strcasecompare(iface->ifa_name, interf)) {
108  result = TRUE;
109  break;
110  }
111  }
112  freeifaddrs(head);
113  }
114  return result;
115 }
116 
117 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
118  unsigned int remote_scope_id, const char *interf,
119  char *buf, int buf_size)
120 {
121  struct ifaddrs *iface, *head;
123 
124 #ifndef ENABLE_IPV6
125  (void) remote_scope;
126 #endif
127 
128 #if !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) || \
129  !defined(ENABLE_IPV6)
130  (void) remote_scope_id;
131 #endif
132 
133  if(getifaddrs(&head) >= 0) {
134  for(iface = head; iface != NULL; iface = iface->ifa_next) {
135  if(iface->ifa_addr != NULL) {
136  if(iface->ifa_addr->sa_family == af) {
137  if(strcasecompare(iface->ifa_name, interf)) {
138  void *addr;
139  char *ip;
140  char scope[12] = "";
141  char ipstr[64];
142 #ifdef ENABLE_IPV6
143  if(af == AF_INET6) {
144  unsigned int scopeid = 0;
145  unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr);
146 
147  if(ifscope != remote_scope) {
148  /* We are interested only in interface addresses whose
149  scope matches the remote address we want to
150  connect to: global for global, link-local for
151  link-local, etc... */
152  if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED;
153  continue;
154  }
155 
156  addr =
157  &((struct sockaddr_in6 *)(void *)iface->ifa_addr)->sin6_addr;
158 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
159  /* Include the scope of this interface as part of the address */
160  scopeid = ((struct sockaddr_in6 *)(void *)iface->ifa_addr)
161  ->sin6_scope_id;
162 
163  /* If given, scope id should match. */
164  if(remote_scope_id && scopeid != remote_scope_id) {
165  if(res == IF2IP_NOT_FOUND)
167 
168  continue;
169  }
170 #endif
171  if(scopeid)
172  snprintf(scope, sizeof(scope), "%%%u", scopeid);
173  }
174  else
175 #endif
176  addr =
177  &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
178  res = IF2IP_FOUND;
179  ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
180  snprintf(buf, buf_size, "%s%s", ip, scope);
181  break;
182  }
183  }
184  else if((res == IF2IP_NOT_FOUND) &&
185  strcasecompare(iface->ifa_name, interf)) {
187  }
188  }
189  }
190 
191  freeifaddrs(head);
192  }
193 
194  return res;
195 }
196 
197 #elif defined(HAVE_IOCTL_SIOCGIFADDR)
198 
199 bool Curl_if_is_interface_name(const char *interf)
200 {
201  /* This is here just to support the old interfaces */
202  char buf[256];
203 
204  return (Curl_if2ip(AF_INET, 0 /* unused */, 0, interf, buf, sizeof(buf)) ==
206 }
207 
208 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
209  unsigned int remote_scope_id, const char *interf,
210  char *buf, int buf_size)
211 {
212  struct ifreq req;
213  struct in_addr in;
214  struct sockaddr_in *s;
215  curl_socket_t dummy;
216  size_t len;
217 
218  (void)remote_scope;
219  (void)remote_scope_id;
220 
221  if(!interf || (af != AF_INET))
222  return IF2IP_NOT_FOUND;
223 
224  len = strlen(interf);
225  if(len >= sizeof(req.ifr_name))
226  return IF2IP_NOT_FOUND;
227 
228  dummy = socket(AF_INET, SOCK_STREAM, 0);
229  if(CURL_SOCKET_BAD == dummy)
230  return IF2IP_NOT_FOUND;
231 
232  memset(&req, 0, sizeof(req));
233  memcpy(req.ifr_name, interf, len + 1);
234  req.ifr_addr.sa_family = AF_INET;
235 
236  if(ioctl(dummy, SIOCGIFADDR, &req) < 0) {
237  sclose(dummy);
238  /* With SIOCGIFADDR, we cannot tell the difference between an interface
239  that does not exist and an interface that has no address of the
240  correct family. Assume the interface does not exist */
241  return IF2IP_NOT_FOUND;
242  }
243 
244  s = (struct sockaddr_in *)(void *)&req.ifr_addr;
245  memcpy(&in, &s->sin_addr, sizeof(in));
246  Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
247 
248  sclose(dummy);
249  return IF2IP_FOUND;
250 }
251 
252 #else
253 
254 bool Curl_if_is_interface_name(const char *interf)
255 {
256  (void) interf;
257 
258  return FALSE;
259 }
260 
261 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
262  unsigned int remote_scope_id, const char *interf,
263  char *buf, int buf_size)
264 {
265  (void) af;
266  (void) remote_scope;
267  (void) remote_scope_id;
268  (void) interf;
269  (void) buf;
270  (void) buf_size;
271  return IF2IP_NOT_FOUND;
272 }
273 
274 #endif
if2ip_result_t
Definition: if2ip.h:37
#define sclose(x)
bool Curl_if_is_interface_name(const char *interf)
Definition: if2ip.c:254
#define CURL_SOCKET_BAD
Definition: curl.h:131
unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
Definition: if2ip.c:64
XmlRpcServer s
#define IPV6_SCOPE_NODELOCAL
Definition: if2ip.h:31
#define IPV6_SCOPE_UNIQUELOCAL
Definition: if2ip.h:30
static int res
#define IPV6_SCOPE_SITELOCAL
Definition: if2ip.h:29
#define strcasecompare(a, b)
Definition: strcase.h:35
UNITTEST_START int result
Definition: unit1304.c:49
char * Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
Definition: inet_ntop.c:183
size_t len
Definition: curl_sasl.c:55
memcpy(filename, filename1, strlen(filename1))
#define IPV6_SCOPE_GLOBAL
Definition: if2ip.h:27
#define FALSE
if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, unsigned int remote_scope_id, const char *interf, char *buf, int buf_size)
Definition: if2ip.c:261
TFSIMD_FORCE_INLINE const tfScalar & w() const
char buf[3]
Definition: unit1398.c:32
#define IPV6_SCOPE_LINKLOCAL
Definition: if2ip.h:28
#define snprintf
Definition: curl_printf.h:42
#define TRUE
int curl_socket_t
Definition: curl.h:130
struct curl_llist_element * head
case 1: list has >1 element, removing head : 1: list size will be decremented by one 2: head will be ...
Definition: unit1300.c:60


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:15