summaryrefslogtreecommitdiffstats
path: root/src/main.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2021-01-10 03:25:02 +0100
committerGravatar Nikias Bassen2021-01-10 03:25:02 +0100
commit6b3e64140419013834589dfcff25cbf9af1b6168 (patch)
tree0f8f2ef2e1e6b9db2c9ad3788fe0b80478b01af2 /src/main.c
parentecb81751f14af6699aef2ea03d54ec08401a40d5 (diff)
downloadusbmuxd-6b3e64140419013834589dfcff25cbf9af1b6168.tar.gz
usbmuxd-6b3e64140419013834589dfcff25cbf9af1b6168.tar.bz2
Allow specifying a custom listen address:port or unix socket
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c187
1 files changed, 167 insertions, 20 deletions
diff --git a/src/main.c b/src/main.c
index 28ca65a..a82cb0c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * main.c 2 * main.c
3 * 3 *
4 * Copyright (C) 2009-2019 Nikias Bassen <nikias@gmx.li> 4 * Copyright (C) 2009-2021 Nikias Bassen <nikias@gmx.li>
5 * Copyright (C) 2013-2014 Martin Szulecki <m.szulecki@libimobiledevice.org> 5 * Copyright (C) 2013-2014 Martin Szulecki <m.szulecki@libimobiledevice.org>
6 * Copyright (C) 2009 Hector Martin <hector@marcansoft.com> 6 * Copyright (C) 2009 Hector Martin <hector@marcansoft.com>
7 * Copyright (C) 2009 Paul Sladen <libiphone@paul.sladen.org> 7 * Copyright (C) 2009 Paul Sladen <libiphone@paul.sladen.org>
@@ -36,6 +36,9 @@
36#include <unistd.h> 36#include <unistd.h>
37#include <sys/socket.h> 37#include <sys/socket.h>
38#include <sys/un.h> 38#include <sys/un.h>
39#include <netinet/in.h>
40#include <netdb.h>
41#include <arpa/inet.h>
39#include <sys/stat.h> 42#include <sys/stat.h>
40#include <sys/types.h> 43#include <sys/types.h>
41#include <sys/resource.h> 44#include <sys/resource.h>
@@ -69,22 +72,162 @@ static int opt_enable_exit = 0;
69static int opt_exit = 0; 72static int opt_exit = 0;
70static int exit_signal = 0; 73static int exit_signal = 0;
71static int daemon_pipe; 74static int daemon_pipe;
75static const char *listen_addr = NULL;
72 76
73static int report_to_parent = 0; 77static int report_to_parent = 0;
74 78
75static int create_socket(void) { 79static int create_socket(void)
76 struct sockaddr_un bind_addr; 80{
77 int listenfd; 81 int listenfd;
82 const char* socket_addr = socket_path;
83 const char* tcp_port;
84 char listen_addr_str[256];
85
86 if (listen_addr) {
87 socket_addr = listen_addr;
88 }
89 tcp_port = strrchr(socket_addr, ':');
90 if (tcp_port) {
91 tcp_port++;
92 size_t nlen = tcp_port - socket_addr;
93 char* hostname = malloc(nlen);
94 struct addrinfo hints;
95 struct addrinfo *result, *rp;
96 int yes = 1;
97 int res;
98
99 strncpy(hostname, socket_addr, nlen-1);
100 hostname[nlen-1] = '\0';
101
102 memset(&hints, '\0', sizeof(struct addrinfo));
103 hints.ai_family = AF_UNSPEC;
104 hints.ai_socktype = SOCK_STREAM;
105 hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
106 hints.ai_protocol = IPPROTO_TCP;
107
108 res = getaddrinfo(hostname, tcp_port, &hints, &result);
109 free(hostname);
110 if (res != 0) {
111 usbmuxd_log(LL_FATAL, "%s: getaddrinfo() failed: %s\n", __func__, gai_strerror(res));
112 return -1;
113 }
78 114
79 if(unlink(socket_path) == -1 && errno != ENOENT) { 115 for (rp = result; rp != NULL; rp = rp->ai_next) {
80 usbmuxd_log(LL_FATAL, "unlink(%s) failed: %s", socket_path, strerror(errno)); 116 listenfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
81 return -1; 117 if (listenfd == -1) {
82 } 118 listenfd = -1;
119 continue;
120 }
83 121
84 listenfd = socket(AF_UNIX, SOCK_STREAM, 0); 122 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
85 if (listenfd == -1) { 123 usbmuxd_log(LL_ERROR, "%s: setsockopt(): %s", __func__, strerror(errno));
86 usbmuxd_log(LL_FATAL, "socket() failed: %s", strerror(errno)); 124 close(listenfd);
87 return -1; 125 listenfd = -1;
126 continue;
127 }
128
129#ifdef SO_NOSIGPIPE
130 if (setsockopt(listenfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
131 usbmuxd_log(LL_ERROR, "%s: setsockopt(): %s", __func__, strerror(errno));
132 close(listenfd);
133 listenfd = -1;
134 continue;
135 }
136#endif
137
138#if defined(AF_INET6) && defined(IPV6_V6ONLY)
139 if (rp->ai_family == AF_INET6) {
140 if (setsockopt(listenfd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&yes, sizeof(int)) == -1) {
141 usbmuxd_log(LL_ERROR, "%s: setsockopt() IPV6_V6ONLY: %s", __func__, strerror(errno));
142 }
143 }
144#endif
145
146 if (bind(listenfd, rp->ai_addr, rp->ai_addrlen) < 0) {
147 usbmuxd_log(LL_FATAL, "%s: bind() failed: %s", __func__, strerror(errno));
148 close(listenfd);
149 listenfd = -1;
150 continue;
151 }
152
153 const void *addrdata = NULL;
154 if (rp->ai_family == AF_INET) {
155 addrdata = &((struct sockaddr_in*)rp->ai_addr)->sin_addr;
156 }
157#ifdef AF_INET6
158 else if (rp->ai_family == AF_INET6) {
159 addrdata = &((struct sockaddr_in6*)rp->ai_addr)->sin6_addr;
160 }
161#endif
162 if (addrdata) {
163 char* endp = NULL;
164 uint16_t listen_port = 0;
165 if (rp->ai_family == AF_INET) {
166 listen_port = ntohs(((struct sockaddr_in*)rp->ai_addr)->sin_port);
167 if (inet_ntop(AF_INET, addrdata, listen_addr_str, sizeof(listen_addr_str)-6)) {
168 endp = &listen_addr_str[0] + strlen(listen_addr_str);
169 }
170 }
171#ifdef AF_INET6
172 else if (rp->ai_family == AF_INET6) {
173 listen_port = ntohs(((struct sockaddr_in6*)rp->ai_addr)->sin6_port);
174 listen_addr_str[0] = '[';
175 if (inet_ntop(AF_INET6, addrdata, listen_addr_str+1, sizeof(listen_addr_str)-8)) {
176 endp = &listen_addr_str[0] + strlen(listen_addr_str);
177 }
178 if (endp) {
179 *endp = ']';
180 endp++;
181 }
182 }
183#endif
184 if (endp) {
185 sprintf(endp, ":%u", listen_port);
186 }
187 }
188 break;
189 }
190 freeaddrinfo(result);
191 if (listenfd == -1) {
192 usbmuxd_log(LL_FATAL, "%s: Failed to create listening socket", __func__);
193 return -1;
194 }
195 } else {
196 struct sockaddr_un bind_addr;
197
198 if (strcmp(socket_addr, socket_path) != 0) {
199 struct stat fst;
200 if (stat(socket_addr, &fst) == 0) {
201 if (!S_ISSOCK(fst.st_mode)) {
202 usbmuxd_log(LL_FATAL, "FATAL: File '%s' already exists and is not a socket file. Refusing to continue.", socket_addr);
203 return -1;
204 }
205 }
206 }
207
208 if (unlink(socket_addr) == -1 && errno != ENOENT) {
209 usbmuxd_log(LL_FATAL, "%s: unlink(%s) failed: %s", __func__, socket_addr, strerror(errno));
210 return -1;
211 }
212
213 listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
214 if (listenfd == -1) {
215 usbmuxd_log(LL_FATAL, "socket() failed: %s", strerror(errno));
216 return -1;
217 }
218
219 bzero(&bind_addr, sizeof(bind_addr));
220 bind_addr.sun_family = AF_UNIX;
221 strncpy(bind_addr.sun_path, socket_addr, sizeof(bind_addr.sun_path));
222 bind_addr.sun_path[sizeof(bind_addr.sun_path) - 1] = '\0';
223
224 if (bind(listenfd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) != 0) {
225 usbmuxd_log(LL_FATAL, "bind() failed: %s", strerror(errno));
226 return -1;
227 }
228 chmod(socket_addr, 0666);
229
230 snprintf(listen_addr_str, sizeof(listen_addr_str), "%s", socket_addr);
88 } 231 }
89 232
90 int flags = fcntl(listenfd, F_GETFL, 0); 233 int flags = fcntl(listenfd, F_GETFL, 0);
@@ -96,21 +239,13 @@ static int create_socket(void) {
96 } 239 }
97 } 240 }
98 241
99 bzero(&bind_addr, sizeof(bind_addr));
100 bind_addr.sun_family = AF_UNIX;
101 strcpy(bind_addr.sun_path, socket_path);
102 if (bind(listenfd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) != 0) {
103 usbmuxd_log(LL_FATAL, "bind() failed: %s", strerror(errno));
104 return -1;
105 }
106
107 // Start listening 242 // Start listening
108 if (listen(listenfd, 256) != 0) { 243 if (listen(listenfd, 256) != 0) {
109 usbmuxd_log(LL_FATAL, "listen() failed: %s", strerror(errno)); 244 usbmuxd_log(LL_FATAL, "listen() failed: %s", strerror(errno));
110 return -1; 245 return -1;
111 } 246 }
112 247
113 chmod(socket_path, 0666); 248 usbmuxd_log(LL_INFO, "Listening on %s", listen_addr_str);
114 249
115 return listenfd; 250 return listenfd;
116} 251}
@@ -381,6 +516,9 @@ static void usage()
381#ifdef HAVE_SYSTEMD 516#ifdef HAVE_SYSTEMD
382 printf(" -s, --systemd\t\tRun in systemd operation mode (implies -z and -f).\n"); 517 printf(" -s, --systemd\t\tRun in systemd operation mode (implies -z and -f).\n");
383#endif 518#endif
519 printf(" -S, --socket ADDR:PORT | PATH Specify source ADDR and PORT or a UNIX\n");
520 printf(" \t\tsocket PATH to use for the listening socket.\n");
521 printf(" \t\tDefault: %s\n", socket_path);
384 printf(" -x, --exit\t\tNotify a running instance to exit if there are no devices\n"); 522 printf(" -x, --exit\t\tNotify a running instance to exit if there are no devices\n");
385 printf(" \t\tconnected (sends SIGUSR1 to running instance) and exit.\n"); 523 printf(" \t\tconnected (sends SIGUSR1 to running instance) and exit.\n");
386 printf(" -X, --force-exit\tNotify a running instance to exit even if there are still\n"); 524 printf(" -X, --force-exit\tNotify a running instance to exit even if there are still\n");
@@ -408,6 +546,7 @@ static void parse_opts(int argc, char **argv)
408#ifdef HAVE_SYSTEMD 546#ifdef HAVE_SYSTEMD
409 {"systemd", no_argument, NULL, 's'}, 547 {"systemd", no_argument, NULL, 's'},
410#endif 548#endif
549 {"socket", required_argument, NULL, 'S'},
411 {"exit", no_argument, NULL, 'x'}, 550 {"exit", no_argument, NULL, 'x'},
412 {"force-exit", no_argument, NULL, 'X'}, 551 {"force-exit", no_argument, NULL, 'X'},
413 {"logfile", required_argument, NULL, 'l'}, 552 {"logfile", required_argument, NULL, 'l'},
@@ -468,6 +607,14 @@ static void parse_opts(int argc, char **argv)
468 case 'z': 607 case 'z':
469 opt_enable_exit = 1; 608 opt_enable_exit = 1;
470 break; 609 break;
610 case 'S':
611 if (!*optarg || *optarg == '-') {
612 usbmuxd_log(LL_FATAL, "ERROR: --socket requires an argument");
613 usage();
614 exit(2);
615 }
616 listen_addr = optarg;
617 break;
471 case 'x': 618 case 'x':
472 opt_exit = 1; 619 opt_exit = 1;
473 exit_signal = SIGUSR1; 620 exit_signal = SIGUSR1;