summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--common/Makefile.am5
-rw-r--r--common/socket.c1169
-rw-r--r--common/socket.h68
-rw-r--r--common/thread.c140
-rw-r--r--common/thread.h76
-rw-r--r--common/userpref.c3
-rw-r--r--common/utils.c530
-rw-r--r--common/utils.h64
-rw-r--r--configure.ac3
-rw-r--r--src/Makefile.am2
-rw-r--r--src/afc.h2
-rw-r--r--src/companion_proxy.c1
-rw-r--r--src/companion_proxy.h2
-rw-r--r--src/debugserver.c3
-rw-r--r--src/idevice.c5
-rw-r--r--src/installation_proxy.h2
-rw-r--r--src/lockdown.c2
-rw-r--r--src/mobile_image_mounter.h2
-rw-r--r--src/notification_proxy.h2
-rw-r--r--src/preboard.h2
-rw-r--r--src/sbservices.h2
-rw-r--r--src/syslog_relay.h2
-rw-r--r--tools/Makefile.am54
-rw-r--r--tools/idevicebackup.c2
-rw-r--r--tools/idevicebackup2.c2
-rw-r--r--tools/idevicecrashreport.c2
-rw-r--r--tools/idevicedebugserverproxy.c4
-rw-r--r--tools/ideviceimagemounter.c2
-rw-r--r--tools/ideviceinfo.c2
-rw-r--r--tools/ideviceprovision.c2
-rw-r--r--tools/idevicesyslog.c92
32 files changed, 71 insertions, 2181 deletions
diff --git a/README.md b/README.md
index 2f561aa..d838453 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ sudo apt-get install \
62 libtool-bin \ 62 libtool-bin \
63 libplist-dev \ 63 libplist-dev \
64 libusbmuxd-dev \ 64 libusbmuxd-dev \
65 libimobiledevice-glue-dev \
65 libssl-dev \ 66 libssl-dev \
66 usbmuxd 67 usbmuxd
67``` 68```
@@ -188,4 +189,4 @@ iPadOS, tvOS, watchOS, and macOS are trademarks of Apple Inc.
188This project is an independent software and has not been authorized, sponsored, 189This project is an independent software and has not been authorized, sponsored,
189or otherwise approved by Apple Inc. 190or otherwise approved by Apple Inc.
190 191
191README Updated on: 2021-07-27 192README Updated on: 2021-08-30
diff --git a/common/Makefile.am b/common/Makefile.am
index ab01b83..1a90571 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -25,11 +25,8 @@ noinst_LTLIBRARIES = libinternalcommon.la
25libinternalcommon_la_LIBADD = 25libinternalcommon_la_LIBADD =
26libinternalcommon_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined 26libinternalcommon_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined
27libinternalcommon_la_SOURCES = \ 27libinternalcommon_la_SOURCES = \
28 socket.c socket.h \
29 thread.c thread.h \
30 debug.c debug.h \ 28 debug.c debug.h \
31 userpref.c userpref.h \ 29 userpref.c userpref.h
32 utils.c utils.h
33 30
34if WIN32 31if WIN32
35libinternalcommon_la_LIBADD += -lole32 -lws2_32 32libinternalcommon_la_LIBADD += -lole32 -lws2_32
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}
diff --git a/common/socket.h b/common/socket.h
deleted file mode 100644
index 9567270..0000000
--- a/common/socket.h
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * socket.h
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#ifndef SOCKET_SOCKET_H
23#define SOCKET_SOCKET_H
24
25#include <stdlib.h>
26#include <stdint.h>
27
28enum fd_mode {
29 FDM_READ,
30 FDM_WRITE,
31 FDM_EXCEPT
32};
33typedef enum fd_mode fd_mode;
34
35#ifdef WIN32
36#include <winsock2.h>
37#define SHUT_RD SD_READ
38#define SHUT_WR SD_WRITE
39#define SHUT_RDWR SD_BOTH
40#else
41#include <sys/socket.h>
42#endif
43
44#ifndef WIN32
45int socket_create_unix(const char *filename);
46int socket_connect_unix(const char *filename);
47#endif
48int socket_create(const char *addr, uint16_t port);
49int socket_connect_addr(struct sockaddr *addr, uint16_t port);
50int socket_connect(const char *addr, uint16_t port);
51int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout);
52int socket_accept(int fd, uint16_t port);
53
54int socket_shutdown(int fd, int how);
55int socket_close(int fd);
56
57int socket_receive(int fd, void *data, size_t length);
58int socket_peek(int fd, void *data, size_t length);
59int socket_receive_timeout(int fd, void *data, size_t length, int flags,
60 unsigned int timeout);
61
62int socket_send(int fd, void *data, size_t length);
63
64void socket_set_verbose(int level);
65
66const char *socket_addr_to_string(struct sockaddr *addr, char *addr_out, size_t addr_out_size);
67
68#endif /* SOCKET_SOCKET_H */
diff --git a/common/thread.c b/common/thread.c
deleted file mode 100644
index eb535ab..0000000
--- a/common/thread.c
+++ /dev/null
@@ -1,140 +0,0 @@
1/*
2 * thread.c
3 *
4 * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
5 * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
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 "thread.h"
26
27int thread_new(THREAD_T *thread, thread_func_t thread_func, void* data)
28{
29#ifdef WIN32
30 HANDLE th = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, NULL);
31 if (th == NULL) {
32 return -1;
33 }
34 *thread = th;
35 return 0;
36#else
37 int res = pthread_create(thread, NULL, thread_func, data);
38 return res;
39#endif
40}
41
42void thread_detach(THREAD_T thread)
43{
44#ifdef WIN32
45 CloseHandle(thread);
46#else
47 pthread_detach(thread);
48#endif
49}
50
51void thread_free(THREAD_T thread)
52{
53#ifdef WIN32
54 CloseHandle(thread);
55#endif
56}
57
58int thread_join(THREAD_T thread)
59{
60 /* wait for thread to complete */
61#ifdef WIN32
62 return (int)WaitForSingleObject(thread, INFINITE);
63#else
64 return pthread_join(thread, NULL);
65#endif
66}
67
68int thread_alive(THREAD_T thread)
69{
70#ifdef WIN32
71 return WaitForSingleObject(thread, 0) == WAIT_TIMEOUT;
72#else
73 return pthread_kill(thread, 0) == 0;
74#endif
75}
76
77int thread_cancel(THREAD_T thread)
78{
79#ifdef WIN32
80 return -1;
81#else
82#ifdef HAVE_PTHREAD_CANCEL
83 return pthread_cancel(thread);
84#else
85 return -1;
86#endif
87#endif
88}
89
90void mutex_init(mutex_t* mutex)
91{
92#ifdef WIN32
93 InitializeCriticalSection(mutex);
94#else
95 pthread_mutex_init(mutex, NULL);
96#endif
97}
98
99void mutex_destroy(mutex_t* mutex)
100{
101#ifdef WIN32
102 DeleteCriticalSection(mutex);
103#else
104 pthread_mutex_destroy(mutex);
105#endif
106}
107
108void mutex_lock(mutex_t* mutex)
109{
110#ifdef WIN32
111 EnterCriticalSection(mutex);
112#else
113 pthread_mutex_lock(mutex);
114#endif
115}
116
117void mutex_unlock(mutex_t* mutex)
118{
119#ifdef WIN32
120 LeaveCriticalSection(mutex);
121#else
122 pthread_mutex_unlock(mutex);
123#endif
124}
125
126void thread_once(thread_once_t *once_control, void (*init_routine)(void))
127{
128#ifdef WIN32
129 while (InterlockedExchange(&(once_control->lock), 1) != 0) {
130 Sleep(1);
131 }
132 if (!once_control->state) {
133 once_control->state = 1;
134 init_routine();
135 }
136 InterlockedExchange(&(once_control->lock), 0);
137#else
138 pthread_once(once_control, init_routine);
139#endif
140}
diff --git a/common/thread.h b/common/thread.h
deleted file mode 100644
index 23e4510..0000000
--- a/common/thread.h
+++ /dev/null
@@ -1,76 +0,0 @@
1/*
2 * thread.h
3 *
4 * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
5 * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
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#ifndef __THREAD_H
23#define __THREAD_H
24
25#include <stddef.h>
26
27#ifdef WIN32
28#include <windows.h>
29typedef HANDLE THREAD_T;
30typedef CRITICAL_SECTION mutex_t;
31typedef volatile struct {
32 LONG lock;
33 int state;
34} thread_once_t;
35#define THREAD_ONCE_INIT {0, 0}
36#define THREAD_ID GetCurrentThreadId()
37#define THREAD_T_NULL (THREAD_T)NULL
38#else
39#include <pthread.h>
40#include <signal.h>
41typedef pthread_t THREAD_T;
42typedef pthread_mutex_t mutex_t;
43typedef pthread_once_t thread_once_t;
44#define THREAD_ONCE_INIT PTHREAD_ONCE_INIT
45#define THREAD_ID pthread_self()
46#define THREAD_T_NULL (THREAD_T)NULL
47#endif
48
49typedef void* (*thread_func_t)(void* data);
50
51int thread_new(THREAD_T* thread, thread_func_t thread_func, void* data);
52void thread_detach(THREAD_T thread);
53void thread_free(THREAD_T thread);
54int thread_join(THREAD_T thread);
55int thread_alive(THREAD_T thread);
56
57int thread_cancel(THREAD_T thread);
58
59#ifdef WIN32
60#undef HAVE_THREAD_CLEANUP
61#else
62#ifdef HAVE_PTHREAD_CANCEL
63#define HAVE_THREAD_CLEANUP 1
64#define thread_cleanup_push(routine, arg) pthread_cleanup_push(routine, arg)
65#define thread_cleanup_pop(execute) pthread_cleanup_pop(execute)
66#endif
67#endif
68
69void mutex_init(mutex_t* mutex);
70void mutex_destroy(mutex_t* mutex);
71void mutex_lock(mutex_t* mutex);
72void mutex_unlock(mutex_t* mutex);
73
74void thread_once(thread_once_t *once_control, void (*init_routine)(void));
75
76#endif
diff --git a/common/userpref.c b/common/userpref.c
index bf7e1bd..32904c7 100644
--- a/common/userpref.c
+++ b/common/userpref.c
@@ -73,9 +73,10 @@
73#include <shlobj.h> 73#include <shlobj.h>
74#endif 74#endif
75 75
76#include <libimobiledevice-glue/utils.h>
77
76#include "userpref.h" 78#include "userpref.h"
77#include "debug.h" 79#include "debug.h"
78#include "utils.h"
79 80
80#if defined(HAVE_GNUTLS) 81#if defined(HAVE_GNUTLS)
81const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { 82const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
diff --git a/common/utils.c b/common/utils.c
deleted file mode 100644
index 58dac02..0000000
--- a/common/utils.c
+++ /dev/null
@@ -1,530 +0,0 @@
1/*
2 * utils.c
3 * Miscellaneous utilities for string manipulation,
4 * file I/O and plist helper.
5 *
6 * Copyright (c) 2014-2019 Nikias Bassen, All Rights Reserved.
7 * Copyright (c) 2013-2014 Martin Szulecki, All Rights Reserved.
8 * Copyright (c) 2013 Federico Mena Quintero
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <stdarg.h>
30#include <stdlib.h>
31#include <string.h>
32#include <time.h>
33#include <sys/time.h>
34#include <inttypes.h>
35#include <ctype.h>
36
37#include "utils.h"
38
39#ifndef HAVE_STPCPY
40/**
41 * Copy characters from one string into another
42 *
43 * @note: The strings should not overlap, as the behavior is undefined.
44 *
45 * @s1: The source string.
46 * @s2: The destination string.
47 *
48 * @return a pointer to the terminating `\0' character of @s1,
49 * or NULL if @s1 or @s2 is NULL.
50 */
51char *stpcpy(char *s1, const char *s2)
52{
53 if (s1 == NULL || s2 == NULL)
54 return NULL;
55
56 strcpy(s1, s2);
57
58 return s1 + strlen(s2);
59}
60#endif
61
62/**
63 * Concatenate strings into a newly allocated string
64 *
65 * @note: Specify NULL for the last string in the varargs list
66 *
67 * @str: The first string in the list
68 * @...: Subsequent strings. Use NULL for the last item.
69 *
70 * @return a newly allocated string, or NULL if @str is NULL. This will also
71 * return NULL and set errno to ENOMEM if memory is exhausted.
72 */
73char *string_concat(const char *str, ...)
74{
75 size_t len;
76 va_list args;
77 char *s;
78 char *result;
79 char *dest;
80
81 if (!str)
82 return NULL;
83
84 /* Compute final length */
85
86 len = strlen(str) + 1; /* plus 1 for the null terminator */
87
88 va_start(args, str);
89 s = va_arg(args, char *);
90 while (s) {
91 len += strlen(s);
92 s = va_arg(args, char*);
93 }
94 va_end(args);
95
96 /* Concat each string */
97
98 result = malloc(len);
99 if (!result)
100 return NULL; /* errno remains set */
101
102 dest = result;
103
104 dest = stpcpy(dest, str);
105
106 va_start(args, str);
107 s = va_arg(args, char *);
108 while (s) {
109 dest = stpcpy(dest, s);
110 s = va_arg(args, char *);
111 }
112 va_end(args);
113
114 return result;
115}
116
117char *string_append(char* str, ...)
118{
119 size_t len = 0;
120 size_t slen;
121 va_list args;
122 char *s;
123 char *result;
124 char *dest;
125
126 /* Compute final length */
127
128 if (str) {
129 len = strlen(str);
130 }
131 slen = len;
132 len++; /* plus 1 for the null terminator */
133
134 va_start(args, str);
135 s = va_arg(args, char *);
136 while (s) {
137 len += strlen(s);
138 s = va_arg(args, char*);
139 }
140 va_end(args);
141
142 result = realloc(str, len);
143 if (!result)
144 return NULL; /* errno remains set */
145
146 dest = result + slen;
147
148 /* Concat additional strings */
149
150 va_start(args, str);
151 s = va_arg(args, char *);
152 while (s) {
153 dest = stpcpy(dest, s);
154 s = va_arg(args, char *);
155 }
156 va_end(args);
157
158 return result;
159}
160
161char *string_build_path(const char *elem, ...)
162{
163 if (!elem)
164 return NULL;
165 va_list args;
166 int len = strlen(elem)+1;
167 va_start(args, elem);
168 char *arg = va_arg(args, char*);
169 while (arg) {
170 len += strlen(arg)+1;
171 arg = va_arg(args, char*);
172 }
173 va_end(args);
174
175 char* out = (char*)malloc(len);
176 strcpy(out, elem);
177
178 va_start(args, elem);
179 arg = va_arg(args, char*);
180 while (arg) {
181 strcat(out, "/");
182 strcat(out, arg);
183 arg = va_arg(args, char*);
184 }
185 va_end(args);
186 return out;
187}
188
189char *string_format_size(uint64_t size)
190{
191 char buf[80];
192 double sz;
193 if (size >= 1000000000000LL) {
194 sz = ((double)size / 1000000000000.0f);
195 sprintf(buf, "%0.1f TB", sz);
196 } else if (size >= 1000000000LL) {
197 sz = ((double)size / 1000000000.0f);
198 sprintf(buf, "%0.1f GB", sz);
199 } else if (size >= 1000000LL) {
200 sz = ((double)size / 1000000.0f);
201 sprintf(buf, "%0.1f MB", sz);
202 } else if (size >= 1000LL) {
203 sz = ((double)size / 1000.0f);
204 sprintf(buf, "%0.1f KB", sz);
205 } else {
206 sprintf(buf, "%d Bytes", (int)size);
207 }
208 return strdup(buf);
209}
210
211char *string_toupper(char* str)
212{
213 char *res = strdup(str);
214 unsigned int i;
215 for (i = 0; i < strlen(res); i++) {
216 res[i] = toupper(res[i]);
217 }
218 return res;
219}
220
221static int get_rand(int min, int max)
222{
223 int retval = (rand() % (max - min)) + min;
224 return retval;
225}
226
227char *generate_uuid()
228{
229 const char *chars = "ABCDEF0123456789";
230 int i = 0;
231 char *uuid = (char *) malloc(sizeof(char) * 37);
232
233 srand(time(NULL));
234
235 for (i = 0; i < 36; i++) {
236 if (i == 8 || i == 13 || i == 18 || i == 23) {
237 uuid[i] = '-';
238 continue;
239 } else {
240 uuid[i] = chars[get_rand(0, 16)];
241 }
242 }
243
244 /* make it a real string */
245 uuid[36] = '\0';
246
247 return uuid;
248}
249
250void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length)
251{
252 FILE *f;
253 uint64_t size;
254
255 *length = 0;
256
257 f = fopen(filename, "rb");
258 if (!f) {
259 return;
260 }
261
262 fseek(f, 0, SEEK_END);
263 size = ftell(f);
264 rewind(f);
265
266 if (size == 0) {
267 fclose(f);
268 return;
269 }
270
271 *buffer = (char*)malloc(sizeof(char)*(size+1));
272 if (fread(*buffer, sizeof(char), size, f) != size) {
273 fclose(f);
274 return;
275 }
276 fclose(f);
277
278 *length = size;
279}
280
281void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length)
282{
283 FILE *f;
284
285 f = fopen(filename, "wb");
286 if (f) {
287 fwrite(buffer, sizeof(char), length, f);
288 fclose(f);
289 }
290}
291
292int plist_read_from_filename(plist_t *plist, const char *filename)
293{
294 char *buffer = NULL;
295 uint64_t length;
296
297 if (!filename)
298 return 0;
299
300 buffer_read_from_filename(filename, &buffer, &length);
301
302 if (!buffer) {
303 return 0;
304 }
305
306 if ((length > 8) && (memcmp(buffer, "bplist00", 8) == 0)) {
307 plist_from_bin(buffer, length, plist);
308 } else {
309 plist_from_xml(buffer, length, plist);
310 }
311
312 free(buffer);
313
314 return 1;
315}
316
317int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format)
318{
319 char *buffer = NULL;
320 uint32_t length;
321
322 if (!plist || !filename)
323 return 0;
324
325 if (format == PLIST_FORMAT_XML)
326 plist_to_xml(plist, &buffer, &length);
327 else if (format == PLIST_FORMAT_BINARY)
328 plist_to_bin(plist, &buffer, &length);
329 else
330 return 0;
331
332 buffer_write_to_filename(filename, buffer, length);
333
334 free(buffer);
335
336 return 1;
337}
338
339static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
340static const char base64_pad = '=';
341
342static char *base64encode(const unsigned char *buf, size_t size)
343{
344 if (!buf || !(size > 0)) return NULL;
345 int outlen = (size / 3) * 4;
346 char *outbuf = (char*)malloc(outlen+5); // 4 spare bytes + 1 for '\0'
347 size_t n = 0;
348 size_t m = 0;
349 unsigned char input[3];
350 unsigned int output[4];
351 while (n < size) {
352 input[0] = buf[n];
353 input[1] = (n+1 < size) ? buf[n+1] : 0;
354 input[2] = (n+2 < size) ? buf[n+2] : 0;
355 output[0] = input[0] >> 2;
356 output[1] = ((input[0] & 3) << 4) + (input[1] >> 4);
357 output[2] = ((input[1] & 15) << 2) + (input[2] >> 6);
358 output[3] = input[2] & 63;
359 outbuf[m++] = base64_str[(int)output[0]];
360 outbuf[m++] = base64_str[(int)output[1]];
361 outbuf[m++] = (n+1 < size) ? base64_str[(int)output[2]] : base64_pad;
362 outbuf[m++] = (n+2 < size) ? base64_str[(int)output[3]] : base64_pad;
363 n+=3;
364 }
365 outbuf[m] = 0; // 0-termination!
366 return outbuf;
367}
368
369static void plist_node_print_to_stream(plist_t node, int* indent_level, FILE* stream);
370
371static void plist_array_print_to_stream(plist_t node, int* indent_level, FILE* stream)
372{
373 /* iterate over items */
374 int i, count;
375 plist_t subnode = NULL;
376
377 count = plist_array_get_size(node);
378
379 for (i = 0; i < count; i++) {
380 subnode = plist_array_get_item(node, i);
381 fprintf(stream, "%*s", *indent_level, "");
382 fprintf(stream, "%d: ", i);
383 plist_node_print_to_stream(subnode, indent_level, stream);
384 }
385}
386
387static void plist_dict_print_to_stream(plist_t node, int* indent_level, FILE* stream)
388{
389 /* iterate over key/value pairs */
390 plist_dict_iter it = NULL;
391
392 char* key = NULL;
393 plist_t subnode = NULL;
394 plist_dict_new_iter(node, &it);
395 plist_dict_next_item(node, it, &key, &subnode);
396 while (subnode)
397 {
398 fprintf(stream, "%*s", *indent_level, "");
399 fprintf(stream, "%s", key);
400 if (plist_get_node_type(subnode) == PLIST_ARRAY)
401 fprintf(stream, "[%d]: ", plist_array_get_size(subnode));
402 else
403 fprintf(stream, ": ");
404 free(key);
405 key = NULL;
406 plist_node_print_to_stream(subnode, indent_level, stream);
407 plist_dict_next_item(node, it, &key, &subnode);
408 }
409 free(it);
410}
411
412static void plist_node_print_to_stream(plist_t node, int* indent_level, FILE* stream)
413{
414 char *s = NULL;
415 char *data = NULL;
416 double d;
417 uint8_t b;
418 uint64_t u = 0;
419 struct timeval tv = { 0, 0 };
420
421 plist_type t;
422
423 if (!node)
424 return;
425
426 t = plist_get_node_type(node);
427
428 switch (t) {
429 case PLIST_BOOLEAN:
430 plist_get_bool_val(node, &b);
431 fprintf(stream, "%s\n", (b ? "true" : "false"));
432 break;
433
434 case PLIST_UINT:
435 plist_get_uint_val(node, &u);
436 fprintf(stream, "%"PRIu64"\n", u);
437 break;
438
439 case PLIST_REAL:
440 plist_get_real_val(node, &d);
441 fprintf(stream, "%f\n", d);
442 break;
443
444 case PLIST_STRING:
445 plist_get_string_val(node, &s);
446 fprintf(stream, "%s\n", s);
447 free(s);
448 break;
449
450 case PLIST_KEY:
451 plist_get_key_val(node, &s);
452 fprintf(stream, "%s: ", s);
453 free(s);
454 break;
455
456 case PLIST_DATA:
457 plist_get_data_val(node, &data, &u);
458 if (u > 0) {
459 s = base64encode((unsigned char*)data, u);
460 free(data);
461 if (s) {
462 fprintf(stream, "%s\n", s);
463 free(s);
464 } else {
465 fprintf(stream, "\n");
466 }
467 } else {
468 fprintf(stream, "\n");
469 }
470 break;
471
472 case PLIST_DATE:
473 plist_get_date_val(node, (int32_t*)&tv.tv_sec, (int32_t*)&tv.tv_usec);
474 {
475 time_t ti = (time_t)tv.tv_sec + MAC_EPOCH;
476 struct tm *btime = localtime(&ti);
477 if (btime) {
478 s = (char*)malloc(24);
479 memset(s, 0, 24);
480 if (strftime(s, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) {
481 free (s);
482 s = NULL;
483 }
484 }
485 }
486 if (s) {
487 fprintf(stream, "%s\n", s);
488 free(s);
489 } else {
490 fprintf(stream, "\n");
491 }
492 break;
493
494 case PLIST_ARRAY:
495 fprintf(stream, "\n");
496 (*indent_level)++;
497 plist_array_print_to_stream(node, indent_level, stream);
498 (*indent_level)--;
499 break;
500
501 case PLIST_DICT:
502 fprintf(stream, "\n");
503 (*indent_level)++;
504 plist_dict_print_to_stream(node, indent_level, stream);
505 (*indent_level)--;
506 break;
507
508 default:
509 break;
510 }
511}
512
513void plist_print_to_stream(plist_t plist, FILE* stream)
514{
515 int indent = 0;
516
517 if (!plist || !stream)
518 return;
519
520 switch (plist_get_node_type(plist)) {
521 case PLIST_DICT:
522 plist_dict_print_to_stream(plist, &indent, stream);
523 break;
524 case PLIST_ARRAY:
525 plist_array_print_to_stream(plist, &indent, stream);
526 break;
527 default:
528 plist_node_print_to_stream(plist, &indent, stream);
529 }
530}
diff --git a/common/utils.h b/common/utils.h
deleted file mode 100644
index 2c3acec..0000000
--- a/common/utils.h
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * utils.h
3 * Miscellaneous utilities for string manipulation,
4 * file I/O and plist helper.
5 *
6 * Copyright (c) 2014-2019 Nikias Bassen, All Rights Reserved.
7 * Copyright (c) 2013-2014 Martin Szulecki, All Rights Reserved.
8 * Copyright (c) 2013 Federico Mena Quintero
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#ifndef __UTILS_H
26#define __UTILS_H
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32#ifdef WIN32
33#include <windows.h>
34#endif
35
36#include <stdio.h>
37#include <plist/plist.h>
38
39#define MAC_EPOCH 978307200
40
41#ifndef HAVE_STPCPY
42char *stpcpy(char *s1, const char *s2);
43#endif
44char *string_concat(const char *str, ...);
45char *string_append(char *str, ...);
46char *string_build_path(const char *elem, ...);
47char *string_format_size(uint64_t size);
48char *string_toupper(char *str);
49char *generate_uuid(void);
50
51void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length);
52void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length);
53
54enum plist_format_t {
55 PLIST_FORMAT_XML,
56 PLIST_FORMAT_BINARY
57};
58
59int plist_read_from_filename(plist_t *plist, const char *filename);
60int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format);
61
62void plist_print_to_stream(plist_t plist, FILE* stream);
63
64#endif
diff --git a/configure.ac b/configure.ac
index a95bc69..ed9270c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,10 +20,12 @@ LIBIMOBILEDEVICE_SO_VERSION=6:0:0
20dnl Minimum package versions 20dnl Minimum package versions
21LIBUSBMUXD_VERSION=2.0.2 21LIBUSBMUXD_VERSION=2.0.2
22LIBPLIST_VERSION=2.2.0 22LIBPLIST_VERSION=2.2.0
23LIMD_GLUE_VERSION=1.0.0
23 24
24AC_SUBST(LIBIMOBILEDEVICE_SO_VERSION) 25AC_SUBST(LIBIMOBILEDEVICE_SO_VERSION)
25AC_SUBST(LIBUSBMUXD_VERSION) 26AC_SUBST(LIBUSBMUXD_VERSION)
26AC_SUBST(LIBPLIST_VERSION) 27AC_SUBST(LIBPLIST_VERSION)
28AC_SUBST(LIMD_GLUE_VERSION)
27 29
28# Checks for programs. 30# Checks for programs.
29AC_PROG_CC 31AC_PROG_CC
@@ -34,6 +36,7 @@ LT_INIT
34# Checks for libraries. 36# Checks for libraries.
35PKG_CHECK_MODULES(libusbmuxd, libusbmuxd-2.0 >= $LIBUSBMUXD_VERSION) 37PKG_CHECK_MODULES(libusbmuxd, libusbmuxd-2.0 >= $LIBUSBMUXD_VERSION)
36PKG_CHECK_MODULES(libplist, libplist-2.0 >= $LIBPLIST_VERSION) 38PKG_CHECK_MODULES(libplist, libplist-2.0 >= $LIBPLIST_VERSION)
39PKG_CHECK_MODULES(limd_glue, libimobiledevice-glue-1.0 >= $LIMD_GLUE_VERSION)
37 40
38# Checks for header files. 41# Checks for header files.
39AC_CHECK_HEADERS([stdint.h stdlib.h string.h gcrypt.h]) 42AC_CHECK_HEADERS([stdint.h stdlib.h string.h gcrypt.h])
diff --git a/src/Makefile.am b/src/Makefile.am
index 96fe963..183a745 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,6 +6,7 @@ AM_CFLAGS = \
6 $(GLOBAL_CFLAGS) \ 6 $(GLOBAL_CFLAGS) \
7 $(libusbmuxd_CFLAGS) \ 7 $(libusbmuxd_CFLAGS) \
8 $(libplist_CFLAGS) \ 8 $(libplist_CFLAGS) \
9 $(limd_glue_CFLAGS) \
9 $(ssl_lib_CFLAGS) \ 10 $(ssl_lib_CFLAGS) \
10 $(LFS_CFLAGS) \ 11 $(LFS_CFLAGS) \
11 $(PTHREAD_CFLAGS) 12 $(PTHREAD_CFLAGS)
@@ -13,6 +14,7 @@ AM_CFLAGS = \
13AM_LDFLAGS = \ 14AM_LDFLAGS = \
14 $(libusbmuxd_LIBS) \ 15 $(libusbmuxd_LIBS) \
15 $(libplist_LIBS) \ 16 $(libplist_LIBS) \
17 $(limd_glue_LIBS) \
16 $(ssl_lib_LIBS) \ 18 $(ssl_lib_LIBS) \
17 $(PTHREAD_LIBS) 19 $(PTHREAD_LIBS)
18 20
diff --git a/src/afc.h b/src/afc.h
index 3e4ef67..6bfdf56 100644
--- a/src/afc.h
+++ b/src/afc.h
@@ -28,7 +28,7 @@
28#include "libimobiledevice/afc.h" 28#include "libimobiledevice/afc.h"
29#include "service.h" 29#include "service.h"
30#include "endianness.h" 30#include "endianness.h"
31#include "common/thread.h" 31#include <libimobiledevice-glue/thread.h>
32 32
33#define AFC_MAGIC "CFA6LPAA" 33#define AFC_MAGIC "CFA6LPAA"
34#define AFC_MAGIC_LEN (8) 34#define AFC_MAGIC_LEN (8)
diff --git a/src/companion_proxy.c b/src/companion_proxy.c
index f09b416..92bc7f1 100644
--- a/src/companion_proxy.c
+++ b/src/companion_proxy.c
@@ -29,7 +29,6 @@
29#include "companion_proxy.h" 29#include "companion_proxy.h"
30#include "lockdown.h" 30#include "lockdown.h"
31#include "common/debug.h" 31#include "common/debug.h"
32#include "common/thread.h"
33 32
34/** 33/**
35 * Convert a property_list_service_error_t value to a companion_proxy_error_t value. 34 * Convert a property_list_service_error_t value to a companion_proxy_error_t value.
diff --git a/src/companion_proxy.h b/src/companion_proxy.h
index 0314b67..0226640 100644
--- a/src/companion_proxy.h
+++ b/src/companion_proxy.h
@@ -24,7 +24,7 @@
24 24
25#include "libimobiledevice/companion_proxy.h" 25#include "libimobiledevice/companion_proxy.h"
26#include "property_list_service.h" 26#include "property_list_service.h"
27#include "common/thread.h" 27#include <libimobiledevice-glue/thread.h>
28 28
29struct companion_proxy_client_private { 29struct companion_proxy_client_private {
30 property_list_service_client_t parent; 30 property_list_service_client_t parent;
diff --git a/src/debugserver.c b/src/debugserver.c
index 1774087..b6a8b62 100644
--- a/src/debugserver.c
+++ b/src/debugserver.c
@@ -29,10 +29,11 @@
29#define __USE_GNU 1 29#define __USE_GNU 1
30#include <stdio.h> 30#include <stdio.h>
31 31
32#include <libimobiledevice-glue/utils.h>
33
32#include "debugserver.h" 34#include "debugserver.h"
33#include "lockdown.h" 35#include "lockdown.h"
34#include "common/debug.h" 36#include "common/debug.h"
35#include "common/utils.h"
36#include "asprintf.h" 37#include "asprintf.h"
37 38
38/** 39/**
diff --git a/src/idevice.c b/src/idevice.c
index 869ecac..4545bfa 100644
--- a/src/idevice.c
+++ b/src/idevice.c
@@ -48,10 +48,11 @@
48#error No supported TLS/SSL library enabled 48#error No supported TLS/SSL library enabled
49#endif 49#endif
50 50
51#include <libimobiledevice-glue/socket.h>
52#include <libimobiledevice-glue/thread.h>
53
51#include "idevice.h" 54#include "idevice.h"
52#include "common/userpref.h" 55#include "common/userpref.h"
53#include "common/socket.h"
54#include "common/thread.h"
55#include "common/debug.h" 56#include "common/debug.h"
56 57
57#ifdef WIN32 58#ifdef WIN32
diff --git a/src/installation_proxy.h b/src/installation_proxy.h
index 66dd5d0..033bdef 100644
--- a/src/installation_proxy.h
+++ b/src/installation_proxy.h
@@ -25,7 +25,7 @@
25 25
26#include "libimobiledevice/installation_proxy.h" 26#include "libimobiledevice/installation_proxy.h"
27#include "property_list_service.h" 27#include "property_list_service.h"
28#include "common/thread.h" 28#include <libimobiledevice-glue/thread.h>
29 29
30struct instproxy_client_private { 30struct instproxy_client_private {
31 property_list_service_client_t parent; 31 property_list_service_client_t parent;
diff --git a/src/lockdown.c b/src/lockdown.c
index 8fc2c49..70db834 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -34,13 +34,13 @@
34#include <ctype.h> 34#include <ctype.h>
35#include <unistd.h> 35#include <unistd.h>
36#include <plist/plist.h> 36#include <plist/plist.h>
37#include <libimobiledevice-glue/utils.h>
37 38
38#include "property_list_service.h" 39#include "property_list_service.h"
39#include "lockdown.h" 40#include "lockdown.h"
40#include "idevice.h" 41#include "idevice.h"
41#include "common/debug.h" 42#include "common/debug.h"
42#include "common/userpref.h" 43#include "common/userpref.h"
43#include "common/utils.h"
44#include "asprintf.h" 44#include "asprintf.h"
45 45
46#ifdef WIN32 46#ifdef WIN32
diff --git a/src/mobile_image_mounter.h b/src/mobile_image_mounter.h
index e9754e4..55c9cf2 100644
--- a/src/mobile_image_mounter.h
+++ b/src/mobile_image_mounter.h
@@ -24,7 +24,7 @@
24 24
25#include "libimobiledevice/mobile_image_mounter.h" 25#include "libimobiledevice/mobile_image_mounter.h"
26#include "property_list_service.h" 26#include "property_list_service.h"
27#include "common/thread.h" 27#include <libimobiledevice-glue/thread.h>
28 28
29struct mobile_image_mounter_client_private { 29struct mobile_image_mounter_client_private {
30 property_list_service_client_t parent; 30 property_list_service_client_t parent;
diff --git a/src/notification_proxy.h b/src/notification_proxy.h
index f641e25..ea85149 100644
--- a/src/notification_proxy.h
+++ b/src/notification_proxy.h
@@ -24,7 +24,7 @@
24 24
25#include "libimobiledevice/notification_proxy.h" 25#include "libimobiledevice/notification_proxy.h"
26#include "property_list_service.h" 26#include "property_list_service.h"
27#include "common/thread.h" 27#include <libimobiledevice-glue/thread.h>
28 28
29struct np_client_private { 29struct np_client_private {
30 property_list_service_client_t parent; 30 property_list_service_client_t parent;
diff --git a/src/preboard.h b/src/preboard.h
index c5143a9..61263fc 100644
--- a/src/preboard.h
+++ b/src/preboard.h
@@ -24,7 +24,7 @@
24 24
25#include "libimobiledevice/preboard.h" 25#include "libimobiledevice/preboard.h"
26#include "property_list_service.h" 26#include "property_list_service.h"
27#include "common/thread.h" 27#include <libimobiledevice-glue/thread.h>
28 28
29struct preboard_client_private { 29struct preboard_client_private {
30 property_list_service_client_t parent; 30 property_list_service_client_t parent;
diff --git a/src/sbservices.h b/src/sbservices.h
index 6c047ce..39d822c 100644
--- a/src/sbservices.h
+++ b/src/sbservices.h
@@ -24,7 +24,7 @@
24 24
25#include "libimobiledevice/sbservices.h" 25#include "libimobiledevice/sbservices.h"
26#include "property_list_service.h" 26#include "property_list_service.h"
27#include "common/thread.h" 27#include <libimobiledevice-glue/thread.h>
28 28
29struct sbservices_client_private { 29struct sbservices_client_private {
30 property_list_service_client_t parent; 30 property_list_service_client_t parent;
diff --git a/src/syslog_relay.h b/src/syslog_relay.h
index 3e48fa4..86d798e 100644
--- a/src/syslog_relay.h
+++ b/src/syslog_relay.h
@@ -24,7 +24,7 @@
24 24
25#include "libimobiledevice/syslog_relay.h" 25#include "libimobiledevice/syslog_relay.h"
26#include "service.h" 26#include "service.h"
27#include "common/thread.h" 27#include <libimobiledevice-glue/thread.h>
28 28
29struct syslog_relay_client_private { 29struct syslog_relay_client_private {
30 service_client_t parent; 30 service_client_t parent;
diff --git a/tools/Makefile.am b/tools/Makefile.am
index b78f3f2..354cf1c 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -31,9 +31,9 @@ bin_PROGRAMS = \
31 idevicesetlocation 31 idevicesetlocation
32 32
33ideviceinfo_SOURCES = ideviceinfo.c 33ideviceinfo_SOURCES = ideviceinfo.c
34ideviceinfo_CFLAGS = $(AM_CFLAGS) 34ideviceinfo_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
35ideviceinfo_LDFLAGS = $(AM_LDFLAGS) 35ideviceinfo_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
36ideviceinfo_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 36ideviceinfo_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
37 37
38idevicename_SOURCES = idevicename.c 38idevicename_SOURCES = idevicename.c
39idevicename_CFLAGS = $(AM_CFLAGS) 39idevicename_CFLAGS = $(AM_CFLAGS)
@@ -41,13 +41,13 @@ idevicename_LDFLAGS = $(AM_LDFLAGS)
41idevicename_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 41idevicename_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
42 42
43idevicepair_SOURCES = idevicepair.c 43idevicepair_SOURCES = idevicepair.c
44idevicepair_CFLAGS = -I$(top_srcdir) $(AM_CFLAGS) $(ssl_lib_CFLAGS) 44idevicepair_CFLAGS = $(AM_CFLAGS) $(ssl_lib_CFLAGS)
45idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS) $(ssl_lib_LIBS) 45idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS) $(ssl_lib_LIBS)
46idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 46idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la
47 47
48idevicesyslog_SOURCES = idevicesyslog.c 48idevicesyslog_SOURCES = idevicesyslog.c
49idevicesyslog_CFLAGS = $(AM_CFLAGS) 49idevicesyslog_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
50idevicesyslog_LDFLAGS = $(AM_LDFLAGS) 50idevicesyslog_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
51idevicesyslog_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 51idevicesyslog_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
52 52
53idevice_id_SOURCES = idevice_id.c 53idevice_id_SOURCES = idevice_id.c
@@ -56,19 +56,19 @@ idevice_id_LDFLAGS = $(AM_LDFLAGS)
56idevice_id_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 56idevice_id_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
57 57
58idevicebackup_SOURCES = idevicebackup.c 58idevicebackup_SOURCES = idevicebackup.c
59idevicebackup_CFLAGS = $(AM_CFLAGS) $(ssl_lib_CFLAGS) 59idevicebackup_CFLAGS = $(AM_CFLAGS) $(ssl_lib_CFLAGS) $(limd_glue_CFLAGS)
60idevicebackup_LDFLAGS = $(AM_LDFLAGS) $(ssl_lib_LIBS) 60idevicebackup_LDFLAGS = $(AM_LDFLAGS) $(ssl_lib_LIBS) $(limd_glue_LIBS)
61idevicebackup_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 61idevicebackup_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
62 62
63idevicebackup2_SOURCES = idevicebackup2.c 63idevicebackup2_SOURCES = idevicebackup2.c
64idevicebackup2_CFLAGS = $(AM_CFLAGS) 64idevicebackup2_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
65idevicebackup2_LDFLAGS = $(AM_LDFLAGS) 65idevicebackup2_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
66idevicebackup2_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 66idevicebackup2_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
67 67
68ideviceimagemounter_SOURCES = ideviceimagemounter.c 68ideviceimagemounter_SOURCES = ideviceimagemounter.c
69ideviceimagemounter_CFLAGS = $(AM_CFLAGS) 69ideviceimagemounter_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
70ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) 70ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
71ideviceimagemounter_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 71ideviceimagemounter_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
72 72
73idevicescreenshot_SOURCES = idevicescreenshot.c 73idevicescreenshot_SOURCES = idevicescreenshot.c
74idevicescreenshot_CFLAGS = $(AM_CFLAGS) 74idevicescreenshot_CFLAGS = $(AM_CFLAGS)
@@ -86,14 +86,14 @@ idevicedate_LDFLAGS = $(AM_LDFLAGS)
86idevicedate_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 86idevicedate_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
87 87
88ideviceprovision_SOURCES = ideviceprovision.c 88ideviceprovision_SOURCES = ideviceprovision.c
89ideviceprovision_CFLAGS = $(AM_CFLAGS) 89ideviceprovision_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
90ideviceprovision_LDFLAGS = $(AM_LDFLAGS) 90ideviceprovision_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
91ideviceprovision_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 91ideviceprovision_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
92 92
93idevicedebugserverproxy_SOURCES = idevicedebugserverproxy.c 93idevicedebugserverproxy_SOURCES = idevicedebugserverproxy.c
94idevicedebugserverproxy_CFLAGS = -I$(top_srcdir) $(AM_CFLAGS) 94idevicedebugserverproxy_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
95idevicedebugserverproxy_LDFLAGS = $(AM_LDFLAGS) 95idevicedebugserverproxy_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
96idevicedebugserverproxy_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 96idevicedebugserverproxy_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
97 97
98idevicediagnostics_SOURCES = idevicediagnostics.c 98idevicediagnostics_SOURCES = idevicediagnostics.c
99idevicediagnostics_CFLAGS = $(AM_CFLAGS) 99idevicediagnostics_CFLAGS = $(AM_CFLAGS)
@@ -101,8 +101,8 @@ idevicediagnostics_LDFLAGS = $(AM_LDFLAGS)
101idevicediagnostics_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 101idevicediagnostics_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
102 102
103idevicedebug_SOURCES = idevicedebug.c 103idevicedebug_SOURCES = idevicedebug.c
104idevicedebug_CFLAGS = $(AM_CFLAGS) 104idevicedebug_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
105idevicedebug_LDFLAGS = $(AM_LDFLAGS) 105idevicedebug_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
106idevicedebug_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 106idevicedebug_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la
107 107
108idevicenotificationproxy_SOURCES = idevicenotificationproxy.c 108idevicenotificationproxy_SOURCES = idevicenotificationproxy.c
@@ -111,11 +111,11 @@ idevicenotificationproxy_LDFLAGS = $(AM_LDFLAGS)
111idevicenotificationproxy_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la 111idevicenotificationproxy_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
112 112
113idevicecrashreport_SOURCES = idevicecrashreport.c 113idevicecrashreport_SOURCES = idevicecrashreport.c
114idevicecrashreport_CFLAGS = -I$(top_srcdir) $(AM_CFLAGS) 114idevicecrashreport_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS)
115idevicecrashreport_LDFLAGS = $(AM_LDFLAGS) 115idevicecrashreport_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS)
116idevicecrashreport_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 116idevicecrashreport_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
117 117
118idevicesetlocation_SOURCES = idevicesetlocation.c 118idevicesetlocation_SOURCES = idevicesetlocation.c
119idevicesetlocation_CFLAGS = $(AM_CFLAGS) 119idevicesetlocation_CFLAGS = $(AM_CFLAGS)
120idevicesetlocation_LDFLAGS = $(AM_LDFLAGS) 120idevicesetlocation_LDFLAGS = $(AM_LDFLAGS)
121idevicesetlocation_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la 121idevicesetlocation_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la
diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c
index 8d0f74b..42f020d 100644
--- a/tools/idevicebackup.c
+++ b/tools/idevicebackup.c
@@ -55,7 +55,7 @@
55#include <libimobiledevice/mobilebackup.h> 55#include <libimobiledevice/mobilebackup.h>
56#include <libimobiledevice/notification_proxy.h> 56#include <libimobiledevice/notification_proxy.h>
57#include <libimobiledevice/afc.h> 57#include <libimobiledevice/afc.h>
58#include "common/utils.h" 58#include <libimobiledevice-glue/utils.h>
59 59
60#define MOBILEBACKUP_SERVICE_NAME "com.apple.mobilebackup" 60#define MOBILEBACKUP_SERVICE_NAME "com.apple.mobilebackup"
61#define NP_SERVICE_NAME "com.apple.mobile.notification_proxy" 61#define NP_SERVICE_NAME "com.apple.mobile.notification_proxy"
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c
index 6ed852f..7c8503e 100644
--- a/tools/idevicebackup2.c
+++ b/tools/idevicebackup2.c
@@ -45,7 +45,7 @@
45#include <libimobiledevice/installation_proxy.h> 45#include <libimobiledevice/installation_proxy.h>
46#include <libimobiledevice/sbservices.h> 46#include <libimobiledevice/sbservices.h>
47#include <libimobiledevice/diagnostics_relay.h> 47#include <libimobiledevice/diagnostics_relay.h>
48#include "common/utils.h" 48#include <libimobiledevice-glue/utils.h>
49 49
50#include <endianness.h> 50#include <endianness.h>
51 51
diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c
index 0a03c68..4d3b686 100644
--- a/tools/idevicecrashreport.c
+++ b/tools/idevicecrashreport.c
@@ -33,7 +33,7 @@
33#ifndef WIN32 33#ifndef WIN32
34#include <signal.h> 34#include <signal.h>
35#endif 35#endif
36#include "common/utils.h" 36#include <libimobiledevice-glue/utils.h>
37 37
38#include <libimobiledevice/libimobiledevice.h> 38#include <libimobiledevice/libimobiledevice.h>
39#include <libimobiledevice/lockdown.h> 39#include <libimobiledevice/lockdown.h>
diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c
index 15e8deb..b190f63 100644
--- a/tools/idevicedebugserverproxy.c
+++ b/tools/idevicedebugserverproxy.c
@@ -41,8 +41,8 @@
41#include <libimobiledevice/libimobiledevice.h> 41#include <libimobiledevice/libimobiledevice.h>
42#include <libimobiledevice/debugserver.h> 42#include <libimobiledevice/debugserver.h>
43 43
44#include "common/socket.h" 44#include <libimobiledevice-glue/socket.h>
45#include "common/thread.h" 45#include <libimobiledevice-glue/thread.h>
46 46
47#define info(...) fprintf(stdout, __VA_ARGS__); fflush(stdout) 47#define info(...) fprintf(stdout, __VA_ARGS__); fflush(stdout)
48#define debug(...) if(debug_mode) fprintf(stdout, __VA_ARGS__) 48#define debug(...) if(debug_mode) fprintf(stdout, __VA_ARGS__)
diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c
index 325a9e2..37c2154 100644
--- a/tools/ideviceimagemounter.c
+++ b/tools/ideviceimagemounter.c
@@ -46,7 +46,7 @@
46#include <libimobiledevice/notification_proxy.h> 46#include <libimobiledevice/notification_proxy.h>
47#include <libimobiledevice/mobile_image_mounter.h> 47#include <libimobiledevice/mobile_image_mounter.h>
48#include <asprintf.h> 48#include <asprintf.h>
49#include "common/utils.h" 49#include <libimobiledevice-glue/utils.h>
50 50
51static int list_mode = 0; 51static int list_mode = 0;
52static int use_network = 0; 52static int use_network = 0;
diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c
index 97ae03a..54ae1d2 100644
--- a/tools/ideviceinfo.c
+++ b/tools/ideviceinfo.c
@@ -37,7 +37,7 @@
37 37
38#include <libimobiledevice/libimobiledevice.h> 38#include <libimobiledevice/libimobiledevice.h>
39#include <libimobiledevice/lockdown.h> 39#include <libimobiledevice/lockdown.h>
40#include "common/utils.h" 40#include <libimobiledevice-glue/utils.h>
41 41
42#define FORMAT_KEY_VALUE 1 42#define FORMAT_KEY_VALUE 1
43#define FORMAT_XML 2 43#define FORMAT_XML 2
diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c
index c93a682..36c69b0 100644
--- a/tools/ideviceprovision.c
+++ b/tools/ideviceprovision.c
@@ -44,7 +44,7 @@
44#include <libimobiledevice/libimobiledevice.h> 44#include <libimobiledevice/libimobiledevice.h>
45#include <libimobiledevice/lockdown.h> 45#include <libimobiledevice/lockdown.h>
46#include <libimobiledevice/misagent.h> 46#include <libimobiledevice/misagent.h>
47#include "common/utils.h" 47#include <libimobiledevice-glue/utils.h>
48 48
49static void print_usage(int argc, char **argv) 49static void print_usage(int argc, char **argv)
50{ 50{
diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c
index d9b627f..4eb1605 100644
--- a/tools/idevicesyslog.c
+++ b/tools/idevicesyslog.c
@@ -41,10 +41,10 @@
41 41
42#include <libimobiledevice/libimobiledevice.h> 42#include <libimobiledevice/libimobiledevice.h>
43#include <libimobiledevice/syslog_relay.h> 43#include <libimobiledevice/syslog_relay.h>
44#include <libimobiledevice-glue/termcolors.h>
44 45
45static int quit_flag = 0; 46static int quit_flag = 0;
46static int exit_on_disconnect = 0; 47static int exit_on_disconnect = 0;
47static int use_colors = 0;
48static int show_device_name = 0; 48static int show_device_name = 0;
49 49
50static char* udid = NULL; 50static char* udid = NULL;
@@ -75,58 +75,6 @@ static char *line = NULL;
75static int line_buffer_size = 0; 75static int line_buffer_size = 0;
76static int lp = 0; 76static int lp = 0;
77 77
78#ifdef WIN32
79static WORD COLOR_RESET = 0;
80static HANDLE h_stdout = INVALID_HANDLE_VALUE;
81
82#define COLOR_NORMAL COLOR_RESET
83#define COLOR_DARK FOREGROUND_INTENSITY
84#define COLOR_RED FOREGROUND_RED |FOREGROUND_INTENSITY
85#define COLOR_DARK_RED FOREGROUND_RED
86#define COLOR_GREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY
87#define COLOR_DARK_GREEN FOREGROUND_GREEN
88#define COLOR_YELLOW FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
89#define COLOR_DARK_YELLOW FOREGROUND_GREEN | FOREGROUND_RED
90#define COLOR_BLUE FOREGROUND_BLUE | FOREGROUND_INTENSITY
91#define COLOR_DARK_BLUE FOREGROUND_BLUE
92#define COLOR_MAGENTA FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY
93#define COLOR_DARK_MAGENTA FOREGROUND_BLUE | FOREGROUND_RED
94#define COLOR_CYAN FOREGROUND_BLUE | FOREGROUND_GREEN
95#define COLOR_BRIGHT_CYAN FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
96#define COLOR_DARK_CYAN FOREGROUND_BLUE | FOREGROUND_GREEN
97#define COLOR_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
98#define COLOR_DARK_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
99
100static void TEXT_COLOR(WORD attr)
101{
102 if (use_colors) {
103 SetConsoleTextAttribute(h_stdout, attr);
104 }
105}
106#else
107
108#define COLOR_RESET "\e[m"
109#define COLOR_NORMAL "\e[0m"
110#define COLOR_DARK "\e[2m"
111#define COLOR_RED "\e[0;31m"
112#define COLOR_DARK_RED "\e[2;31m"
113#define COLOR_GREEN "\e[0;32m"
114#define COLOR_DARK_GREEN "\e[2;32m"
115#define COLOR_YELLOW "\e[0;33m"
116#define COLOR_DARK_YELLOW "\e[2;33m"
117#define COLOR_BLUE "\e[0;34m"
118#define COLOR_DARK_BLUE "\e[2;34m"
119#define COLOR_MAGENTA "\e[0;35m"
120#define COLOR_DARK_MAGENTA "\e[2;35m"
121#define COLOR_CYAN "\e[0;36m"
122#define COLOR_BRIGHT_CYAN "\e[1;36m"
123#define COLOR_DARK_CYAN "\e[2;36m"
124#define COLOR_WHITE "\e[1;37m"
125#define COLOR_DARK_WHITE "\e[0;37m"
126
127#define TEXT_COLOR(x) if (use_colors) { fwrite(x, 1, sizeof(x)-1, stdout); }
128#endif
129
130static void add_filter(const char* filterstr) 78static void add_filter(const char* filterstr)
131{ 79{
132 int filter_len = strlen(filterstr); 80 int filter_len = strlen(filterstr);
@@ -201,7 +149,7 @@ static void syslog_callback(char c, void *user_data)
201 do { 149 do {
202 if (lp < 16) { 150 if (lp < 16) {
203 shall_print = 1; 151 shall_print = 1;
204 TEXT_COLOR(COLOR_WHITE); 152 cprintf(COLOR_WHITE);
205 break; 153 break;
206 } else if (line[3] == ' ' && line[6] == ' ' && line[15] == ' ') { 154 } else if (line[3] == ' ' && line[6] == ' ' && line[15] == ' ') {
207 char* end = &line[lp]; 155 char* end = &line[lp];
@@ -331,11 +279,7 @@ static void syslog_callback(char c, void *user_data)
331 /* log level */ 279 /* log level */
332 char* level_start = p; 280 char* level_start = p;
333 char* level_end = p; 281 char* level_end = p;
334#ifdef WIN32
335 WORD level_color = COLOR_NORMAL;
336#else
337 const char* level_color = NULL; 282 const char* level_color = NULL;
338#endif
339 if (!strncmp(p, "<Notice>:", 9)) { 283 if (!strncmp(p, "<Notice>:", 9)) {
340 level_end += 9; 284 level_end += 9;
341 level_color = COLOR_GREEN; 285 level_color = COLOR_GREEN;
@@ -353,24 +297,24 @@ static void syslog_callback(char c, void *user_data)
353 } 297 }
354 298
355 /* write date and time */ 299 /* write date and time */
356 TEXT_COLOR(COLOR_DARK_WHITE); 300 cprintf(COLOR_LIGHT_GRAY);
357 fwrite(line, 1, 16, stdout); 301 fwrite(line, 1, 16, stdout);
358 302
359 if (show_device_name) { 303 if (show_device_name) {
360 /* write device name */ 304 /* write device name */
361 TEXT_COLOR(COLOR_DARK_YELLOW); 305 cprintf(COLOR_DARK_YELLOW);
362 fwrite(device_name_start, 1, device_name_end-device_name_start+1, stdout); 306 fwrite(device_name_start, 1, device_name_end-device_name_start+1, stdout);
363 TEXT_COLOR(COLOR_RESET); 307 cprintf(COLOR_RESET);
364 } 308 }
365 309
366 /* write process name */ 310 /* write process name */
367 TEXT_COLOR(COLOR_BRIGHT_CYAN); 311 cprintf(COLOR_BRIGHT_CYAN);
368 fwrite(process_name_start, 1, process_name_end-process_name_start, stdout); 312 fwrite(process_name_start, 1, process_name_end-process_name_start, stdout);
369 TEXT_COLOR(COLOR_CYAN); 313 cprintf(COLOR_CYAN);
370 fwrite(process_name_end, 1, proc_name_end-process_name_end+1, stdout); 314 fwrite(process_name_end, 1, proc_name_end-process_name_end+1, stdout);
371 315
372 /* write log level */ 316 /* write log level */
373 TEXT_COLOR(level_color); 317 cprintf(level_color);
374 if (level_end > level_start) { 318 if (level_end > level_start) {
375 fwrite(level_start, 1, level_end-level_start, stdout); 319 fwrite(level_start, 1, level_end-level_start, stdout);
376 p = level_end; 320 p = level_end;
@@ -379,17 +323,17 @@ static void syslog_callback(char c, void *user_data)
379 lp -= p - linep; 323 lp -= p - linep;
380 linep = p; 324 linep = p;
381 325
382 TEXT_COLOR(COLOR_WHITE); 326 cprintf(COLOR_WHITE);
383 327
384 } else { 328 } else {
385 shall_print = 1; 329 shall_print = 1;
386 TEXT_COLOR(COLOR_WHITE); 330 cprintf(COLOR_WHITE);
387 } 331 }
388 } while (0); 332 } while (0);
389 333
390 if ((num_msg_filters == 0 && num_proc_filters == 0 && num_pid_filters == 0 && num_trigger_filters == 0 && num_untrigger_filters == 0) || shall_print) { 334 if ((num_msg_filters == 0 && num_proc_filters == 0 && num_pid_filters == 0 && num_trigger_filters == 0 && num_untrigger_filters == 0) || shall_print) {
391 fwrite(linep, 1, lp, stdout); 335 fwrite(linep, 1, lp, stdout);
392 TEXT_COLOR(COLOR_RESET); 336 cprintf(COLOR_RESET);
393 fflush(stdout); 337 fflush(stdout);
394 if (trigger_off) { 338 if (trigger_off) {
395 triggered = 0; 339 triggered = 0;
@@ -560,14 +504,6 @@ static void print_usage(int argc, char **argv, int is_error)
560 504
561int main(int argc, char *argv[]) 505int main(int argc, char *argv[])
562{ 506{
563#ifdef WIN32
564 CONSOLE_SCREEN_BUFFER_INFO csbi;
565 h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
566 if (GetConsoleScreenBufferInfo(h_stdout, &csbi)) {
567 COLOR_RESET = csbi.wAttributes;
568 }
569#endif
570 int no_colors = 0;
571 int include_filter = 0; 507 int include_filter = 0;
572 int exclude_filter = 0; 508 int exclude_filter = 0;
573 int include_kernel = 0; 509 int include_kernel = 0;
@@ -700,7 +636,7 @@ int main(int argc, char *argv[])
700 return 0; 636 return 0;
701 } 637 }
702 case 2: 638 case 2:
703 no_colors = 1; 639 term_colors_set_enabled(0);
704 break; 640 break;
705 case 'v': 641 case 'v':
706 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION); 642 printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
@@ -756,10 +692,6 @@ int main(int argc, char *argv[])
756 argc -= optind; 692 argc -= optind;
757 argv += optind; 693 argv += optind;
758 694
759 if (!no_colors && isatty(1)) {
760 use_colors = 1;
761 }
762
763 int num = 0; 695 int num = 0;
764 idevice_info_t *devices = NULL; 696 idevice_info_t *devices = NULL;
765 idevice_get_device_list_extended(&devices, &num); 697 idevice_get_device_list_extended(&devices, &num);