socket_create only binds to IPv6 any instead of IPv4 and IPv6 loopback
Opened this issue · 3 comments
This commit 303ece5 uses socket_create
to bind and listen address, however by default it seems to bind to IPv6 address only on my mac device.
IPv4 loopback
$ iproxy -s '127.0.0.1' 2222:22
$ sudo lsof -P -i tcp:2222
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
iproxy 4759 user 3u IPv4 0x920c56b46d641c07 0t0 TCP localhost:2222 (LISTEN)
# ssh ok
IPv6 loopback
$ iproxy -s '::1' 2222:22
$ sudo lsof -P -i tcp:2222
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
iproxy 4898 user 3u IPv6 0x920c56b935c599b7 0t0 TCP localhost:2222 (LISTEN)
# ssh ok
Default: IPv6 any
$ iproxy 2222:22
$ sudo lsof -P -i tcp:2222
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
iproxy 4923 user 4u IPv6 0x920c56b935c599b7 0t0 TCP *:2222 (LISTEN
$ ssh root@127.0.0.1 -p 2222
ssh: connect to host 127.0.0.1 port 2222: Connection refused
$ ssh root@localhost -p 2222
# success
Env
$ sw_vers
ProductName: macOS
ProductVersion: 14.4.1
BuildVersion: 23E224
According to the code at https://github.com/libimobiledevice/libimobiledevice-glue/blob/fde8946a3988790fd5d3f01fc0a1fd43609ab1d1/src/socket.c#L534
On my device, I will get 2 address which are [::]:2222
and 0.0.0.0:2222
by calling getaddrinfo
, however due to the break
, the second address will not be bind
, which does not match the help (127.0.0.1) / commit (ipv4+ipv6) description.
Oh... the reason for the changes was this: libimobiledevice/libimobiledevice-glue#40
I guess I misunderstood (and subsequently failed to properly test) what NULL would mean for getaddrinfo, and assumed we'd get a single socket capable of listening to both IPv4 and IPv6, but I was wrong apparently... Now the break obviously prevents creating further sockets, and that makes perfect sense, since the function create_socket
returns a single socket and I don't see a way to change it. However, I can just change the code in iproxy to the old behavior, creating two listening sockets.
Ok I know how to fix this, but I am not sure if this is the best way to do it. In https://github.com/libimobiledevice/libimobiledevice-glue/blob/fde8946a3988790fd5d3f01fc0a1fd43609ab1d1/src/socket.c#L517
I am setting IPV6_V6ONLY
to 1. Setting this to NO would end up creating a single socket that would also be reachable with IPv4.
I tried this:
diff --git a/src/socket.c b/src/socket.c
index d4dedd1..3375e5b 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -463,6 +463,7 @@ int socket_create(const char* addr, uint16_t port)
{
int sfd = -1;
int yes = 1;
+ int no = 0;
struct addrinfo hints;
struct addrinfo *result, *rp;
char portstr[8];
@@ -514,7 +515,7 @@ int socket_create(const char* addr, uint16_t port)
#if defined(AF_INET6) && defined(IPV6_V6ONLY)
if (rp->ai_family == AF_INET6) {
- if (setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&yes, sizeof(int)) == -1) {
+ if (setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (addr) ? (void*)&yes : (void*)&no, sizeof(int)) == -1) {
perror("setsockopt() IPV6_V6ONLY");
}
}
And it will make it work. It would set IPV6_V6ONLY
to 0 only if addr
is NULL but 1 in any other case. Not sure if it would be needed in any other case?
That looks great 💯