Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

udpsend error in mac os #175

Open
GeekCookie opened this issue May 26, 2017 · 10 comments
Open

udpsend error in mac os #175

GeekCookie opened this issue May 26, 2017 · 10 comments

Comments

@GeekCookie
Copy link

When invoke udpsend method, the error occurs. error code is 22, means invalid argument.

@sustrik
Copy link
Owner

sustrik commented May 26, 2017

Can you give a concrete example?

@HarukaMa
Copy link

I have tested this on macOS 10.13 and found that if you use IPADDR_PREF_IPV6 when creating iplocal in dual-stack environment, sending to IPv4 address would cause errno 22. Changing iplocal to IPADDR_PREF_IPV4 works.

Didn't test with other configuration: IPv4 only environment or sending to IPv6 address.

Here is a simple example:

#include <libmill.h>
#include <stdio.h>

int main() {
	ipaddr local = iplocal(NULL, 0, IPADDR_PREF_IPV6);
	udpsock s = udplisten(local);
	ipaddr addr = ipremote("8.8.8.8", 60000, 0, -1);
	char* data[10] = {0};
	udpsend(s, addr, data, 10);
	printf("%d\n", errno);
}

Program would print out 22 in this case. If you change IPADDR_PREF_IPV6 to IPADDR_PREF_IPV4 in line 5 program would print out 0.

@sustrik
Copy link
Owner

sustrik commented Oct 24, 2017

It looks like the error is coming from here: https://github.com/sustrik/libmill/blob/master/udp.c#L104

22 means EINVAL

The man page description doesn't seem to apply: https://www.unix.com/man-page/osx/2/sendto/

Try checking whether udplisten succeeds.

@HarukaMa
Copy link

Upon more testing I've found that the above code works on ipv4-only interfaces such as one of my VPN tunnel utun2, but it fails on interfaces with ipv6 address even if it is link local address (fe80::/64).

udplisten succeeded nonetheless.

@sustrik
Copy link
Owner

sustrik commented Oct 25, 2017

Can you trace the execution to udp.c:104 then check the argument values to sendto() function as well as the result value and errno?

@HarukaMa
Copy link

(gdb) r
Starting program: /Users/MrX/test2
[New Thread 0x1403 of process 43440]
warning: unhandled dyld version (15)

Thread 2 hit Breakpoint 1, main () at test2.c:9
9		udpsend(s, addr, data, 10);
(gdb) s
mill_udpsend_ (s=0x100200060, addr=..., buf=0x7ffeefbff600, len=10) at udp.c:103
103	    struct sockaddr *saddr = (struct sockaddr*) &addr;
(gdb) s
104	    ssize_t ss = sendto(s->fd, buf, len, 0, saddr, saddr->sa_family ==
(gdb) p s->fd
$1 = 3
(gdb) p buf
$2 = (const void *) 0x7ffeefbff600
(gdb) p len
$3 = 10
(gdb) p saddr->sa_family
$4 = 2 '\002'
(gdb) s
106	    int _errno = errno;
(gdb) s
107	    if(mill_fast(ss == (ssize_t)len)) {
(gdb) p ss
$5 = -1
(gdb) p _errno
$6 = 22

Couldn't check errno in gdb so I modified udp.c a little. Seems that saddr->sa_family is AF_INET.

@sustrik
Copy link
Owner

sustrik commented Oct 27, 2017

sa_family is AF_INET because you pass in IPv4 address (8.8.8.8)

Possibly, the problem is that socket, although using "bind to all interfaces" option only binds to IPv6 interfaces and as such it complains when trying to send to IPv4 address.

@HarukaMa
Copy link

I have tried to bind to dual-stack interfaces by using iplocal("en0", 0, IPADDR_PREF_IPV6); but still the same error. en0 have both ipv4 and ipv6 addresses.

@sustrik
Copy link
Owner

sustrik commented Oct 27, 2017

What happens if you try to send the packet to an acutal IPv6 address?

@HarukaMa
Copy link

The packet could be sent successfully with no error. The packet was observed on tcpdump.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants