Can't bind ipv4-mapped ipv6 address

Aleksej Lebedev root at zta.lk
Tue Feb 21 23:04:35 PST 2023


Thanks for clarifying. Well, I suspected that's not a bug per se right after sending my email. I noticed a few comments in the kernel source code about ipv6-mapped addresses which lead me to think that my comment might have been wrong.

Interestingly, the problematic code does not require IPV6-only support in the first place. I am talking about fefe-patched djbdns. There is absolutely no need to use INET6 sockets in the code as the server is actually opening multiple sockets per address anyway so why not open INET sockets for ipv4 addresses? I'll fix the code - looks like it's trivial.

Thanks once more.

--
Aleksej Lebedev

On Wed, Feb 22, 2023, at 01:46, Aaron LI wrote:
> 
> Hi Aleksej,
> 
> DragonFly doesn’t support the ‘IPV6_V6ONLY’ socket option, and thus no support of IPv4-mapped IPv6 address.
> 
> So a dual-stack program must create one IPv4 socket *and* another IPv6 socket.
> 
> See also the ip6(4) man page:
> https://man.dragonflybsd.org/?command=ip6&section=ANY
> 
>> Aaron
> 
>> On Feb 22, 2023, at 06:10, Aleksej Lebedev <root at zta.lk> wrote:
>> Hi,
>> 
>> I think I found a bug in bind(2) or at least the behavior that differs from Linux and is expected to like in Linux.
>> On linux instead of creating a PF_INET UDP socket and assigning an ipv4 address I can create PF_INET6 UDP socket and assigning it an ipv4-mapped ipv6 address (i.e. ::ffff:x.x.x.x).
>> On DragonFly the first way works (of course) but the second option doesn't seem to:
>> 
>> $ cat test_bind.c 
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <netinet/in.h>
>> #include <sys/types.h>
>> #include <sys/socket.h>
>> #include <arpa/inet.h>
>> 
>> void die(const char *s) { perror(s); exit(1); }
>> 
>> int main()
>> {
>>  struct sockaddr_in sa;
>>  int s, r;
>> 
>>  s = socket(PF_INET, SOCK_DGRAM, 0);
>> 
>>  r = inet_pton(AF_INET, "176.9.104.141", &sa.sin_addr);
>>  if (r == INADDR_NONE) die("inet_pton");
>> 
>>  sa.sin_family = AF_INET;
>>  sa.sin_port = 53;
>> 
>>  r = bind(s, (const struct sockaddr *)&sa, sizeof sa);
>>  if (r != 0) die("bind");
>> 
>> }
>> $ cc test_bind.c && a.out
>> $ echo $?
>> 0
>> 
>> $ cat test_bind6.c 
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <netinet/in.h>
>> #include <sys/types.h>
>> #include <sys/socket.h>
>> #include <arpa/inet.h>
>> 
>> void die(const char *s) { perror(s); exit(1); }
>> 
>> int main()
>> {
>>  struct sockaddr_in6 sa;
>>  int s, r;
>> 
>>  s = socket(PF_INET6, SOCK_DGRAM, 0);
>> 
>>  r = inet_pton(AF_INET6, "::ffff:176.9.104.141", &sa.sin6_addr);
>>  if (r == INADDR_NONE) die("inet_pton");
>> 
>>  sa.sin6_family = AF_INET6;
>>  sa.sin6_port = 53;
>> 
>>  r = bind(s, (const struct sockaddr *)&sa, sizeof sa);
>>  if (r != 0) die("bind");
>> 
>> }
>> $ cc test_bind6.c && ./a.out
>> bind: Can't assign requested address
>> $ echo $?
>> 1
>> 
>> On Linux both versions work.
>> 
>> --
>> Aleksej Lebedev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dragonflybsd.org/pipermail/users/attachments/20230222/96b5dc5e/attachment-0002.htm>


More information about the Users mailing list