Skip site navigation (1)Skip section navigation (2)
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>