diff options
| -rw-r--r-- | common/socket.c | 94 | ||||
| -rw-r--r-- | common/socket.h | 2 | ||||
| -rw-r--r-- | tools/iproxy.c | 24 | 
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;  } | 
