Reputation: 21
I'm trying to send IPv6 UDP multicast messages.
Part of test code below shows two parts, one for sending IPv6 multicast messages, the other for sending IPv4 multicast messages.
Code for IPv4 works fine.
Code for IPv6 always fails in sendto, returning with EADDRNOTAVAIL (99) Cannot assign requested address.
...
if (ipV6Select)
{
// Create IPv6 DGRAM Socket
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0)
throw OIP::OipException(OIP_SOCK_ACTION_FAILED("Cannot set socket option IPV6 socket, socket function failed with retVal " <<
sock << " (errno=" << strerror(errno) << " (" << errno << ")."));
// Register multicast interface.
int ifIdx{static_cast<int>(if_nametoindex("svlan1_260"))};
std::cout << "Temp:ifIdx=" << ifIdx << std::endl;
std::lock_guard<std::mutex> lockGuard(setSockoptMutex);
retVal = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIdx, sizeof(ifIdx));
if (retVal < 0)
throw OIP::OipException(OIP_SOCK_ACTION_FAILED("Cannot set socket option IPV6_MULTICAST_IF, setsockopt function failed with retVal " <<
retVal << " (errno=" << strerror(errno) << " (" << errno << ")."));
// Create IPv6 address.
struct sockaddr_in6 sockAddrIpV6{};
sockAddrIpV6.sin6_family = {AF_INET6};
sockAddrIpV6.sin6_port = {htons(2020)};
sockAddrIpV6.sin6_scope_id = {static_cast<uint32_t>(ifIdx)};
inet_pton(AF_INET6, "FF02:0000:0000:0000:0000:0000:0000:00FE", &sockAddrIpV6.sin6_addr);
std::cout << "IPV6 Send: family=" << sockAddrIpV6.sin6_family << ", sin6_port=" << sockAddrIpV6.sin6_port << ", sin6_scope_id=" << sockAddrIpV6.sin6_scope_id
<< ", addr=FF02:0000:0000:0000:0000:0000:0000:00FE" << std::endl;
// Send message to socket.
retVal = sendto(sock,
sendMsgCharBufVect.data(),
sendMsgCharBufVect.size(),
0,
reinterpret_cast<struct sockaddr*>(&sockAddrIpV6),
sizeof(struct sockaddr_in6));
if (retVal < 0)
throw OIP::OipException(OIP_SOCK_ACTION_FAILED("IPV6 Socket send data (socket sendto function) failed with retVal " << retVal <<
" (errno=" << strerror(errno) << " (" << errno << "))."));
}
// Send IPV4 multicast message.
else
{
// Create IPv4 DGRAM Socket
std::string ipV4Str{"239.0.0.254"};
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
throw OIP::OipException(OIP_SOCK_ACTION_FAILED("Cannot set socket option IPV4 socket, socket function failed with retVal " <<
sock << " (errno=" << strerror(errno) << " (" << errno << ")."));
// Register multicast interface.
struct ip_mreqn mreqn{};
inet_aton(ipV4Str.c_str(), &mreqn.imr_multiaddr);
mreqn.imr_ifindex = {static_cast<int>(if_nametoindex("svlan1_260"))};
retVal = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn));
if (retVal < 0)
throw OIP::OipException(OIP_SOCK_ACTION_FAILED("Cannot set socket option IP_MULTICAST_IF, setsockopt function failed with retVal " <<
retVal << " (errno=" << strerror(errno) << " (" << errno << ")."));
// Create IPv4 address.
struct sockaddr_in sockAddrIpV4{};
sockAddrIpV4.sin_family = {AF_INET};
sockAddrIpV4.sin_port = {htons(2020)};
inet_aton(ipV4Str.c_str(), &sockAddrIpV4.sin_addr);
std::cout << "IPV4 Send: family=" << sockAddrIpV4.sin_family << ", sin_port=" << sockAddrIpV4.sin_port << ", addr=" << std::hex << sockAddrIpV4.sin_addr.s_addr<< std::dec <<std::endl;
// Send message to socket.
retVal = sendto(sock,
sendMsgCharBufVect.data(),
sendMsgCharBufVect.size(),
0,
reinterpret_cast<struct sockaddr*>(&sockAddrIpV4),
sizeof(struct sockaddr_in));
if (retVal < 0)
throw OIP::OipException(OIP_SOCK_ACTION_FAILED("IPV4 Socket send data (socket sendto function) failed with retVal " << retVal <<
" (errno=" << strerror(errno) << " (" << errno << "))."));
}
...
tcpdump IPv4 shows outgoing multicast message with requested address:
2020-04-02 23:30:19.384892 00:60:1d:7d:08:07 (oui Unknown) > 01:00:5e:00:00:fe (oui Unknown), ethertype 802.1Q (0x8100), length 90: vlan 260, p 0, ethertype IPv4, (tos 0x0, ttl 1, id 54916, offset 0, flags [none], proto UDP (17), length 72)
100.5.81.1.38790 > 239.0.0.254.2020: UDP, length 44
0x0000: 0100 5e00 00fe 0060 1d7d 0807 8100 0104
0x0010: 0800 4500 0048 d684 0000 0111 3e1c 6405
0x0020: 5101 ef00 00fe 9786 07e4 0034 a54a 4479
tcpdump for IPV6 only shows automatic generated IPV6 multicast messages:
2020-04-02 22:48:19.569203 00:60:1d:7d:08:07 (oui Unknown) > 33:33:00:00:00:16 (oui Unknown), ethertype 802.1Q (0x8100), length 174: vlan 260, p 0, ethertype IPv6, [|ip6]
0x0000: 3333 0000 0016 0060 1d7d 0807 8100 0104
0x0010: 86dd 6000 0000 0074 0001 0000 0000 0000
0x0020: 0000 0000 0000 0000 0000 ff02 0000 0000
2020-04-02 22:48:20.049156 00:60:1d:7d:08:07 (oui Unknown) > 33:33:00:00:00:16 (oui Unknown), ethertype 802.1Q (0x8100), length 174: vlan 260, p 0, ethertype IPv6, [|ip6]
0x0000: 3333 0000 0016 0060 1d7d 0807 8100 0104
0x0010: 86dd 6000 0000 0074 0001 0000 0000 0000
0x0020: 0000 0000 0000 0000 0000 ff02 0000 0000
2020-04-02 22:48:20.329171 00:60:1d:7d:08:07 (oui Unknown) > 33:33:ff:7d:08:07 (oui Unknown), ethertype 802.1Q (0x8100), length 90: vlan 260, p 0, ethertype IPv6, [|ip6]
0x0000: 3333 ff7d 0807 0060 1d7d 0807 8100 0104
0x0010: 86dd 6000 0000 0020 3aff 0000 0000 0000
0x0020: 0000 0000 0000 0000 0000 ff02 0000 0000
root@MEC2-81-1-STDBY:/lib# 2020-04-02 22:48:21.359289 00:60:1d:7d:08:07 (oui Unknown) > 33:33:00:00:00:16 (oui Unknown), ethertype 802.1Q (0x8100), length 134: vlan 260, p 0, ethertype IPv6, [|ip6]
0x0000: 3333 0000 0016 0060 1d7d 0807 8100 0104
0x0010: 86dd 6000 0000 004c 0001 fe80 0000 0000
0x0020: 0000 0260 1dff fe7d 0807 ff02 0000 0000
2020-04-02 22:48:21.389154 00:60:1d:7d:08:07 (oui Unknown) > 33:33:00:00:00:16 (oui Unknown), ethertype 802.1Q (0x8100), length 94: vlan 260, p 0, ethertype IPv6, [|ip6]
0x0000: 3333 0000 0016 0060 1d7d 0807 8100 0104
0x0010: 86dd 6000 0000 0024 0001 fe80 0000 0000
0x0020: 0000 0260 1dff fe7d 0807 ff02 0000 0000
2020-04-02 22:48:22.159152 00:60:1d:7d:08:07 (oui Unknown) > 33:33:00:00:00:16 (oui Unknown), ethertype 802.1Q (0x8100), length 134: vlan 260, p 0, ethertype IPv6, [|ip6]
0x0000: 3333 0000 0016 0060 1d7d 0807 8100 0104
0x0010: 86dd 6000 0000 004c 0001 fe80 0000 0000
0x0020: 0000 0260 1dff fe7d 0807 ff02 0000 0000
2020-04-02 22:48:22.319152 00:60:1d:7d:08:07 (oui Unknown) > 33:33:00:00:00:16 (oui Unknown), ethertype 802.1Q (0x8100), length 94: vlan 260, p 0, ethertype IPv6, [|ip6]
0x0000: 3333 0000 0016 0060 1d7d 0807 8100 0104
0x0010: 86dd 6000 0000 0024 0001 fe80 0000 0000
0x0020: 0000 0260 1dff fe7d 0807 ff02 0000 0000
Network interface: The used network interface is a VLAN interface svlan1_260 with VLAN ID 260, created on physical network interface eth2.
eth2 Link encap:Ethernet HWaddr 00:00:00:00:81:01
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1513 Metric:1
RX packets:3684437 errors:0 dropped:0 overruns:0 frame:0
TX packets:3410666 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:572562185 (546.0 MiB) TX bytes:109620349 (104.5 MiB)
Interrupt:32
svlan1_260 Link encap:Ethernet HWaddr 00:60:1d:7d:08:07
inet addr:100.5.81.1 Bcast:100.5.255.255 Mask:255.255.0.0
inet6 addr: fe80::260:1dff:fe7d:807/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:709 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:85982 (83.9 KiB)
Questions:
Is there any idea, what is going wrong for IPv6?
May be wrong address, although I tried several?
Any missing socket configuration?
Any system settings, not correctly set?
thanks
Upvotes: 0
Views: 1165
Reputation: 21
Found reason of the problem after much debugging.
The T-bit flag (Dynamically assigned multicast address), mentioned in comments above for sure should be correctly set. But sending also works, if T-bit is set to 0 (Well-known multicast address).
There's following reason for the failing sendto call. Short time before creating the socket and sending the message, on the respective network interface the MAC address has been changed via ioctl SIOCSIFHWADDR. In order to get the local IPv6 address automatically updated with the new MAC address the network interface was set down and up again via ioctl SIOCSIFFLAGS.
When socket was created and message sent, link up had not been finished. Therefore the sendto failed. The IPv6 messages in the tcpdump above belong to the network interface start up.
When waiting some seconds after network interface up, everything works fine.
Upvotes: 0