Bug 281391 - IPv6 multicast sent to wrong MAC address
Summary: IPv6 multicast sent to wrong MAC address
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 14.0-RELEASE
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-net (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-09-09 13:39 UTC by cmfitch1
Modified: 2024-09-20 22:02 UTC (History)
5 users (show)

See Also:


Attachments
test case program (4.88 KB, text/plain)
2024-09-20 21:42 UTC, antonfb
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description cmfitch1 2024-09-09 13:39:55 UTC
An application that joins an IPv6 multicast group without performing an IPV6_MULTICAST_IF setsockopt() will see packets sent to the wrong MAC address. According to RFC2464 section 7 [1], the MAC should be 33:33:DST[13]:DST[14]:DST[15]:DST[16], but FreeBSD is sending to 33:33:last:four:of:gateway. Setting IPV6_MULTICAST_IF results in the expected destination MAC.

My uneducated analysis - It looks to me like this is because setting IPV6_MULTICAST_IF bypasses (sys/netinet6/ip6_output.c:753) the routing code that would otherwise modify the destination IP to be the gateway. I expect what's missing is the equivalent of sys/netinet/ip_output.c:551 where the destination is restored to be the multicast address after the routing decision is made:

/*
 * IP destination address is multicast.  Make sure "gw"
 * still points to the address in "ro".  (It may have been
 * changed to point to a gateway address, above.)
 */
gw = (const struct sockaddr *)dst;

[1] https://datatracker.ietf.org/doc/html/rfc2464#section-7
Comment 1 antonfb 2024-09-15 23:34:08 UTC
I have a test program which shows 13.3 multicast reaching 14.1 but the 14.1 packets do not reach 13.3
The program tests ipv4 or ipv6.
It was working fine when written for 13.1 years ago.
So, anyhow, I think I've hit this problem.
Comment 2 Mark Johnston freebsd_committer freebsd_triage 2024-09-20 15:09:54 UTC
(In reply to antonfb from comment #1)
Is it possible to share the test program?
Comment 3 antonfb 2024-09-20 21:42:02 UTC
Created attachment 253704 [details]
test case program

My test program attached.
NOTE: You need to modify it with your /64 address in the location with a comment.

Here's some of my truss output with concurrent runs on 13.4 and 14.1

the 14.1 machine... (command "hive foo" i.e. one argument to cause ipv6 case...)
NOTE this receives the multicast messages...
socket(PF_INET6,SOCK_DGRAM,0)                    = 3 (0x3)
bind(3,{ AF_INET6 [::]:3412 },28)                = 0 (0x0)
setsockopt(3,IPPROTO_IPV6,IPV6_MULTICAST_HOPS,0x8209f444c,4) = 0 (0x0)
setsockopt(3,IPPROTO_IPV6,IPV6_MULTICAST_LOOP,0x8209f444c,4) = 0 (0x0)
setsockopt(3,IPPROTO_IPV6,IPV6_JOIN_GROUP,0x8209f4438,20) = 0 (0x0)
sendmsg(3,{{ AF_INET6 [ff34:40:2001:5a8:60c8:1e00:2:1]:3412 },28,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 4.999998 })             = 1 (0x1)
recvfrom(3,"This is a test",200,0,{ AF_INET6 [2001:5a8:60c8:1e00:8647:9ff:fe2e:141a]:3412 },0x8209f433c) = 14 (0xe)
fstat(1,{ mode=crw--w---- ,inode=379,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0x8209f3ac4)                    = 0 (0x0)
2001:5a8:60c8:1e00:8647:9ff:fe2e:141a 3412 This is a test
write(1,"2001:5a8:60c8:1e00:8647:9ff:fe2e"...,58) = 58 (0x3a)
select(4,{ 3 },0x0,0x0,{ 4.678515 })             = 0 (0x0)
sendmsg(3,{{ AF_INET6 [ff34:40:2001:5a8:60c8:1e00:2:1]:3412 },28,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)

The 13.4 machine...
same command run, one argument to cause ipv6
NOTE this does not receive messages from the 14.1 machine
socket(PF_INET6,SOCK_DGRAM,0)                    = 3 (0x3)
bind(3,{ AF_INET6 [::]:3412 },28)                = 0 (0x0)
setsockopt(3,IPPROTO_IPV6,IPV6_MULTICAST_HOPS,0x820ada4dc,4) = 0 (0x0)
setsockopt(3,IPPROTO_IPV6,IPV6_MULTICAST_LOOP,0x820ada4dc,4) = 0 (0x0)
setsockopt(3,IPPROTO_IPV6,IPV6_JOIN_GROUP,0x820ada4c8,20) = 0 (0x0)
sendmsg(3,{{ AF_INET6 [ff34:40:2001:5a8:60c8:1e00:2:1]:3412 },28,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 5.000000 })             = 0 (0x0)
sendmsg(3,{{ AF_INET6 [ff34:40:2001:5a8:60c8:1e00:2:1]:3412 },28,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 4.999999 })             = 0 (0x0)
sendmsg(3,{{ AF_INET6 [ff34:40:2001:5a8:60c8:1e00:2:1]:3412 },28,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 4.999999 })             = 0 (0x0)
sendmsg(3,{{ AF_INET6 [ff34:40:2001:5a8:60c8:1e00:2:1]:3412 },28,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 4.999999 })             = 0 (0x0)
sendmsg(3,{{ AF_INET6 [ff34:40:2001:5a8:60c8:1e00:2:1]:3412 },28,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 4.999999 })             = 0 (0x0)

For completeness... the ipv4 runs work.
14.1 machine...
socket(PF_INET,SOCK_DGRAM,0)                     = 3 (0x3)
bind(3,{ AF_INET 0.0.0.0:3412 },16)              = 0 (0x0)
setsockopt(3,IPPROTO_IP,IP_MULTICAST_TTL,0x821026d5c,4) = 0 (0x0)
setsockopt(3,IPPROTO_IP,IP_MULTICAST_LOOP,0x821026d5c,4) = 0 (0x0)
setsockopt(3,IPPROTO_IP,IP_ADD_MEMBERSHIP,0x821026d48,8) = 0 (0x0)
sendmsg(3,{{ AF_INET 239.1.0.1:3412 },16,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 5.000000 })             = 1 (0x1)
recvfrom(3,"This is a test",200,0,{ AF_INET 192.168.2.5:3412 },0x821026c4c) = 14 (0xe)
fstat(1,{ mode=crw--w---- ,inode=379,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0x8210263d4)                    = 0 (0x0)
192.168.2.5 3412 This is a test
write(1,"192.168.2.5 3412 This is a test"...,32) = 32 (0x20)
select(4,{ 3 },0x0,0x0,{ 4.998028 })             = 0 (0x0)
sendmsg(3,{{ AF_INET 239.1.0.1:3412 },16,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 5.000000 })             = 1 (0x1)
recvfrom(3,"This is a test",200,0,{ AF_INET 192.168.2.5:3412 },0x821026c4c) = 14 (0xe)
192.168.2.5 3412 This is a test

13.2 machine...
socket(PF_INET,SOCK_DGRAM,0)                     = 3 (0x3)
bind(3,{ AF_INET 0.0.0.0:3412 },16)              = 0 (0x0)
setsockopt(3,IPPROTO_IP,IP_MULTICAST_TTL,0x8205725ec,4) = 0 (0x0)
setsockopt(3,IPPROTO_IP,IP_MULTICAST_LOOP,0x8205725ec,4) = 0 (0x0)
setsockopt(3,IPPROTO_IP,IP_ADD_MEMBERSHIP,0x8205725d8,8) = 0 (0x0)
sendmsg(3,{{ AF_INET 239.1.0.1:3412 },16,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 5.000000 })             = 0 (0x0)
sendmsg(3,{{ AF_INET 239.1.0.1:3412 },16,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 5.000000 })             = 0 (0x0)
sendmsg(3,{{ AF_INET 239.1.0.1:3412 },16,[{"This is a test",14}],1,{},0,0},0) = 14 (0xe)
select(4,{ 3 },0x0,0x0,{ 5.000000 })             = 1 (0x1)
recvfrom(3,"This is a test",200,0,{ AF_INET 192.168.2.3:3412 },0x8205724dc) = 14 (0xe)
fstat(1,{ mode=crw--w---- ,inode=381,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0x820571c64)                    = 0 (0x0)
192.168.2.3 3412 This is a test