diff --git a/include/tins/packet_sender.h b/include/tins/packet_sender.h index e7acc10..1a1160f 100644 --- a/include/tins/packet_sender.h +++ b/include/tins/packet_sender.h @@ -65,7 +65,9 @@ class PDU; * - Those that don't contain a link layer PDU. In this case, the * kernel will be responsible for picking the appropriate network interface * based on the destination address. - * + * - Exception: RFC2553 + * requires IPv6 link-scope address have a interface defined. + * . * \par Note for Windows users: * Sending layer 3 PDUs (without a link layer protocol) is very restricted * on Windows (link). diff --git a/src/ipv6.cpp b/src/ipv6.cpp index 1689086..78c6824 100644 --- a/src/ipv6.cpp +++ b/src/ipv6.cpp @@ -366,11 +366,16 @@ void IPv6::write_serialization(uint8_t* buffer, uint32_t total_sz) { } #ifndef BSD -void IPv6::send(PacketSender& sender, const NetworkInterface &) { +void IPv6::send(PacketSender& sender, const NetworkInterface& interface) { sockaddr_in6 link_addr; const PacketSender::SocketType type = PacketSender::IPV6_SOCKET; link_addr.sin6_family = AF_INET6; link_addr.sin6_port = 0; + // Required to set sin6_scope_id to interface index as stated in RFC2553. + // https://datatracker.ietf.org/doc/html/rfc2553#section-3.3 + if (IPv6Address(header_.dst_addr).is_local_unicast()) { + link_addr.sin6_scope_id = interface.id(); + } memcpy((uint8_t*)&link_addr.sin6_addr, header_.dst_addr, address_type::address_size); sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type); }