kern/99558: FreeBSD 6.1 can't send packets to INADDR_BROADCAST
Andre Oppermann
andre at freebsd.org
Fri Jun 30 10:22:28 UTC 2006
Andrey V. Elsukov wrote:
> Bruce M Simpson wrote:
>> 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.
>>
>> http://www.freebsd.org/cgi/query-pr.cgi?pr=99558
>
> Ok. I've tested 5.4-STABLE.
> Without IP_ONESBCAST:
> 09:24:50.293393 IP 10.0.0.4.5000 > 10.0.7.255.5000: UDP, length: 4
> 0x0000: ffff ffff ffff 0007 e909 d5b3 0800 4500 ..............E.
> 0x0010: 0020 24d7 0000 4011 39f4 0a00 0004 0a00 ..$... at .9.......
> 0x0020: 07ff 1388 1388 000c 1c20 7465 7374 ..........test
>
> With IP_ONESBCAST:
> 09:28:08.275418 IP 10.0.0.4.54715 > 255.255.255.255.5000: UDP,length:4
> 0x0000: ffff ffff ffff 0007 e909 d5b3 0800 4500 ..............E.
> 0x0010: 0020 8987 0000 4011 e742 0a00 0004 ffff ...... at ..B......
> 0x0020: ffff d5bb 1388 000c 0a21 7465 7374 .........!test
>
> In result we have difference only in IP destination address.
> I want to pay attention that a Ethernet destination address is a
> ethernet broadcast!
>
> Now for 6.1-STABLE. Without IP_ONESBCAST:
> 10:43:15.384080 IP 172.21.81.19.58298 > 255.255.255.255.5000: UDP, length 4
> 0x0000: 0011 936b 3c91 0080 4819 86df 0800 4500 ...k<...H.....E.
> 0x0010: 0020 a670 0000 4011 d734 ac15 5113 ffff ...p.. at ..4..Q...
> 0x0020: ffff e3ba 1388 000c 2391 7465 7374 0000 ........#.test..
> 0x0030: 0000 0000 0000 0000 0000 0000 ............
>
> With IP_ONESBCAST:
> 10:44:20.320314 IP 172.21.81.19.53276 > 255.255.255.255.5000: UDP, length 4
> 0x0000: 0011 936b 3c91 0080 4819 86df 0800 4500 ...k<...H.....E.
> 0x0010: 0020 a998 0000 4011 d40c ac15 5113 ffff ...... at .....Q...
> 0x0020: ffff d01c 1388 000c 372f 7465 7374 0000 ........7/test..
> 0x0030: 0000 0000 0000 0000 0000 0000 ............
>
> In result we have an identical datagrams with *incorrect* ethernet
> destination addresses. When my system don't have default route, he
> can not send broadcast. I've got error message "sendto(): Network is
> unreachable"!
The attached patch should fix the problem with SENDONES (untested).
--
Andre
Index: net/if.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.259
diff -u -p -r1.259 if.c
--- net/if.c 21 Jun 2006 06:02:35 -0000 1.259
+++ net/if.c 30 Jun 2006 10:20:19 -0000
@@ -1007,6 +1007,33 @@ done:
}
/*
+ * Locate an interface based on the broadcast address.
+ */
+/* ARGSUSED */
+struct ifaddr *
+ifa_ifwithbroadaddr(struct sockaddr *addr)
+{
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifp, &ifnet, if_link)
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (ifa->ifa_addr->sa_family != addr->sa_family)
+ continue;
+ if ((ifp->if_flags & IFF_BROADCAST) &&
+ ifa->ifa_broadaddr &&
+ ifa->ifa_broadaddr->sa_len != 0 &&
+ sa_equal(ifa->ifa_broadaddr, addr))
+ goto done;
+ }
+ ifa = NULL;
+done:
+ IFNET_RUNLOCK();
+ return (ifa);
+}
+
+/*
* Locate the point to point interface with a given destination address.
*/
/*ARGSUSED*/
Index: net/if_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_var.h,v
retrieving revision 1.107
diff -u -p -r1.107 if_var.h
--- net/if_var.h 19 Jun 2006 22:20:44 -0000 1.107
+++ net/if_var.h 30 Jun 2006 10:20:19 -0000
@@ -682,6 +682,7 @@ int ifpromisc(struct ifnet *, int);
struct ifnet *ifunit(const char *);
struct ifaddr *ifa_ifwithaddr(struct sockaddr *);
+struct ifaddr *ifa_ifwithbroadaddr(struct sockaddr *);
struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *);
struct ifaddr *ifa_ifwithnet(struct sockaddr *);
struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *);
Index: netinet/ip_output.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.257
diff -u -p -r1.257 ip_output.c
--- netinet/ip_output.c 21 May 2006 17:52:08 -0000 1.257
+++ netinet/ip_output.c 30 Jun 2006 10:20:20 -0000
@@ -198,6 +198,15 @@ again:
ifp = ia->ia_ifp;
ip->ip_ttl = 1;
isbroadcast = in_broadcast(dst->sin_addr, ifp);
+ } else if (flags & IP_SENDONES) {
+ if ((ia = ifatoia(ifa_ifwithbroadaddr(sintosa(dst)))) == NULL) {
+ ipstat.ips_noroute++;
+ error = ENETUNREACH;
+ goto bad;
+ }
+ ifp = ia->ia_ifp;
+ ip->ip_dst.s_addr = INADDR_BROADCAST;
+ isbroadcast = 1;
} else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
imo != NULL && imo->imo_multicast_ifp != NULL) {
/*
@@ -381,8 +390,6 @@ again:
error = EMSGSIZE;
goto bad;
}
- if (flags & IP_SENDONES)
- ip->ip_dst.s_addr = INADDR_BROADCAST;
m->m_flags |= M_BCAST;
} else {
m->m_flags &= ~M_BCAST;
More information about the freebsd-bugs
mailing list