diff options
Diffstat (limited to 'tools/idevicesetlocation.c')
-rw-r--r-- | tools/idevicesetlocation.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/tools/idevicesetlocation.c b/tools/idevicesetlocation.c new file mode 100644 index 0000000..69fbaf5 --- /dev/null +++ b/tools/idevicesetlocation.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * idevicesetlocation.c | ||
3 | * Simulate location on iOS device with mounted developer disk image | ||
4 | * | ||
5 | * Copyright (c) 2016-2020 Nikias Bassen, All Rights Reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program 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 | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | */ | ||
21 | #ifdef HAVE_CONFIG_H | ||
22 | #include <config.h> | ||
23 | #endif | ||
24 | |||
25 | #define TOOL_NAME "idevicesetlocation" | ||
26 | |||
27 | #include <stdio.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <stdint.h> | ||
30 | #include <string.h> | ||
31 | #include <errno.h> | ||
32 | #include <getopt.h> | ||
33 | |||
34 | #include <libimobiledevice/libimobiledevice.h> | ||
35 | #include <libimobiledevice/lockdown.h> | ||
36 | #include <libimobiledevice/service.h> | ||
37 | |||
38 | #include <endianness.h> | ||
39 | |||
40 | #define DT_SIMULATELOCATION_SERVICE "com.apple.dt.simulatelocation" | ||
41 | |||
42 | enum { | ||
43 | SET_LOCATION = 0, | ||
44 | RESET_LOCATION = 1 | ||
45 | }; | ||
46 | |||
47 | static void print_usage(int argc, char **argv, int is_error) | ||
48 | { | ||
49 | char *bname = strrchr(argv[0], '/'); | ||
50 | bname = (bname) ? bname + 1 : argv[0]; | ||
51 | |||
52 | fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] -- <LAT> <LONG>\n", bname); | ||
53 | fprintf(is_error ? stderr : stdout, " %s [OPTIONS] reset\n", bname); | ||
54 | fprintf(is_error ? stderr : stdout, | ||
55 | "\n" | ||
56 | "OPTIONS:\n" | ||
57 | " -u, --udid UDID target specific device by UDID\n" | ||
58 | " -n, --network connect to network device\n" | ||
59 | " -d, --debug enable communication debugging\n" | ||
60 | " -h, --help prints usage information\n" | ||
61 | " -v, --version prints version information\n" | ||
62 | "\n" | ||
63 | "Homepage: <" PACKAGE_URL ">\n" | ||
64 | "Bug Reports: <" PACKAGE_BUGREPORT ">\n" | ||
65 | ); | ||
66 | } | ||
67 | |||
68 | int main(int argc, char **argv) | ||
69 | { | ||
70 | int c = 0; | ||
71 | const struct option longopts[] = { | ||
72 | { "help", no_argument, NULL, 'h' }, | ||
73 | { "udid", required_argument, NULL, 'u' }, | ||
74 | { "debug", no_argument, NULL, 'd' }, | ||
75 | { "network", no_argument, NULL, 'n' }, | ||
76 | { "version", no_argument, NULL, 'v' }, | ||
77 | { NULL, 0, NULL, 0} | ||
78 | }; | ||
79 | uint32_t mode = 0; | ||
80 | const char *udid = NULL; | ||
81 | int use_network = 0; | ||
82 | |||
83 | while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) { | ||
84 | switch (c) { | ||
85 | case 'd': | ||
86 | idevice_set_debug_level(1); | ||
87 | break; | ||
88 | case 'u': | ||
89 | if (!*optarg) { | ||
90 | fprintf(stderr, "ERROR: UDID must not be empty!\n"); | ||
91 | print_usage(argc, argv, 1); | ||
92 | return 2; | ||
93 | } | ||
94 | udid = optarg; | ||
95 | break; | ||
96 | case 'n': | ||
97 | use_network = 1; | ||
98 | break; | ||
99 | case 'h': | ||
100 | print_usage(argc, argv, 0); | ||
101 | return 0; | ||
102 | case 'v': | ||
103 | printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION); | ||
104 | return 0; | ||
105 | default: | ||
106 | print_usage(argc, argv, 1); | ||
107 | return 2; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | argc -= optind; | ||
112 | argv += optind; | ||
113 | |||
114 | if ((argc > 2) || (argc < 1)) { | ||
115 | print_usage(argc+optind, argv-optind, 1); | ||
116 | return -1; | ||
117 | } | ||
118 | |||
119 | if (argc == 2) { | ||
120 | mode = SET_LOCATION; | ||
121 | } else if (argc == 1) { | ||
122 | if (strcmp(argv[0], "reset") == 0) { | ||
123 | mode = RESET_LOCATION; | ||
124 | } else { | ||
125 | print_usage(argc+optind, argv-optind, 1); | ||
126 | return -1; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | idevice_t device = NULL; | ||
131 | |||
132 | if (idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX) != IDEVICE_E_SUCCESS) { | ||
133 | if (udid) { | ||
134 | printf("ERROR: Device %s not found!\n", udid); | ||
135 | } else { | ||
136 | printf("ERROR: No device found!\n"); | ||
137 | } | ||
138 | return -1; | ||
139 | } | ||
140 | |||
141 | lockdownd_client_t lockdown; | ||
142 | lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME); | ||
143 | |||
144 | lockdownd_service_descriptor_t svc = NULL; | ||
145 | lockdownd_error_t lerr = lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc); | ||
146 | if (lerr != LOCKDOWN_E_SUCCESS) { | ||
147 | lockdownd_client_free(lockdown); | ||
148 | idevice_free(device); | ||
149 | printf("ERROR: Could not start the simulatelocation service: %s\nMake sure a developer disk image is mounted!\n", lockdownd_strerror(lerr)); | ||
150 | return -1; | ||
151 | } | ||
152 | lockdownd_client_free(lockdown); | ||
153 | |||
154 | service_client_t service = NULL; | ||
155 | |||
156 | service_error_t serr = service_client_new(device, svc, &service); | ||
157 | |||
158 | lockdownd_service_descriptor_free(svc); | ||
159 | |||
160 | if (serr != SERVICE_E_SUCCESS) { | ||
161 | lockdownd_client_free(lockdown); | ||
162 | idevice_free(device); | ||
163 | printf("ERROR: Could not connect to simulatelocation service (%d)\n", serr); | ||
164 | return -1; | ||
165 | } | ||
166 | |||
167 | uint32_t l; | ||
168 | uint32_t s = 0; | ||
169 | |||
170 | l = htobe32(mode); | ||
171 | service_send(service, (const char*)&l, 4, &s); | ||
172 | if (mode == SET_LOCATION) { | ||
173 | int len = 4 + strlen(argv[0]) + 4 + strlen(argv[1]); | ||
174 | char *buf = malloc(len); | ||
175 | uint32_t latlen; | ||
176 | latlen = strlen(argv[0]); | ||
177 | l = htobe32(latlen); | ||
178 | memcpy(buf, &l, 4); | ||
179 | memcpy(buf+4, argv[0], latlen); | ||
180 | uint32_t longlen = strlen(argv[1]); | ||
181 | l = htobe32(longlen); | ||
182 | memcpy(buf+4+latlen, &l, 4); | ||
183 | memcpy(buf+4+latlen+4, argv[1], longlen); | ||
184 | |||
185 | s = 0; | ||
186 | service_send(service, buf, len, &s); | ||
187 | } | ||
188 | |||
189 | idevice_free(device); | ||
190 | |||
191 | return 0; | ||
192 | } | ||