Revert "Update to 7.40.1"
[platform/upstream/curl.git] / lib / if2ip.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2013, 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 http://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 "strequal.h"
55 #include "if2ip.h"
56
57 #define _MPRINTF_REPLACE /* use our functions only */
58 #include <curl/mprintf.h>
59
60 #include "curl_memory.h"
61 /* The last #include file should be: */
62 #include "memdebug.h"
63
64 /* ------------------------------------------------------------------ */
65
66 #if defined(HAVE_GETIFADDRS)
67
68 bool Curl_if_is_interface_name(const char *interf)
69 {
70   bool result = FALSE;
71
72   struct ifaddrs *iface, *head;
73
74   if(getifaddrs(&head) >= 0) {
75     for(iface=head; iface != NULL; iface=iface->ifa_next) {
76       if(curl_strequal(iface->ifa_name, interf)) {
77         result = TRUE;
78         break;
79       }
80     }
81     freeifaddrs(head);
82   }
83   return result;
84 }
85
86 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
87                           const char *interf, char *buf, int buf_size)
88 {
89   struct ifaddrs *iface, *head;
90   if2ip_result_t res = IF2IP_NOT_FOUND;
91
92 #ifndef ENABLE_IPV6
93   (void) remote_scope;
94 #endif
95
96   if(getifaddrs(&head) >= 0) {
97     for(iface=head; iface != NULL; iface=iface->ifa_next) {
98       if(iface->ifa_addr != NULL) {
99         if(iface->ifa_addr->sa_family == af) {
100           if(curl_strequal(iface->ifa_name, interf)) {
101             void *addr;
102             char *ip;
103             char scope[12]="";
104             char ipstr[64];
105 #ifdef ENABLE_IPV6
106             if(af == AF_INET6) {
107               unsigned int scopeid = 0;
108               addr = &((struct sockaddr_in6 *)iface->ifa_addr)->sin6_addr;
109 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
110               /* Include the scope of this interface as part of the address */
111               scopeid =
112                 ((struct sockaddr_in6 *)iface->ifa_addr)->sin6_scope_id;
113 #endif
114               if(scopeid != remote_scope) {
115                 /* We are interested only in interface addresses whose
116                    scope ID matches the remote address we want to
117                    connect to: global (0) for global, link-local for
118                    link-local, etc... */
119                 if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED;
120                 continue;
121               }
122               if(scopeid)
123                 snprintf(scope, sizeof(scope), "%%%u", scopeid);
124             }
125             else
126 #endif
127               addr = &((struct sockaddr_in *)iface->ifa_addr)->sin_addr;
128             res = IF2IP_FOUND;
129             ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
130             snprintf(buf, buf_size, "%s%s", ip, scope);
131             break;
132           }
133         }
134         else if((res == IF2IP_NOT_FOUND) &&
135                 curl_strequal(iface->ifa_name, interf)) {
136           res = IF2IP_AF_NOT_SUPPORTED;
137         }
138       }
139     }
140     freeifaddrs(head);
141   }
142   return res;
143 }
144
145 #elif defined(HAVE_IOCTL_SIOCGIFADDR)
146
147 bool Curl_if_is_interface_name(const char *interf)
148 {
149   /* This is here just to support the old interfaces */
150   char buf[256];
151
152   return (Curl_if2ip(AF_INET, 0, interf, buf, sizeof(buf)) ==
153           IF2IP_NOT_FOUND) ? FALSE : TRUE;
154 }
155
156 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
157                           const char *interf, char *buf, int buf_size)
158 {
159   struct ifreq req;
160   struct in_addr in;
161   struct sockaddr_in *s;
162   curl_socket_t dummy;
163   size_t len;
164
165   (void)remote_scope;
166
167   if(!interf || (af != AF_INET))
168     return IF2IP_NOT_FOUND;
169
170   len = strlen(interf);
171   if(len >= sizeof(req.ifr_name))
172     return IF2IP_NOT_FOUND;
173
174   dummy = socket(AF_INET, SOCK_STREAM, 0);
175   if(CURL_SOCKET_BAD == dummy)
176     return IF2IP_NOT_FOUND;
177
178   memset(&req, 0, sizeof(req));
179   memcpy(req.ifr_name, interf, len+1);
180   req.ifr_addr.sa_family = AF_INET;
181
182   if(ioctl(dummy, SIOCGIFADDR, &req) < 0) {
183     sclose(dummy);
184     /* With SIOCGIFADDR, we cannot tell the difference between an interface
185        that does not exist and an interface that has no address of the
186        correct family. Assume the interface does not exist */
187     return IF2IP_NOT_FOUND;
188   }
189
190   s = (struct sockaddr_in *)&req.ifr_addr;
191   memcpy(&in, &s->sin_addr, sizeof(in));
192   Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
193
194   sclose(dummy);
195   return IF2IP_FOUND;
196 }
197
198 #else
199
200 bool Curl_if_is_interface_name(const char *interf)
201 {
202   (void) interf;
203
204   return FALSE;
205 }
206
207 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
208                           const char *interf, char *buf, int buf_size)
209 {
210     (void) af;
211     (void) remote_scope;
212     (void) interf;
213     (void) buf;
214     (void) buf_size;
215     return IF2IP_NOT_FOUND;
216 }
217
218 #endif