summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2020-05-28 04:06:28 +0200
committerGravatar Nikias Bassen2020-05-28 04:06:28 +0200
commit910166b3d67652abb54dece7e1cacdc9dcfdb659 (patch)
treeb64196ba50cac4ddd666bff576035f362f754e4c
parent1bfcffbb9ea297457b4f0237d179004371b6df48 (diff)
downloadlibusbmuxd-910166b3d67652abb54dece7e1cacdc9dcfdb659.tar.gz
libusbmuxd-910166b3d67652abb54dece7e1cacdc9dcfdb659.tar.bz2
iproxy: Allow specifying source address for the listening socket
-rw-r--r--common/socket.c94
-rw-r--r--common/socket.h2
-rw-r--r--tools/iproxy.c24
3 files changed, 99 insertions, 21 deletions
diff --git a/common/socket.c b/common/socket.c
index a47de2a..1c38965 100644
--- a/common/socket.c
+++ b/common/socket.c
@@ -255,7 +255,7 @@ int socket_connect_unix(const char *filename)
}
#endif
-int socket_create(uint16_t port)
+int socket_create(const char* addr, uint16_t port)
{
int sfd = -1;
int yes = 1;
@@ -269,9 +269,79 @@ int socket_create(uint16_t port)
wsa_init = 1;
}
#endif
+ struct sockaddr* srcaddr;
+ int srcaddr_len = 0;
+ int domain = PF_INET;
+
+#if defined(AF_INET6)
+ struct sockaddr_in6 saddr6;
+ memset((void*) &saddr6, 0, sizeof(saddr6));
+ saddr6.sin6_family = AF_INET6;
+ saddr6.sin6_port = htons(port);
+ saddr6.sin6_addr = in6addr_loopback;
+#endif
+
struct sockaddr_in saddr;
+ memset((void*) &saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ saddr.sin_port = htons(port);
+
+ if (addr) {
+ if (strchr(addr, ':')) {
+#ifdef AF_INET6
+#ifdef WIN32
+ struct sockaddr_storage ss;
+ int ss_size = sizeof(ss);
+ if (WSAStringToAddress((LPSTR)addr, AF_INET6, NULL, (struct sockaddr*)&ss, &ss_size) == 0) {
+ memcpy(&(saddr6.sin6_addr), &(((struct sockaddr_in6*)&ss)->sin6_addr), sizeof(struct in6_addr));
+ } else
+#else
+ if (inet_pton(AF_INET6, addr, &(saddr6.sin6_addr)) != 1)
+#endif
+ {
+ fprintf(stderr, "FATAL: Failed to convert '%s' to an IPv6 address.\n", addr);
+ socket_close(sfd);
+ return -1;
+ }
+ srcaddr = (struct sockaddr*)&saddr6;
+ srcaddr_len = sizeof(saddr6);
+ domain = PF_INET6;
+#else
+ fprintf(stderr, "FATAL: Got IPv6 address but AF_INET6 is not supported.\n");
+ socket_close(sfd);
+ return -1;
+#endif
+ } else {
+#ifdef WIN32
+ struct sockaddr_storage ss;
+ int ss_size = sizeof(ss);
+ if (WSAStringToAddress((LPSTR)addr, AF_INET, NULL, (struct sockaddr*)&ss, &ss_size) == 0) {
+ saddr.sin_addr.s_addr = ((struct sockaddr_in*)&ss)->sin_addr.s_addr;
+ } else
+#else
+ if (inet_pton(AF_INET, addr, &(saddr.sin_addr)) != 1)
+#endif
+ {
+ fprintf(stderr, "FATAL: Failed to convert '%s' to an IPv4 address.\n", addr);
+ socket_close(sfd);
+ return -1;
+ }
+ srcaddr = (struct sockaddr*)&saddr;
+ srcaddr_len = sizeof(saddr);
+ }
+ } else {
+#if !defined(WIN32) && defined(AF_INET6)
+ srcaddr = (struct sockaddr*)&saddr6;
+ srcaddr_len = sizeof(saddr6);
+ domain = PF_INET6;
+#else
+ srcaddr = (struct sockaddr*)&saddr;
+ srcaddr_len = sizeof(saddr);
+#endif
+ }
- if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
+ if ((sfd = socket(domain, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket()");
return -1;
}
@@ -290,18 +360,13 @@ int socket_create(uint16_t port)
}
#endif
- memset((void *) &saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- saddr.sin_port = htons(port);
-
- if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) {
+ if (bind(sfd, srcaddr, srcaddr_len) < 0) {
perror("bind()");
socket_close(sfd);
return -1;
}
- if (listen(sfd, 1) == -1) {
+ if (listen(sfd, 1) < 0) {
perror("listen()");
socket_close(sfd);
return -1;
@@ -626,14 +691,13 @@ int socket_accept(int fd, uint16_t port)
socklen_t addr_len;
#endif
int result;
+#ifdef AF_INET6
+ struct sockaddr_in6 addr;
+ addr_len = sizeof(addr);
+#else
struct sockaddr_in addr;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr.sin_port = htons(port);
-
addr_len = sizeof(addr);
+#endif
result = accept(fd, (struct sockaddr*)&addr, &addr_len);
return result;
diff --git a/common/socket.h b/common/socket.h
index 38eeddf..f510147 100644
--- a/common/socket.h
+++ b/common/socket.h
@@ -45,7 +45,7 @@ typedef enum fd_mode fd_mode;
int socket_create_unix(const char *filename);
int socket_connect_unix(const char *filename);
#endif
-int socket_create(uint16_t port);
+int socket_create(const char *addr, uint16_t port);
int socket_connect_addr(struct sockaddr *addr, uint16_t port);
int socket_connect(const char *addr, uint16_t port);
int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout);
diff --git a/tools/iproxy.c b/tools/iproxy.c
index 8321143..e9524a4 100644
--- a/tools/iproxy.c
+++ b/tools/iproxy.c
@@ -220,6 +220,7 @@ static void print_usage(int argc, char **argv, int is_error)
" -u, --udid UDID target specific device by UDID\n" \
" -n, --network connect to network device\n" \
" -l, --local connect to USB device (default)\n" \
+ " -s, --source ADDR source address for listening socket (default 127.0.0.1)\n" \
" -h, --help prints usage information\n" \
" -d, --debug increase debug level\n" \
"\n" \
@@ -233,6 +234,7 @@ int main(int argc, char **argv)
{
int mysock = -1;
char* device_udid = NULL;
+ char* source_addr = NULL;
uint16_t listen_port = 0;
uint16_t device_port = 0;
enum usbmux_lookup_options lookup_opts = 0;
@@ -243,10 +245,11 @@ int main(int argc, char **argv)
{ "udid", required_argument, NULL, 'u' },
{ "local", no_argument, NULL, 'l' },
{ "network", no_argument, NULL, 'n' },
+ { "source", required_argument, NULL, 's' },
{ NULL, 0, NULL, 0}
};
int c = 0;
- while ((c = getopt_long(argc, argv, "dhu:ln", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "dhu:lns:", longopts, NULL)) != -1) {
switch (c) {
case 'd':
libusbmuxd_set_debug_level(++debug_level);
@@ -266,6 +269,15 @@ int main(int argc, char **argv)
case 'n':
lookup_opts |= DEVICE_LOOKUP_NETWORK;
break;
+ case 's':
+ if (!*optarg) {
+ fprintf(stderr, "ERROR: source address must not be empty!\n");
+ print_usage(argc, argv, 1);
+ return 2;
+ }
+ free(source_addr);
+ source_addr = strdup(optarg);
+ break;
case 'h':
print_usage(argc, argv, 0);
return 0;
@@ -307,7 +319,7 @@ int main(int argc, char **argv)
signal(SIGPIPE, SIG_IGN);
#endif
// first create the listening socket endpoint waiting for connections.
- mysock = socket_create(listen_port);
+ mysock = socket_create(source_addr, listen_port);
if (mysock < 0) {
fprintf(stderr, "Error creating socket: %s\n", strerror(errno));
free(device_udid);
@@ -323,7 +335,10 @@ int main(int argc, char **argv)
while (1) {
printf("waiting for connection\n");
c_sock = socket_accept(mysock, listen_port);
- if (c_sock) {
+ if (c_sock < 0) {
+ fprintf(stderr, "accept: %s\n", strerror(errno));
+ break;
+ } else {
printf("accepted connection, fd = %d\n", c_sock);
cdata = (struct client_data*)malloc(sizeof(struct client_data));
if (!cdata) {
@@ -344,8 +359,6 @@ int main(int argc, char **argv)
pthread_create(&acceptor, NULL, acceptor_thread, cdata);
pthread_detach(acceptor);
#endif
- } else {
- break;
}
}
socket_close(c_sock);
@@ -353,6 +366,7 @@ int main(int argc, char **argv)
}
free(device_udid);
+ free(source_addr);
return 0;
}