summaryrefslogtreecommitdiffstats
path: root/common/socket.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2021-09-01 15:48:32 +0200
committerGravatar Nikias Bassen2021-09-01 15:48:32 +0200
commitce7609375646cfb1e7d490579e172c37c74a0589 (patch)
tree0e0855e3c3971fc831c1378c35169990fb21cb13 /common/socket.c
parent24abbb9450c723617e10a6843978aa04a576523e (diff)
downloadlibimobiledevice-ce7609375646cfb1e7d490579e172c37c74a0589.tar.gz
libimobiledevice-ce7609375646cfb1e7d490579e172c37c74a0589.tar.bz2
Remove common code in favor of new libimobiledevice-glue
Diffstat (limited to 'common/socket.c')
-rw-r--r--common/socket.c1169
1 files changed, 0 insertions, 1169 deletions
diff --git a/common/socket.c b/common/socket.c
deleted file mode 100644
index 99a96b1..0000000
--- a/common/socket.c
+++ /dev/null
@@ -1,1169 +0,0 @@
1/*
2 * socket.c
3 *
4 * Copyright (C) 2012-2020 Nikias Bassen <nikias@gmx.li>
5 * Copyright (C) 2012 Martin Szulecki <m.szulecki@libimobiledevice.org>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25#include <stdio.h>
26#include <stddef.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include <errno.h>
31#include <sys/time.h>
32#include <sys/stat.h>
33#ifdef WIN32
34#include <winsock2.h>
35#include <ws2tcpip.h>
36#include <windows.h>
37#ifndef HAVE_GETIFADDRS
38#include <iphlpapi.h>
39#endif
40static int wsa_init = 0;
41#ifndef IFF_RUNNING
42#define IFF_RUNNING IFF_UP
43#endif
44#ifndef AI_NUMERICSERV
45#define AI_NUMERICSERV 0
46#endif
47#else
48#include <sys/socket.h>
49#include <sys/un.h>
50#include <netinet/in.h>
51#include <netinet/tcp.h>
52#include <netdb.h>
53#include <arpa/inet.h>
54#include <fcntl.h>
55#ifdef AF_INET6
56#include <net/if.h>
57#include <ifaddrs.h>
58#endif
59#endif
60#include "socket.h"
61
62#define RECV_TIMEOUT 20000
63#define SEND_TIMEOUT 10000
64#define CONNECT_TIMEOUT 5000
65
66#ifndef EAFNOSUPPORT
67#define EAFNOSUPPORT 102
68#endif
69#ifndef ECONNRESET
70#define ECONNRESET 108
71#endif
72#ifndef ETIMEDOUT
73#define ETIMEDOUT 138
74#endif
75
76static int verbose = 0;
77
78void socket_set_verbose(int level)
79{
80 verbose = level;
81}
82
83const char *socket_addr_to_string(struct sockaddr *addr, char *addr_out, size_t addr_out_size)
84{
85#ifdef WIN32
86 WSADATA wsa_data;
87 if (!wsa_init) {
88 if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
89 fprintf(stderr, "WSAStartup failed!\n");
90 ExitProcess(-1);
91 }
92 wsa_init = 1;
93 }
94 DWORD addr_out_len = addr_out_size;
95 DWORD addrlen = 0;
96
97 if (addr->sa_family == AF_INET) {
98 addrlen = sizeof(struct sockaddr_in);
99 }
100#ifdef AF_INET6
101 else if (addr->sa_family == AF_INET6) {
102 addrlen = sizeof(struct sockaddr_in6);
103 }
104#endif
105 else {
106 errno = EAFNOSUPPORT;
107 return NULL;
108 }
109
110 if (WSAAddressToString(addr, addrlen, NULL, addr_out, &addr_out_len) == 0) {
111 return addr_out;
112 }
113#else
114 const void *addrdata = NULL;
115
116 if (addr->sa_family == AF_INET) {
117 addrdata = &((struct sockaddr_in*)addr)->sin_addr;
118 }
119#ifdef AF_INET6
120 else if (addr->sa_family == AF_INET6) {
121 addrdata = &((struct sockaddr_in6*)addr)->sin6_addr;
122 }
123#endif
124 else {
125 errno = EAFNOSUPPORT;
126 return NULL;
127 }
128
129 if (inet_ntop(addr->sa_family, addrdata, addr_out, addr_out_size)) {
130 return addr_out;
131 }
132#endif
133 return NULL;
134}
135
136#ifndef WIN32
137int socket_create_unix(const char *filename)
138{
139 struct sockaddr_un name;
140 int sock;
141#ifdef SO_NOSIGPIPE
142 int yes = 1;
143#endif
144
145 // remove if still present
146 unlink(filename);
147
148 /* Create the socket. */
149 sock = socket(PF_UNIX, SOCK_STREAM, 0);
150 if (sock < 0) {
151 perror("socket");
152 return -1;
153 }
154
155#ifdef SO_NOSIGPIPE
156 if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
157 perror("setsockopt()");
158 socket_close(sock);
159 return -1;
160 }
161#endif
162
163 /* Bind a name to the socket. */
164 name.sun_family = AF_UNIX;
165 strncpy(name.sun_path, filename, sizeof(name.sun_path));
166 name.sun_path[sizeof(name.sun_path) - 1] = '\0';
167
168 if (bind(sock, (struct sockaddr*)&name, sizeof(name)) < 0) {
169 perror("bind");
170 socket_close(sock);
171 return -1;
172 }
173
174 if (listen(sock, 100) < 0) {
175 perror("listen");
176 socket_close(sock);
177 return -1;
178 }
179
180 return sock;
181}
182
183int socket_connect_unix(const char *filename)
184{
185 struct sockaddr_un name;
186 int sfd = -1;
187 struct stat fst;
188#ifdef SO_NOSIGPIPE
189 int yes = 1;
190#endif
191 int bufsize = 0x20000;
192
193 // check if socket file exists...
194 if (stat(filename, &fst) != 0) {
195 if (verbose >= 2)
196 fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename,
197 strerror(errno));
198 return -1;
199 }
200 // ... and if it is a unix domain socket
201 if (!S_ISSOCK(fst.st_mode)) {
202 if (verbose >= 2)
203 fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__,
204 filename);
205 return -1;
206 }
207 // make a new socket
208 if ((sfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
209 if (verbose >= 2)
210 fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno));
211 return -1;
212 }
213
214 if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void*)&bufsize, sizeof(int)) == -1) {
215 perror("Could not set send buffer for socket");
216 }
217
218 if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, (void*)&bufsize, sizeof(int)) == -1) {
219 perror("Could not set receive buffer for socket");
220 }
221
222#ifdef SO_NOSIGPIPE
223 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
224 perror("setsockopt()");
225 socket_close(sfd);
226 return -1;
227 }
228#endif
229 // and connect to 'filename'
230 name.sun_family = AF_UNIX;
231 strncpy(name.sun_path, filename, sizeof(name.sun_path));
232 name.sun_path[sizeof(name.sun_path) - 1] = 0;
233
234 int flags = fcntl(sfd, F_GETFL, 0);
235 fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
236
237 do {
238 if (connect(sfd, (struct sockaddr*)&name, sizeof(name)) != -1) {
239 break;
240 }
241 if (errno == EINPROGRESS) {
242 fd_set fds;
243 FD_ZERO(&fds);
244 FD_SET(sfd, &fds);
245
246 struct timeval timeout;
247 timeout.tv_sec = CONNECT_TIMEOUT / 1000;
248 timeout.tv_usec = (CONNECT_TIMEOUT - (timeout.tv_sec * 1000)) * 1000;
249 if (select(sfd + 1, NULL, &fds, NULL, &timeout) == 1) {
250 int so_error;
251 socklen_t len = sizeof(so_error);
252 getsockopt(sfd, SOL_SOCKET, SO_ERROR, (void*)&so_error, &len);
253 if (so_error == 0) {
254 break;
255 }
256 }
257 }
258 socket_close(sfd);
259 sfd = -1;
260 } while (0);
261
262 if (sfd < 0) {
263 if (verbose >= 2)
264 fprintf(stderr, "%s: connect: %s\n", __func__, strerror(errno));
265 return -1;
266 }
267
268 return sfd;
269}
270#endif
271
272int socket_create(const char* addr, uint16_t port)
273{
274 int sfd = -1;
275 int yes = 1;
276 struct addrinfo hints;
277 struct addrinfo *result, *rp;
278 char portstr[8];
279 int res;
280#ifdef WIN32
281 WSADATA wsa_data;
282 if (!wsa_init) {
283 if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
284 fprintf(stderr, "WSAStartup failed!\n");
285 ExitProcess(-1);
286 }
287 wsa_init = 1;
288 }
289#endif
290
291 memset(&hints, '\0', sizeof(struct addrinfo));
292 hints.ai_family = AF_UNSPEC;
293 hints.ai_socktype = SOCK_STREAM;
294 hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
295 hints.ai_protocol = IPPROTO_TCP;
296
297 sprintf(portstr, "%d", port);
298
299 if (!addr) {
300 addr = "localhost";
301 }
302 res = getaddrinfo(addr, portstr, &hints, &result);
303 if (res != 0) {
304 fprintf(stderr, "%s: getaddrinfo: %s\n", __func__, gai_strerror(res));
305 return -1;
306 }
307
308 for (rp = result; rp != NULL; rp = rp->ai_next) {
309 sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
310 if (sfd == -1) {
311 continue;
312 }
313
314 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
315 perror("setsockopt()");
316 socket_close(sfd);
317 continue;
318 }
319
320#ifdef SO_NOSIGPIPE
321 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
322 perror("setsockopt()");
323 socket_close(sfd);
324 continue;
325 }
326#endif
327
328#if defined(AF_INET6) && defined(IPV6_V6ONLY)
329 if (rp->ai_family == AF_INET6) {
330 if (setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&yes, sizeof(int)) == -1) {
331 perror("setsockopt() IPV6_V6ONLY");
332 }
333 }
334#endif
335
336 if (bind(sfd, rp->ai_addr, rp->ai_addrlen) < 0) {
337 perror("bind()");
338 socket_close(sfd);
339 continue;
340 }
341
342 if (listen(sfd, 100) < 0) {
343 perror("listen()");
344 socket_close(sfd);
345 continue;
346 }
347 break;
348 }
349
350 freeaddrinfo(result);
351
352 if (rp == NULL) {
353 return -1;
354 }
355
356 return sfd;
357}
358
359#ifdef AF_INET6
360static uint32_t _in6_addr_scope(struct in6_addr* addr)
361{
362 uint32_t scope = 0;
363
364 if (IN6_IS_ADDR_MULTICAST(addr)) {
365 if (IN6_IS_ADDR_MC_NODELOCAL(addr)) {
366 scope = 1;
367 } else if (IN6_IS_ADDR_MC_LINKLOCAL(addr)) {
368 scope = 2;
369 } else if (IN6_IS_ADDR_MC_SITELOCAL(addr)) {
370 scope = 5;
371 }
372
373 return scope;
374 }
375
376 if (IN6_IS_ADDR_LINKLOCAL(addr)) {
377 scope = 2;
378 } else if (IN6_IS_ADDR_LOOPBACK(addr)) {
379 scope = 2;
380 } else if (IN6_IS_ADDR_SITELOCAL(addr)) {
381 scope = 5;
382 } else if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
383 scope = 0;
384 }
385
386 return scope;
387}
388
389#ifndef HAVE_GETIFADDRS
390#ifdef WIN32
391
392struct ifaddrs {
393 struct ifaddrs *ifa_next; /* Next item in list */
394 char *ifa_name; /* Name of interface */
395 unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */
396 struct sockaddr *ifa_addr; /* Address of interface */
397 struct sockaddr *ifa_netmask; /* Netmask of interface */
398 union {
399 struct sockaddr *ifu_broadaddr; /* Broadcast address of interface */
400 struct sockaddr *ifu_dstaddr; /* Point-to-point destination address */
401 } ifa_ifu;
402#define ifa_broadaddr ifa_ifu.ifu_broadaddr
403#define ifa_dstaddr ifa_ifu.ifu_dstaddr
404 void *ifa_data; /* Address-specific data */
405};
406
407#define WORKING_BUFFER_SIZE 15000
408#define MAX_TRIES 3
409
410static void freeifaddrs(struct ifaddrs *ifa)
411{
412 if (!ifa) {
413 return;
414 }
415 free(ifa->ifa_name);
416 free(ifa->ifa_addr);
417 free(ifa->ifa_netmask);
418 free(ifa->ifa_dstaddr);
419 freeifaddrs(ifa->ifa_next);
420 free(ifa);
421}
422
423/*
424 * getifaddrs() reference implementation for win32.
425 * Heavily based on openpgm's implementation found here:
426 * https://github.com/steve-o/openpgm/blob/master/openpgm/pgm/getifaddrs.c
427 */
428static int getifaddrs(struct ifaddrs** ifap)
429{
430 struct ifaddrs* ifa = NULL;
431
432 DWORD dwRetVal = 0;
433
434 PIP_ADAPTER_ADDRESSES pAddresses = NULL;
435 ULONG outBufLen = 0;
436 ULONG Iterations = 0;
437
438 ULONG flags = GAA_FLAG_INCLUDE_PREFIX |
439 GAA_FLAG_SKIP_ANYCAST |
440 GAA_FLAG_SKIP_DNS_SERVER |
441 GAA_FLAG_SKIP_FRIENDLY_NAME |
442 GAA_FLAG_SKIP_MULTICAST;
443
444 PIP_ADAPTER_ADDRESSES adapter = NULL;
445
446 if (!ifap) {
447 errno = EINVAL;
448 return -1;
449 }
450 *ifap = NULL;
451
452 outBufLen = WORKING_BUFFER_SIZE;
453 do {
454 pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);
455 if (pAddresses == NULL) {
456 printf("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
457 return -1;
458 }
459 dwRetVal = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);
460 if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
461 free(pAddresses);
462 pAddresses = NULL;
463 } else {
464 break;
465 }
466 Iterations++;
467 } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
468
469 if (dwRetVal != NO_ERROR) {
470 free(pAddresses);
471 return -1;
472 }
473
474 for (adapter = pAddresses; adapter; adapter = adapter->Next) {
475 int unicastIndex = 0;
476 for (IP_ADAPTER_UNICAST_ADDRESS *unicast = adapter->FirstUnicastAddress; unicast; unicast = unicast->Next, ++unicastIndex) {
477 /* ensure IP adapter */
478 if (AF_INET != unicast->Address.lpSockaddr->sa_family && AF_INET6 != unicast->Address.lpSockaddr->sa_family) {
479 continue;
480 }
481
482 if (!ifa) {
483 ifa = malloc(sizeof(struct ifaddrs));
484 if (!ifa) {
485 errno = ENOMEM;
486 free(pAddresses);
487 return -1;
488 }
489 *ifap = ifa;
490 ifa->ifa_next = NULL;
491 } else {
492 struct ifaddrs* ifanew = malloc(sizeof(struct ifaddrs));
493 if (!ifanew) {
494 freeifaddrs(*ifap);
495 free(pAddresses);
496 errno = ENOMEM;
497 return -1;
498 }
499 ifa->ifa_next = ifanew;
500 ifa = ifanew;
501 ifa->ifa_next = NULL;
502 }
503
504 /* name */
505 ifa->ifa_name = strdup(adapter->AdapterName);
506
507 /* flags */
508 ifa->ifa_flags = 0;
509 if (IfOperStatusUp == adapter->OperStatus)
510 ifa->ifa_flags |= IFF_UP;
511 if (IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)
512 ifa->ifa_flags |= IFF_LOOPBACK;
513 if (!(adapter->Flags & IP_ADAPTER_NO_MULTICAST))
514 ifa->ifa_flags |= IFF_MULTICAST;
515
516 /* address */
517 ifa->ifa_addr = (struct sockaddr*)malloc(sizeof(struct sockaddr_storage));
518 memcpy(ifa->ifa_addr, unicast->Address.lpSockaddr, unicast->Address.iSockaddrLength);
519
520 /* netmask */
521 ifa->ifa_netmask = (struct sockaddr*)malloc(sizeof(struct sockaddr_storage));
522 memset(ifa->ifa_netmask, 0, sizeof(struct sockaddr_storage));
523
524/* pre-Vista must hunt for matching prefix in linked list, otherwise use
525 * OnLinkPrefixLength from IP_ADAPTER_UNICAST_ADDRESS structure.
526 * FirstPrefix requires Windows XP SP1, from SP1 to pre-Vista provides a
527 * single adapter prefix for each IP address. Vista and later provides
528 * host IP address prefix, subnet IP address, and subnet broadcast IP
529 * address. In addition there is a multicast and broadcast address prefix.
530 */
531 ULONG prefixLength = 0;
532
533#if defined( _WIN32 ) && ( _WIN32_WINNT >= 0x0600 )
534/* For a unicast IPv4 address, any value greater than 32 is an illegal
535 * value. For a unicast IPv6 address, any value greater than 128 is an
536 * illegal value. A value of 255 is commonly used to represent an illegal
537 * value.
538 *
539 * Windows 7 SP1 returns 64 for Teredo links which is incorrect.
540 */
541
542#define IN6_IS_ADDR_TEREDO(addr) \
543 (((const uint32_t *)(addr))[0] == ntohl (0x20010000))
544
545 if (AF_INET6 == unicast->Address.lpSockaddr->sa_family &&
546/* TunnelType only applies to one interface on the adapter and no
547 * convenient method is provided to determine which.
548 */
549 TUNNEL_TYPE_TEREDO == adapter->TunnelType &&
550/* Test the interface with the known Teredo network prefix.
551 */
552 IN6_IS_ADDR_TEREDO( &((struct sockaddr_in6*)(unicast->Address.lpSockaddr))->sin6_addr) &&
553/* Test that this version is actually wrong, subsequent releases from Microsoft
554 * may resolve the issue.
555 */
556 32 != unicast->OnLinkPrefixLength)
557 {
558 prefixLength = 32;
559 }
560 else
561 prefixLength = unicast->OnLinkPrefixLength;
562#else
563/* The order of linked IP_ADAPTER_UNICAST_ADDRESS structures pointed to by
564 * the FirstUnicastAddress member does not have any relationship with the
565 * order of linked IP_ADAPTER_PREFIX structures pointed to by the FirstPrefix
566 * member.
567 *
568 * Example enumeration:
569 * [ no subnet ]
570 * ::1/128 - address
571 * ff00::%1/8 - multicast (no IPv6 broadcast)
572 * 127.0.0.0/8 - subnet
573 * 127.0.0.1/32 - address
574 * 127.255.255.255/32 - subnet broadcast
575 * 224.0.0.0/4 - multicast
576 * 255.255.255.255/32 - broadcast
577 *
578 * Which differs from most adapters listing three IPv6:
579 * fe80::%10/64 - subnet
580 * fe80::51e9:5fe5:4202:325a%10/128 - address
581 * ff00::%10/8 - multicast
582 *
583 * !IfOperStatusUp IPv4 addresses are skipped:
584 * fe80::%13/64 - subnet
585 * fe80::d530:946d:e8df:8c91%13/128 - address
586 * ff00::%13/8 - multicast
587 * [ no subnet ]
588 * [ no address ]
589 * 224.0.0.0/4 - multicast
590 * 255.255.255.255/32 - broadcast
591 *
592 * On PTP links no multicast or broadcast addresses are returned:
593 * [ no subnet ]
594 * fe80::5efe:10.203.9.30/128 - address
595 * [ no multicast ]
596 * [ no multicast ]
597 * [ no broadcast ]
598 *
599 * Active primary IPv6 interfaces are a bit overloaded:
600 * ::/0 - default route
601 * 2001::/32 - global subnet
602 * 2001:0:4137:9e76:2443:d6:ba87:1a2a/128 - global address
603 * fe80::/64 - link-local subnet
604 * fe80::2443:d6:ba87:1a2a/128 - link-local address
605 * ff00::/8 - multicast
606 */
607
608#define IN_LINKLOCAL(a) ((((uint32_t) (a)) & 0xaffff0000) == 0xa9fe0000)
609
610 for (IP_ADAPTER_PREFIX *prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) {
611 LPSOCKADDR lpSockaddr = prefix->Address.lpSockaddr;
612 if (lpSockaddr->sa_family != unicast->Address.lpSockaddr->sa_family)
613 continue;
614/* special cases */
615/* RFC2863: IPv4 interface not up */
616 if (AF_INET == lpSockaddr->sa_family && adapter->OperStatus != IfOperStatusUp) {
617/* RFC3927: link-local IPv4 always has 16-bit CIDR */
618 if (IN_LINKLOCAL( ntohl (((struct sockaddr_in*)(unicast->Address.lpSockaddr))->sin_addr.s_addr))) {
619 prefixLength = 16;
620 }
621 break;
622 }
623/* default IPv6 route */
624 if (AF_INET6 == lpSockaddr->sa_family && 0 == prefix->PrefixLength && IN6_IS_ADDR_UNSPECIFIED( &((struct sockaddr_in6*)(lpSockaddr))->sin6_addr)) {
625 continue;
626 }
627/* Assume unicast address for first prefix of operational adapter */
628 if (AF_INET == lpSockaddr->sa_family)
629 if (IN_MULTICAST( ntohl (((struct sockaddr_in*)(lpSockaddr))->sin_addr.s_addr))) {
630 fprintf(stderr, "FATAL: first prefix is non a unicast address\n");
631 break;
632 }
633 if (AF_INET6 == lpSockaddr->sa_family)
634 if (IN6_IS_ADDR_MULTICAST( &((struct sockaddr_in6*)(lpSockaddr))->sin6_addr)) {
635 fprintf(stderr, "FATAL: first prefix is not a unicast address\n");
636 break;
637 }
638/* Assume subnet or host IP address for XP backward compatibility */
639
640 prefixLength = prefix->PrefixLength;
641 break;
642 }
643#endif /* defined( _WIN32 ) && ( _WIN32_WINNT >= 0x0600 ) */
644
645/* map prefix to netmask */
646 ifa->ifa_netmask->sa_family = unicast->Address.lpSockaddr->sa_family;
647 switch (unicast->Address.lpSockaddr->sa_family) {
648 case AF_INET:
649 if (0 == prefixLength || prefixLength > 32) {
650 prefixLength = 32;
651 }
652#if defined( _WIN32) && ( _WIN32_WINNT >= 0x0600 )
653/* Added in Vista, but no IPv6 equivalent. */
654 {
655 ULONG Mask;
656 ConvertLengthToIpv4Mask (prefixLength, &Mask);
657 ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr = Mask; /* network order */
658 }
659#else
660/* NB: left-shift of full bit-width is undefined in C standard. */
661 ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr = htonl( 0xffffffffU << ( 32 - prefixLength ) );
662#endif
663 break;
664
665 case AF_INET6:
666 if (0 == prefixLength || prefixLength > 128) {
667 prefixLength = 128;
668 }
669 for (LONG i = prefixLength, j = 0; i > 0; i -= 8, ++j) {
670 ((struct sockaddr_in6*)ifa->ifa_netmask)->sin6_addr.s6_addr[ j ] = i >= 8 ? 0xff : (ULONG)(( 0xffU << ( 8 - i ) ) & 0xffU );
671 }
672 break;
673 default:
674 break;
675 }
676 }
677 }
678 free(pAddresses);
679
680 return 0;
681}
682#else
683#error No reference implementation for getifaddrs available for this platform.
684#endif
685#endif
686
687static int32_t _sockaddr_in6_scope_id(struct sockaddr_in6* addr)
688{
689 int32_t res = -1;
690 struct ifaddrs *ifaddr = NULL, *ifa = NULL;
691 uint32_t addr_scope;
692
693 /* get scope for requested address */
694 addr_scope = _in6_addr_scope(&addr->sin6_addr);
695 if (addr_scope == 0) {
696 /* global scope doesn't need a specific scope id */
697 return addr_scope;
698 }
699
700 /* get interfaces */
701 if (getifaddrs(&ifaddr) == -1) {
702 perror("getifaddrs");
703 return res;
704 }
705
706 /* loop over interfaces */
707 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
708 /* skip if no address is available */
709 if (ifa->ifa_addr == NULL) {
710 continue;
711 }
712
713 /* skip if wrong family */
714 if (ifa->ifa_addr->sa_family != AF_INET6) {
715 continue;
716 }
717
718 /* skip if not up */
719 if ((ifa->ifa_flags & IFF_UP) == 0) {
720 continue;
721 }
722
723 /* skip if not running */
724 if ((ifa->ifa_flags & IFF_RUNNING) == 0) {
725 continue;
726 }
727
728 struct sockaddr_in6* addr_in = (struct sockaddr_in6*)ifa->ifa_addr;
729
730 /* skip if scopes do not match */
731 if (_in6_addr_scope(&addr_in->sin6_addr) != addr_scope) {
732 continue;
733 }
734
735 /* use if address is equal */
736 if (memcmp(&addr->sin6_addr.s6_addr, &addr_in->sin6_addr.s6_addr, sizeof(addr_in->sin6_addr.s6_addr)) == 0) {
737 /* if scope id equals the requested one then assume it was valid */
738 if (addr->sin6_scope_id == addr_in->sin6_scope_id) {
739 res = addr_in->sin6_scope_id;
740 break;
741 }
742
743 if ((addr_in->sin6_scope_id > addr->sin6_scope_id) && (res >= 0)) {
744 // use last valid scope id as we're past the requested scope id
745 break;
746 }
747 res = addr_in->sin6_scope_id;
748 continue;
749 }
750
751 /* skip loopback interface if not already matched exactly above */
752 if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) {
753 continue;
754 }
755
756 if ((addr_in->sin6_scope_id > addr->sin6_scope_id) && (res >= 0)) {
757 // use last valid scope id as we're past the requested scope id
758 break;
759 }
760
761 res = addr_in->sin6_scope_id;
762
763 /* if scope id equals the requested one then assume it was valid */
764 if (addr->sin6_scope_id == addr_in->sin6_scope_id) {
765 /* set the scope id of this interface as most likely candidate */
766 break;
767 }
768 }
769
770 freeifaddrs(ifaddr);
771
772 return res;
773}
774#endif
775
776int socket_connect_addr(struct sockaddr* addr, uint16_t port)
777{
778 int sfd = -1;
779 int yes = 1;
780 int bufsize = 0x20000;
781 int addrlen = 0;
782#ifdef WIN32
783 u_long l_yes = 1;
784 WSADATA wsa_data;
785 if (!wsa_init) {
786 if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
787 fprintf(stderr, "WSAStartup failed!\n");
788 ExitProcess(-1);
789 }
790 wsa_init = 1;
791 }
792#endif
793
794 if (addr->sa_family == AF_INET) {
795 struct sockaddr_in* addr_in = (struct sockaddr_in*)addr;
796 addr_in->sin_port = htons(port);
797 addrlen = sizeof(struct sockaddr_in);
798 }
799#ifdef AF_INET6
800 else if (addr->sa_family == AF_INET6) {
801 struct sockaddr_in6* addr_in = (struct sockaddr_in6*)addr;
802 addr_in->sin6_port = htons(port);
803
804 /*
805 * IPv6 Routing Magic:
806 *
807 * If the scope of the address is a link-local one, IPv6 requires the
808 * scope id set to an interface number to allow proper routing. However,
809 * as the provided sockaddr might contain a wrong scope id, we must find
810 * a scope id from a suitable interface on this system or routing might
811 * fail. An IPv6 guru should have another look though...
812 */
813 addr_in->sin6_scope_id = _sockaddr_in6_scope_id(addr_in);
814
815 addrlen = sizeof(struct sockaddr_in6);
816 }
817#endif
818 else {
819 fprintf(stderr, "ERROR: Unsupported address family");
820 return -1;
821 }
822
823 sfd = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
824 if (sfd == -1) {
825 perror("socket()");
826 return -1;
827 }
828
829#ifdef SO_NOSIGPIPE
830 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
831 perror("setsockopt()");
832 socket_close(sfd);
833 return -1;
834 }
835#endif
836
837 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
838 perror("setsockopt()");
839 socket_close(sfd);
840 return -1;
841 }
842
843#ifdef WIN32
844 ioctlsocket(sfd, FIONBIO, &l_yes);
845#else
846 int flags = fcntl(sfd, F_GETFL, 0);
847 fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
848#endif
849
850 do {
851 if (connect(sfd, addr, addrlen) != -1) {
852 break;
853 }
854#ifdef WIN32
855 if (WSAGetLastError() == WSAEWOULDBLOCK)
856#else
857 if (errno == EINPROGRESS)
858#endif
859 {
860 fd_set fds;
861 FD_ZERO(&fds);
862 FD_SET(sfd, &fds);
863
864 struct timeval timeout;
865 timeout.tv_sec = CONNECT_TIMEOUT / 1000;
866 timeout.tv_usec = (CONNECT_TIMEOUT - (timeout.tv_sec * 1000)) * 1000;
867 if (select(sfd + 1, NULL, &fds, NULL, &timeout) == 1) {
868 int so_error;
869 socklen_t len = sizeof(so_error);
870 getsockopt(sfd, SOL_SOCKET, SO_ERROR, (void*)&so_error, &len);
871 if (so_error == 0) {
872 errno = 0;
873 break;
874 }
875 errno = so_error;
876 }
877 }
878 socket_close(sfd);
879 sfd = -1;
880 } while (0);
881
882 if (sfd < 0) {
883 if (verbose >= 2) {
884 char addrtxt[48];
885 socket_addr_to_string(addr, addrtxt, sizeof(addrtxt));
886 fprintf(stderr, "%s: Could not connect to %s port %d\n", __func__, addrtxt, port);
887 }
888 return -1;
889 }
890
891 if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(int)) == -1) {
892 perror("Could not set TCP_NODELAY on socket");
893 }
894
895 if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void*)&bufsize, sizeof(int)) == -1) {
896 perror("Could not set send buffer for socket");
897 }
898
899 if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, (void*)&bufsize, sizeof(int)) == -1) {
900 perror("Could not set receive buffer for socket");
901 }
902
903 return sfd;
904}
905
906int socket_connect(const char *addr, uint16_t port)
907{
908 int sfd = -1;
909 int yes = 1;
910 int bufsize = 0x20000;
911 struct addrinfo hints;
912 struct addrinfo *result, *rp;
913 char portstr[8];
914 int res;
915#ifdef WIN32
916 u_long l_yes = 1;
917 WSADATA wsa_data;
918 if (!wsa_init) {
919 if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
920 fprintf(stderr, "WSAStartup failed!\n");
921 ExitProcess(-1);
922 }
923 wsa_init = 1;
924 }
925#else
926 int flags = 0;
927#endif
928
929 if (!addr) {
930 errno = EINVAL;
931 return -1;
932 }
933
934 memset(&hints, '\0', sizeof(struct addrinfo));
935 hints.ai_family = AF_UNSPEC;
936 hints.ai_socktype = SOCK_STREAM;
937 hints.ai_flags = AI_NUMERICSERV;
938 hints.ai_protocol = IPPROTO_TCP;
939
940 sprintf(portstr, "%d", port);
941
942 res = getaddrinfo(addr, portstr, &hints, &result);
943 if (res != 0) {
944 fprintf(stderr, "%s: getaddrinfo: %s\n", __func__, gai_strerror(res));
945 return -1;
946 }
947
948 for (rp = result; rp != NULL; rp = rp->ai_next) {
949 sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
950 if (sfd == -1) {
951 continue;
952 }
953
954#ifdef SO_NOSIGPIPE
955 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
956 perror("setsockopt()");
957 socket_close(sfd);
958 return -1;
959 }
960#endif
961
962 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
963 perror("setsockopt()");
964 socket_close(sfd);
965 continue;
966 }
967
968#ifdef WIN32
969 ioctlsocket(sfd, FIONBIO, &l_yes);
970#else
971 flags = fcntl(sfd, F_GETFL, 0);
972 fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
973#endif
974
975 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) {
976 break;
977 }
978#ifdef WIN32
979 if (WSAGetLastError() == WSAEWOULDBLOCK)
980#else
981 if (errno == EINPROGRESS)
982#endif
983 {
984 fd_set fds;
985 FD_ZERO(&fds);
986 FD_SET(sfd, &fds);
987
988 struct timeval timeout;
989 timeout.tv_sec = CONNECT_TIMEOUT / 1000;
990 timeout.tv_usec = (CONNECT_TIMEOUT - (timeout.tv_sec * 1000)) * 1000;
991 if (select(sfd + 1, NULL, &fds, NULL, &timeout) == 1) {
992 int so_error;
993 socklen_t len = sizeof(so_error);
994 getsockopt(sfd, SOL_SOCKET, SO_ERROR, (void*)&so_error, &len);
995 if (so_error == 0) {
996 break;
997 }
998 }
999 }
1000 socket_close(sfd);
1001 }
1002
1003 freeaddrinfo(result);
1004
1005 if (rp == NULL) {
1006 if (verbose >= 2)
1007 fprintf(stderr, "%s: Could not connect to %s:%d\n", __func__, addr, port);
1008 return -1;
1009 }
1010
1011 if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(int)) == -1) {
1012 perror("Could not set TCP_NODELAY on socket");
1013 }
1014
1015 if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void*)&bufsize, sizeof(int)) == -1) {
1016 perror("Could not set send buffer for socket");
1017 }
1018
1019 if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, (void*)&bufsize, sizeof(int)) == -1) {
1020 perror("Could not set receive buffer for socket");
1021 }
1022
1023 return sfd;
1024}
1025
1026int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout)
1027{
1028 fd_set fds;
1029 int sret;
1030 int eagain;
1031 struct timeval to;
1032 struct timeval *pto;
1033
1034 if (fd < 0) {
1035 if (verbose >= 2)
1036 fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd);
1037 return -1;
1038 }
1039
1040 FD_ZERO(&fds);
1041 FD_SET(fd, &fds);
1042
1043 sret = -1;
1044
1045 do {
1046 if (timeout > 0) {
1047 to.tv_sec = (time_t) (timeout / 1000);
1048 to.tv_usec = (time_t) ((timeout - (to.tv_sec * 1000)) * 1000);
1049 pto = &to;
1050 } else {
1051 pto = NULL;
1052 }
1053 eagain = 0;
1054 switch (fdm) {
1055 case FDM_READ:
1056 sret = select(fd + 1, &fds, NULL, NULL, pto);
1057 break;
1058 case FDM_WRITE:
1059 sret = select(fd + 1, NULL, &fds, NULL, pto);
1060 break;
1061 case FDM_EXCEPT:
1062 sret = select(fd + 1, NULL, NULL, &fds, pto);
1063 break;
1064 default:
1065 return -1;
1066 }
1067
1068 if (sret < 0) {
1069 switch (errno) {
1070 case EINTR:
1071 // interrupt signal in select
1072 if (verbose >= 2)
1073 fprintf(stderr, "%s: EINTR\n", __func__);
1074 eagain = 1;
1075 break;
1076 case EAGAIN:
1077 if (verbose >= 2)
1078 fprintf(stderr, "%s: EAGAIN\n", __func__);
1079 break;
1080 default:
1081 if (verbose >= 2)
1082 fprintf(stderr, "%s: select failed: %s\n", __func__,
1083 strerror(errno));
1084 return -1;
1085 }
1086 } else if (sret == 0) {
1087 return -ETIMEDOUT;
1088 }
1089 } while (eagain);
1090
1091 return sret;
1092}
1093
1094int socket_accept(int fd, uint16_t port)
1095{
1096#ifdef WIN32
1097 int addr_len;
1098#else
1099 socklen_t addr_len;
1100#endif
1101 int result;
1102 struct sockaddr_storage addr;
1103 addr_len = sizeof(addr);
1104
1105 result = accept(fd, (struct sockaddr*)&addr, &addr_len);
1106
1107 return result;
1108}
1109
1110int socket_shutdown(int fd, int how)
1111{
1112 return shutdown(fd, how);
1113}
1114
1115int socket_close(int fd) {
1116#ifdef WIN32
1117 return closesocket(fd);
1118#else
1119 return close(fd);
1120#endif
1121}
1122
1123int socket_receive(int fd, void *data, size_t length)
1124{
1125 return socket_receive_timeout(fd, data, length, 0, RECV_TIMEOUT);
1126}
1127
1128int socket_peek(int fd, void *data, size_t length)
1129{
1130 return socket_receive_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT);
1131}
1132
1133int socket_receive_timeout(int fd, void *data, size_t length, int flags,
1134 unsigned int timeout)
1135{
1136 int res;
1137 int result;
1138
1139 // check if data is available
1140 res = socket_check_fd(fd, FDM_READ, timeout);
1141 if (res <= 0) {
1142 return res;
1143 }
1144 // if we get here, there _is_ data available
1145 result = recv(fd, data, length, flags);
1146 if (res > 0 && result == 0) {
1147 // but this is an error condition
1148 if (verbose >= 3)
1149 fprintf(stderr, "%s: fd=%d recv returned 0\n", __func__, fd);
1150 return -ECONNRESET;
1151 }
1152 if (result < 0) {
1153 return -errno;
1154 }
1155 return result;
1156}
1157
1158int socket_send(int fd, void *data, size_t length)
1159{
1160 int flags = 0;
1161 int res = socket_check_fd(fd, FDM_WRITE, SEND_TIMEOUT);
1162 if (res <= 0) {
1163 return res;
1164 }
1165#ifdef MSG_NOSIGNAL
1166 flags |= MSG_NOSIGNAL;
1167#endif
1168 return send(fd, data, length, flags);
1169}