FreeBSD 6.1 can't send UDP Broadcast. Here is simple test programm: --- test.c --- #include <stdio.h> #include <err.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> int main(void) { int sock, val, ret; struct sockaddr_in addr; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) err(1, "socket()"); addr.sin_family = AF_INET; addr.sin_port = htons(5000); addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); val = 1; ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&val, sizeof(val)); if (ret < 0) err(2, "setsockopt()"); ret = sendto(sock, "test", 4, 0, (struct sockaddr*)&addr, sizeof(addr)); if (ret != 4) err(3, "sendto()"); close(sock); return (0); } --- test.c --- 1. I've connect via PPTP tunnel and my host have default route. [butcher@btr butcher]> ./test [butcher@btr butcher]> sudo tcpdump -ni ng0 -XX udp port 5000 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ng0, link-type NULL (BSD loopback), capture size 96 bytes 19:25:32.169657 IP 192.168.3.6.53565 > 255.255.255.255.5000: UDP, length 4 0x0000: 0200 0000 4500 0020 241a 0000 4011 9305 ....E...$...@... 0x0010: c0a8 0306 ffff ffff d13d 1388 000c 6f88 .........=....o. 0x0020: 7465 7374 test ^C Message was send, but via PPTP to default destination. 2. I've not connected to PPTP server and don't have default route. [butcher@btr butcher]> netstat -rnf inet | grep default [butcher@btr butcher]> ./test test: sendto(): Network is unreachable test programm was fail with error. 3. I have the default route. [butcher@btr butcher]> sudo route add default server add net default: gateway server [butcher@btr butcher]> ./test [butcher@btr butcher]> sudo tcpdump -ni nve0 -XX udp port 5000 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on nve0, link-type EN10MB (Ethernet), capture size 96 bytes 19:29:51.988429 IP 192.168.4.234.54134 > 255.255.255.255.5000: UDP, length 4 0x0000: 0080 4836 9531 4255 5443 4821 0800 4500 ..H6.1BUTCH!..E. 0x0010: 0020 2459 0000 4011 90e2 c0a8 04ea ffff ..$Y..@......... 0x0020: ffff d376 1388 000c 6b6b 7465 7374 ...v....kktest ^C Message was send to default destination with router's destination MAC address. How-To-Repeat: Always.
State Changed From-To: open->feedback This behaviour is by design. Please read the manual page ip(4) for information on the IP_ONESBCAST option. The INADDR_BROADCAST destination is by its nature non specific and link local therefore you need to use the IP_ONESBCAST option to cause undirected broadcasts to be sent on a particular interface.
Responsible Changed From-To: freebsd-bugs->bms This behaviour is by design. Please read the manual page ip(4) for information on the IP_ONESBCAST option. The INADDR_BROADCAST destination is by its nature non specific and link local therefore you need to use the IP_ONESBCAST option to cause undirected broadcasts to be sent on a particular interface.
bms wrote: > This behaviour is by design.Please read the manual page ip(4) for > information on the IP_ONESBCASToption. The INADDR_BROADCAST destination > is by its nature non specificand link local therefore you need to use > the IP_ONESBCAST option tocause undirected broadcasts to be sent on a > particular interface. You are wrong. This behaviour violates both POLA and STD 0005 (RFC 919), regardless of any implementation-specific details like socket options. It requires that IP broadcast address must be mapped to link-level broadcast address, and STD 0041 (RFC 894) clearly specifies that on Ethernet it MUST be only ff:ff:ff:ff:ff:ff - while FreeBSD 6.0 and 6.1 send such packet with destination MAC address of gateway, by default routing (WRONG!) instead of link-level broadcast. Talking about IP_ONESBCAST option is unrelated to this bug, as FreeBSD 5.4 and 5.5 (I've tested) behaves correctly, while having this option too. It only tells about selection of interface, and not about resending broadcast to default router with his MAC addr instead of link-level broadcast on that interface. Here is excerpt from perl program ports/net/wakeonlan, doing broadcast to user-specified address - it works correctly (in subject of this PR) on FreeBSD 5 without IP_ONESBCAST option: socket(S, AF_INET, SOCK_DGRAM, $proto) or die "socket : $!"; setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!"; print "Sending magic packet to $ipaddr:$port with $hwaddr\n"; send(S, $pkt, 0, $them) or die "send : $!"; -- WBR, Vadim Goncharov
A few comments: * Please, when submitting tcpdump output, use the -e option to display the decoded link-layer addresses. It is all too easy for those of us who work on FreeBSD in what free time we can spare from our full-time jobs to miss such details, as I am sure you can appreciate, FreeBSD is a volunteer project. * Please attach the code in full you used to produce this condition as an attachment to the PR. * Based on the tcpdump output the submitter sent, this looks like it could be a regression introduced during the 6.x lifetime around the code which implements the IP_ONESBCAST option (which I introduced in FreeBSD 4.8), but this needs to be reproduced/confirmed. * Sends to 255.255.255.255 have never worked on FreeBSD the way STD0005 documents them. This is because 255.255.255.255 doesn't get any special treatment on the transmit path -- it is by design, and FreeBSD has always worked this way. On Thu, Jun 29, 2006 at 03:50:37PM +0700, Vadim Goncharov wrote: > Talking about IP_ONESBCAST option is unrelated to this bug, as FreeBSD > 5.4 and 5.5 (I've tested) behaves correctly, while having this option > too. It only tells about selection of interface, and not about > resending broadcast to default router with his MAC addr instead of > link-level broadcast on that interface. Here is excerpt from perl [..] Incorrect. The bug report was about the undirected broadcast address. IP_ONESBCAST is the only way to send an undirected broadcast datagram on FreeBSD without relying on the default route behaviour you comment on, as explained in the documentation. It is important to distinguish between undirected broadcasts (255.255.255.255) and directed broadcasts here (e.g. 192.168.1.255 in a network 192.168.1.0/24). You seem to be suggesting there is a problem with *all* forms of broadcast IPv4 traffic, both directed and undirected. This would point to a problem in the ARP layer, which would be a serious issue for the entire network stack. Can you please submit the information needed to reproduce this problem, and in particular, the date where you first noticed the problem? Thank you.
Andre Oppermann wrote: > The attached patch should fix the problem with SENDONES (untested). The problem was not resolved for me with this patch. :( -- WBR, Andrey V. Elsukov
Andrey V. Elsukov wrote: > Andre Oppermann wrote: >> The attached patch should fix the problem with SENDONES (untested). > > The problem was not resolved for me with this patch. :( Did you get an error message or did it simply put in the gateway's MAC address again? Was the IP destination address correct this time? Can you provide a tcpdump again? Have you set both SO_BROADCAST and IP_SENDONES? -- Andre
Andre Oppermann wrote: > Did you get an error message or did it simply put in the gateway's > MAC address again? Was the IP destination address correct this time? > Can you provide a tcpdump again? Have you set both SO_BROADCAST and > IP_SENDONES? Seems nothing has changed. Without default route i can't send broadcast (with both SO_BROADCAST and IP_ONESBCAST). With default route i have an equal messages (with IP_ONESBCAST and without). The tcpdump output is the same. -- WBR, Andrey V. Elsukov
Andrey V. Elsukov wrote: > Andre Oppermann wrote: >> Did you get an error message or did it simply put in the gateway's >> MAC address again? Was the IP destination address correct this time? >> Can you provide a tcpdump again? Have you set both SO_BROADCAST and >> IP_SENDONES? > > Seems nothing has changed. > Without default route i can't send broadcast > (with both SO_BROADCAST and IP_ONESBCAST). > > With default route i have an equal messages > (with IP_ONESBCAST and without). > > The tcpdump output is the same. OK, this time it is fixed. Please try again, if it works as it should then I'll commit it asap. http://people.freebsd.org/sendonesfix-20060830.diff http://people.freebsd.org/sendonestest-20060830.c The IP_ONESBCAST socket option is dependent on the SO_BROADCAST socket option which allows the sending of broadcast messages in general. Jails for example do not have this permission and will fail there. Another change I made is the unconditional setting of TTL=1. Allowing any higher TTL is not useful and actually dangerous. After the fix is in I'll change the ip(4) manpage accordingly. -- Andre
Andre Oppermann wrote: > Andrey V. Elsukov wrote: >> Andre Oppermann wrote: >>> Did you get an error message or did it simply put in the gateway's >>> MAC address again? Was the IP destination address correct this time? >>> Can you provide a tcpdump again? Have you set both SO_BROADCAST and >>> IP_SENDONES? >> >> Seems nothing has changed. >> Without default route i can't send broadcast >> (with both SO_BROADCAST and IP_ONESBCAST). >> >> With default route i have an equal messages >> (with IP_ONESBCAST and without). >> >> The tcpdump output is the same. > > OK, this time it is fixed. Please try again, if it works as it should > then I'll commit it asap. > > http://people.freebsd.org/sendonesfix-20060830.diff > http://people.freebsd.org/sendonestest-20060830.c OK, correct URL here: http://people.freebsd.org/~andre/sendonesfix-20060830.diff http://people.freebsd.org/~andre/sendonestest-20060830.c > The IP_ONESBCAST socket option is dependent on the SO_BROADCAST socket > option which allows the sending of broadcast messages in general. Jails > for example do not have this permission and will fail there. > > Another change I made is the unconditional setting of TTL=1. Allowing > any higher TTL is not useful and actually dangerous. After the fix is > in I'll change the ip(4) manpage accordingly. -- Andre
Andre Oppermann wrote: > OK, correct URL here: > > http://people.freebsd.org/~andre/sendonesfix-20060830.diff > http://people.freebsd.org/~andre/sendonestest-20060830.c > >> The IP_ONESBCAST socket option is dependent on the SO_BROADCAST socket >> option which allows the sending of broadcast messages in general. Jails >> for example do not have this permission and will fail there. Ok, i've tried your patches with fresh RELENG_6 kernel sources. 1. Without default gateway, ip_dst = 172.21.81.255 (broadcast for my subnet), SO_BROADCAST and IP_ONESBCAST was set. This works as described in ip(4) - I have a datagram with dst_ip 255.255.255.255 and broadcast MAC address. 2. Without default gateway, ip_dst = 172.21.81.255, SO_BROADCAST was set (without IP_ONESBCAST). I have a datagram with dst_ip 172.21.81.255 and broadcast MAC address. 3. Without default gateway, ip_dst = INADDR_BROADCAST, SO_BROADCAST was set (without IP_ONESBCAST). sendto(): Network is unreachable 4. Without default gateway, ip_dst = INADDR_BROADCAST, SO_BROADCAST and IP_ONESBCAST was set. sendto(): Network is unreachable 5. With default gateway, ip_dst = INADDR_BROADCAST, SO_BROADCAST and IP_ONESBCAST was set. sendto(): Network is unreachable 6. With default gateway, ip_dst = INADDR_BROADCAST, SO_BROADCAST was set (without IP_ONESBCAST). I have a datagram with ip_dst = 255.255.255.255 and gateway's MAC as destination ethernet address. 7. With default gateway, ip_dst = 172.21.81.255, SO_BROADCAST was set (without IP_ONESBCAST). I have a datagram with ip_dst = 172.21.81.255 and broadcast destination ethernet address. 8. With default gateway, ip_dst = 172.21.81.255, SO_BROADCAST and IP_ONESBCAST was set. I have a datagram with ip_dst = 255.255.255.255 and broadcast destination ethernet address. So, i think tests #4, #5 and #6 is incorrect, but maybe this is by design? -- WBR, Andrey V. Elsukov
Andrey V. Elsukov wrote: > Andre Oppermann wrote: >> OK, correct URL here: >> >> http://people.freebsd.org/~andre/sendonesfix-20060830.diff >> http://people.freebsd.org/~andre/sendonestest-20060830.c >> >>> The IP_ONESBCAST socket option is dependent on the SO_BROADCAST socket >>> option which allows the sending of broadcast messages in general. Jails >>> for example do not have this permission and will fail there. > > Ok, i've tried your patches with fresh RELENG_6 kernel sources. > > 1. Without default gateway, ip_dst = 172.21.81.255 (broadcast for my > subnet), SO_BROADCAST and IP_ONESBCAST was set. > This works as described in ip(4) - I have a datagram with dst_ip > 255.255.255.255 and broadcast MAC address. > > 2. Without default gateway, ip_dst = 172.21.81.255, SO_BROADCAST was set > (without IP_ONESBCAST). > I have a datagram with dst_ip 172.21.81.255 and broadcast MAC address. > > 3. Without default gateway, ip_dst = INADDR_BROADCAST, SO_BROADCAST was > set (without IP_ONESBCAST). > sendto(): Network is unreachable > > 4. Without default gateway, ip_dst = INADDR_BROADCAST, SO_BROADCAST and > IP_ONESBCAST was set. > sendto(): Network is unreachable > > 5. With default gateway, ip_dst = INADDR_BROADCAST, SO_BROADCAST and > IP_ONESBCAST was set. > sendto(): Network is unreachable > > 6. With default gateway, ip_dst = INADDR_BROADCAST, SO_BROADCAST was set > (without IP_ONESBCAST). > I have a datagram with ip_dst = 255.255.255.255 and gateway's MAC as > destination ethernet address. > > 7. With default gateway, ip_dst = 172.21.81.255, SO_BROADCAST was set > (without IP_ONESBCAST). > I have a datagram with ip_dst = 172.21.81.255 and broadcast destination > ethernet address. > > 8. With default gateway, ip_dst = 172.21.81.255, SO_BROADCAST and > IP_ONESBCAST was set. > I have a datagram with ip_dst = 255.255.255.255 and broadcast > destination ethernet address. > > So, i think tests #4, #5 and #6 is incorrect, but maybe this is by design? There may be a couple of bugs in the broadcast code and I have to look at the standards to find out what the expected behavior should is. #4 and #5 is correct however. When specifying IP_ONESBCAST you must supply a valid subnet broadcast address and INADDR_BROADCAST is not one of them. #3 and #6 are certainly not correct and I will look into fixing them as well. The important message here is that the fix IP_ONESBCAST works as intended. So I'm going to commit it to -current with a MFC date in a few days. -- Andre
State Changed From-To: feedback->patched The patch has been committed to -current today. MFC after 3 days to 6-stable.
Responsible Changed From-To: bms->andre Take over.
andre 2006-10-06 20:26:06 UTC FreeBSD src repository Modified files: (Branch: RELENG_6) sys/net if.c if_var.h sys/netinet ip_output.c raw_ip.c udp_usrreq.c Log: MFC: - Fix the socket option IP_ONESBCAST by giving it its own case in ip_output() and skip over the normal IP processing. - Add a supporting function ifa_ifwithbroadaddr() to verify and validate the supplied subnet broadcast address. - Check inp_flags instead of inp_vflag for INP_ONESBCAST flag. PR: kern/99558 Approved by: re (kensmith) Revision Changes Path 1.234.2.17 +27 -0 src/sys/net/if.c 1.98.2.6 +1 -0 src/sys/net/if_var.h 1.242.2.15 +11 -2 src/sys/netinet/ip_output.c 1.150.2.5 +1 -1 src/sys/netinet/raw_ip.c 1.175.2.8 +2 -2 src/sys/netinet/udp_usrreq.c _______________________________________________ cvs-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/cvs-all To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
Hi, Andre. Sorry to bug you, but there appears to be a small problem with this patch to ip_output.c (RELENG_6 1.242.2.15). In the previous version, the IP_SENDONES flag is tested only if ifbroadcast is set. In the new version, if IP_SENDONES is set, the destination is unconditionally set to INADDR_BROADCAST. As a result, it appears that -all- unicast packets sent on a IP_SENDONES socket are affected and result in ENETUNREACH. Attached to this message is a small change I made which appears to fix this. Could you please review it? Thanks! -- Ryan Beasley <ryanb@FreeBSD.org>
Ryan Beasley wrote: > In the previous version, the IP_SENDONES flag is tested only if > ifbroadcast is set. In the new version, if IP_SENDONES is set, the > destination is unconditionally set to INADDR_BROADCAST. As a result, it > appears that -all- unicast packets sent on a IP_SENDONES socket are > affected and result in ENETUNREACH. Er, please excuse me. :) I mean to say that if IP_ONESBCAST / IP_SENDONES is set, then all packets follow the same branch, where non-broadcasts end up discarded w/ ENETUNREACH. (When I first wrote that paragraph a few hours ago, before I attempted a patch, I misunderstood the block which tests the destination address for broadcasting.) -- Ryan Beasley <ryanb@FreeBSD.org>
Responsible Changed From-To: andre->bms andre@ fixed the original bug (thanks!) but ryan@ raises the issue that IP_ONESBCAST can't just be left set on a socket w/o affecting normal traffic. It was never intended to be used in this way, and the best way to deal with this is probably to update the documentation in ip(4). In future we'd hope to get rid of IP_ONESBCAST when we have an opportunity to refactor the FIB.
State Changed From-To: patched->closed The fix was MFCed, however I have pending work related to this in p4.
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=3b281d1421a78b588c5fc4182009ce62d8823d95 commit 3b281d1421a78b588c5fc4182009ce62d8823d95 Author: Gleb Smirnoff <glebius@FreeBSD.org> AuthorDate: 2025-02-22 02:11:00 +0000 Commit: Gleb Smirnoff <glebius@FreeBSD.org> CommitDate: 2025-02-22 02:11:00 +0000 netinet: enforce broadcast mode for all-ones and all-zeroes destinations When a socket has SO_BROADCAST set and destination address is INADDR_ANY or INADDR_BROADCAST, the kernel shall pick up first broadcast capable interface and broadcast the packet out of it. Since this API is not reliable on a machine with > 1 broadcast capable interfaces, all practical software seems to use IP_ONESBCAST or other mechanisms to send broadcasts. This has been broken at least since FreeBSD 6.0, see bug 99558. Back then the problem was in the fact that in_broadcast() check was always done against the gateway address, not the destination address. Later, with 90cc51a1ab4be, a second problem piled on top - we aren't checking for INADDR_ANY and INADDR_BROADCAST at all. Better late than never, fix that by checking destination address. PR: 99558 Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D49042 sys/netinet/in.h | 7 +++++++ sys/netinet/ip_output.c | 15 ++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-)