blob: 6237a1a42e67e3dd19ec3bd15ca67b9563cc931e [file] [log] [blame]
/*
* idevicesetlocation.c
* Simulate location on iOS device with mounted developer disk image
*
* Copyright (c) 2016-2020 Nikias Bassen, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define TOOL_NAME "idevicesetlocation"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libimobiledevice/service.h>
#include <endianness.h>
#define DT_SIMULATELOCATION_SERVICE "com.apple.dt.simulatelocation"
enum {
SET_LOCATION = 0,
RESET_LOCATION = 1
};
static void print_usage(int argc, char **argv, int is_error)
{
char *bname = strrchr(argv[0], '/');
bname = (bname) ? bname + 1 : argv[0];
fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] -- <LAT> <LONG>\n", bname);
fprintf(is_error ? stderr : stdout, " %s [OPTIONS] reset\n", bname);
fprintf(is_error ? stderr : stdout, "\n" \
"OPTIONS:\n" \
" -u, --udid UDID target specific device by UDID\n" \
" -n, --network connect to network device\n" \
" -d, --debug enable communication debugging\n" \
" -h, --help prints usage information\n" \
" -v, --version prints version information\n" \
"\n" \
"Homepage: <" PACKAGE_URL ">\n" \
"Bug Reports: <" PACKAGE_BUGREPORT ">\n"
);
}
int main(int argc, char **argv)
{
int c = 0;
const struct option longopts[] = {
{ "help", no_argument, NULL, 'h' },
{ "udid", required_argument, NULL, 'u' },
{ "debug", no_argument, NULL, 'd' },
{ "network", no_argument, NULL, 'n' },
{ "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0}
};
uint32_t mode = 0;
const char *udid = NULL;
int use_network = 0;
while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) {
switch (c) {
case 'd':
idevice_set_debug_level(1);
break;
case 'u':
if (!*optarg) {
fprintf(stderr, "ERROR: UDID must not be empty!\n");
print_usage(argc, argv, 1);
return 2;
}
udid = optarg;
break;
case 'n':
use_network = 1;
break;
case 'h':
print_usage(argc, argv, 0);
return 0;
case 'v':
printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION);
return 0;
default:
print_usage(argc, argv, 1);
return 2;
}
}
argc -= optind;
argv += optind;
if ((argc > 2) || (argc < 1)) {
print_usage(argc+optind, argv-optind, 1);
return -1;
}
if (argc == 2) {
mode = SET_LOCATION;
} else if (argc == 1) {
if (strcmp(argv[0], "reset") == 0) {
mode = RESET_LOCATION;
} else {
print_usage(argc+optind, argv-optind, 1);
return -1;
}
}
idevice_t device = NULL;
if (idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX) != IDEVICE_E_SUCCESS) {
if (udid) {
printf("ERROR: Device %s not found!\n", udid);
} else {
printf("ERROR: No device found!\n");
}
return -1;
}
lockdownd_client_t lockdown;
lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME);
lockdownd_service_descriptor_t svc = NULL;
lockdownd_error_t lerr = lockdownd_start_service(lockdown, DT_SIMULATELOCATION_SERVICE, &svc);
if (lerr != LOCKDOWN_E_SUCCESS) {
lockdownd_client_free(lockdown);
idevice_free(device);
printf("ERROR: Could not start the simulatelocation service: %s\nMake sure a developer disk image is mounted!\n", lockdownd_strerror(lerr));
return -1;
}
lockdownd_client_free(lockdown);
service_client_t service = NULL;
service_error_t serr = service_client_new(device, svc, &service);
lockdownd_service_descriptor_free(svc);
if (serr != SERVICE_E_SUCCESS) {
lockdownd_client_free(lockdown);
idevice_free(device);
printf("ERROR: Could not connect to simulatelocation service (%d)\n", serr);
return -1;
}
uint32_t l;
uint32_t s = 0;
l = htobe32(mode);
service_send(service, (const char*)&l, 4, &s);
if (mode == SET_LOCATION) {
int len = 4 + strlen(argv[0]) + 4 + strlen(argv[1]);
char *buf = malloc(len);
uint32_t latlen;
latlen = strlen(argv[0]);
l = htobe32(latlen);
memcpy(buf, &l, 4);
memcpy(buf+4, argv[0], latlen);
uint32_t longlen = strlen(argv[1]);
l = htobe32(longlen);
memcpy(buf+4+latlen, &l, 4);
memcpy(buf+4+latlen+4, argv[1], longlen);
s = 0;
service_send(service, buf, len, &s);
}
idevice_free(device);
return 0;
}