<resending since my from: wasn't previously subscribed, sorry for any dups>
Hello,
The manpage for recvmsg states
"""
These calls return the number of bytes received, or -1 if an error
occurred. In the event of an error, errno is set to indicate the
error. The return value will be 0 when the peer has performed an
orderly shutdown.
"""
Now, I'm not sure what an "orderly shutdown" means in the context of
Multicast UDP, but it appears that zero is also returned when a UDP
packet with zero payload arrives at a PTP port, to either the
multicast address or a client's unicast address,
A packet with short but non-zero payload (i.e 1 byte) results in ptp4l
logging "Bad message" as expected.
A packet with a zero-length payload triggers an error code path:
* Prints an errstr "host or device not found" (stale errno?)
* Reset the whole state machine after a 2^4 second pause.
I get that such broken packets probably shouldn't exist in the first
place, but since we're already robust to 1, 2, 3 .. byte payloads, it
makes sense to also survive zero byte ones.
Unfortunately there are networks (GMs?) in the wild which appear to do
this, and in not all cases do ptp client users have control over the
master. The first time we saw this an iptables rule to drop unusually
tiny frames was deemed sufficient, but it's come up again so I looked
to a more general solution.
Are there situations where recvmsg could return zero to indicate an
actual "error" as opposed to "successfully received the empty string"?
I guess we could pay closer attention to errno if so.
Thanks,
David
For what it's worth, with this script I was able to freak out all
clients on the same broadcast domain:
#!/usr/bin/env python
import socket
import struct
def main():
MCAST_GRP = '224.0.1.129'
MCAST_PORT = 320
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
sock.sendto('', (MCAST_GRP, MCAST_PORT))
if __name__ == '__main__':
main()
And here's a patch which appears to mitigate it, at least in this case:
(It's against 1.9.2, but applies to git head as of just now with minor
offsets)
diff --git a/port.c b/port.c
index 6d1ce21..cfda01e 100644
--- a/port.c
+++ b/port.c
@@ -2549,7 +2549,7 @@ enum fsm_event port_event(struct port *p, int
fd_index)
msg->hwts.type = p->timestamping;
cnt = transport_recv(p->trp, fd, msg);
- if (cnt <= 0) {
+ if (cnt < 0) {
pr_err("port %hu: recv message failed", portnum(p));
msg_put(msg);
return EV_FAULT_DETECTED;
diff --git a/sk.c b/sk.c
index f18b2bf..2fff605 100644
--- a/sk.c
+++ b/sk.c
@@ -321,7 +321,7 @@ int sk_receive(int fd, void *buf, int buflen,
}
cnt = recvmsg(fd, &msg, flags);
- if (cnt < 1)
+ if (cnt < 0)
pr_err("recvmsg%sfailed: %m",
flags == MSG_ERRQUEUE ? " tx timestamp " : " ");
_______________________________________________
Linuxptp-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel