Repository navigation
v0.1.14
One fix this release, for appliances that answer a DTLS handshake from a port the client never dialled (#66, #73).
Replies from an unexpected source port (#66)
dtls_probe and DtlsCoapSession opened a connected UDP socket, which accepts datagrams only from the exact port it addressed. @elirnyk's capture on an NQ8300T oven shows a ClientHello going to 5684 and the answer arriving from 59768, followed by ICMP port unreachable from the client's own host. The probe reported a live appliance as dead, and a session retransmitted a cookie-less ClientHello until its deadline.
smartthings_local.protocol.endpoint now provides HostFilteredUdpSocket and open_host_filtered_udp_socket. They bind without connecting and filter inbound datagrams on host alone, which is what ocf_discovery already did. Both probe call sites and the session use them. open_connected_udp_socket is unchanged.
Sending stays on the port originally dialled. The capture in #66 shows the appliance still accepting there, and following the reply port instead would be a behaviour change with no evidence behind it.
Why an appliance does this
Stock RT-OCF binds only its multicast socket to a fixed port. In rt_udp_open_server, ucast_v4 and dtls_v4 both bind port 0, so the kernel assigns them, and rt_udp_get_secure_port_v4 reads the assigned port back to advertise as dport in /oic/res.
A secure port is therefore ephemeral by design and is reassigned across a reboot. Two practical consequences. An advertised port that moves between readings is expected. And 5684 is a guess on these devices, so read dport with discover_ocf_secure_ports.
Boundary
Off-path spoofing resistance drops from address-and-port to address alone. The DTLS cookie exchange and handshake authentication remain the real protection, as they already were behind a connected socket, and ocf_discovery had already made this tradeoff.
The RT-OCF reading above comes from the public source. The reporter's appliance runs a Samsung build that plainly differs from it: nothing in stock RT-OCF binds 5684, yet that oven answered a datagram sent there. Why it does remains open.
676 tests pass, six of them new: acceptance from another port, send-target stability, rejection of another host, IPv6 scope as part of host identity, and a bounded deadline under a flood of foreign datagrams.