Date: Fri, 30 Jun 2006 12:22:33 +0200 From: Andre Oppermann <andre@freebsd.org> To: "Andrey V. Elsukov" <bu7cher@yandex.ru> Cc: Robert Watson <rwatson@FreeBSD.org>, freebsd-bugs@FreeBSD.org, Gleb Smirnoff <glebius@FreeBSD.org>, Bruce M Simpson <bms@FreeBSD.org>, citrin@citrin.ru Subject: Re: kern/99558: FreeBSD 6.1 can't send packets to INADDR_BROADCAST Message-ID: <44A4FB69.1070609@freebsd.org> In-Reply-To: <44A36B44.1030100@yandex.ru> References: <200606282026.k5SKQF76000393@freefall.freebsd.org> <44A36B44.1030100@yandex.ru>
next in thread | previous in thread | raw e-mail | index | archive | help
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 ..$...@.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 ......@..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..@..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 ......@.....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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?44A4FB69.1070609>