Different behavior of ping'ing INADDR_BROADCAST?

Eygene Ryabinkin rea-fbsd at codelabs.ru
Fri Jan 5 08:20:32 PST 2007


I am CC'ing this message to Gleb Smirnov. Gleb, my apologies if you're
not interested in this stuff.

> When FBSD is pinging 0xffffffff it does not use the Ethernet broadcasts,
> when the link-level destination MAC is set to 0xffffffffffff, using some
> 'known MAC' instead. For the network broadcast address -- it does use
> link-level broadcasts.
> 
> For me the 'known MAC' is that of our border router that serves as
> the default destination. And my box doing the ARP request for the
> precisely the IP of the router before pinging 255.255.255.255. You can
> try to empty your ARP table and then ping 255.255.255.255 watching
> for the ARP requests and the link-level header of the ICMP packets.

OK, I've found that in order to ping undirected broadcast address
one should add some functionality to the 'ping' utility.

The explanation of the behaviour you notes is the following: when
ping is requesting 255.255.255.255 as the destination the IP layer
does the lookup the route for the 255.255.255.255. In my case the
route lookup yielded 'default destination'. And the code in the
/sys/netinet/ip_output.c do no checks for the broadcast address if
the looked up destination is the gateway (lines 257-258 in the
revision 1.242.2.17). So the packet was not recognised as the
broadcast and was sent with the destination MAC of the gateway.
Our gateway responds to such packets. Your probably responds too.

> > Just curious why there is such difference.  Literally, I think
> > INADDR_BROADCAST is supposed to reach local network nodes, no?

Yes, the appendix II of the STD0005 (RFC 791) specifies that it
is the case: the packet should go to all hosts 'on the wire'.

I've prepared the patch for the ping (RELENG-6, 6.2-PRERELEASE) that
adds '-b' option that permits to ping to 255.255.255.255. An argument
to '-b' specifies the broadcast address of the interface that will
be used for the transmission. If you're interested, please, test the
patch. I see one caveat now: no Linux stations respond to my
pings with '-b' option. I will try to see why, but later.

One use-case for the '-b' is the following: suppose you're on the
unknown network in which you know some IPs, but the netmask is not
known or you see the errorneous netmask. Then setting the netmask
to some value and pinging to the resulting network broadcast will
not reveal hosts in the local network. But using '-b' with the
resulting network broadcast address and the 255.255.255.255 as the
destination will do the work.
-- 
Eygene
-------------- next part --------------
--- /usr/src/sbin/ping/ping.c.orig	Fri Jan  5 17:11:24 2007
+++ /usr/src/sbin/ping/ping.c	Fri Jan  5 18:48:54 2007
@@ -144,6 +144,7 @@
 #define	F_TIME		0x100000
 #define	F_SWEEP		0x200000
 #define	F_WAITTIME	0x400000
+#define F_BIF		0x800000
 
 /*
  * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@@ -219,7 +220,7 @@
 	char *const *argv;
 {
 	struct sockaddr_in from, sock_in;
-	struct in_addr ifaddr;
+	struct in_addr ifaddr, bifaddr;
 	struct timeval last, intvl;
 	struct iovec iov;
 	struct ip *ip;
@@ -264,7 +265,7 @@
 
 	outpack = outpackhdr + sizeof(struct ip);
 	while ((ch = getopt(argc, argv,
-		"Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:"
+		"Aab:c:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:"
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
 		"P:"
@@ -279,6 +280,13 @@
 		case 'a':
 			options |= F_AUDIBLE;
 			break;
+		case 'b':
+			if (inet_aton(optarg, &bifaddr) == 0)
+				errx(EX_USAGE,
+				    "invalid broadcast interface: `%s'",
+				    optarg);
+			options |= F_BIF;
+			break;
 		case 'c':
 			ultmp = strtoul(optarg, &ep, 0);
 			if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp)
@@ -584,6 +592,8 @@
 	    && !IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
 		errx(EX_USAGE,
 		    "-I, -L, -T flags cannot be used with unicast destination");
+	if ((options & F_MIF) && (options & F_BIF))
+		errx(EX_USAGE, "-b and -I: incompatible options");
 
 	if (datalen >= TIMEVAL_LEN)	/* can we time transfer */
 		timing = 1;
@@ -605,6 +615,21 @@
 	if (options & F_SO_DONTROUTE)
 		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
 		    sizeof(hold));
+	if (to->sin_addr.s_addr == INADDR_BROADCAST) {
+		if ((options & F_BIF) == 0) {
+			errx(EX_USAGE,
+			    "Broadcast ping requested, but '-b' option was not given");
+		}
+		/* Should instruct IP stack to use broadcast destination. */
+		if (setsockopt(s, IPPROTO_IP, IP_ONESBCAST, (char *)&hold,
+		    sizeof(hold)) < 0) {
+			errx(EX_OSERR,
+			    "setsockopt(IPPROTO_IP, IP_ONESBCAST) failed");
+		}
+		bcopy(&bifaddr, &(whereto.sin_addr), sizeof(whereto.sin_addr));
+		printf("WARNING: will ping to broadcast address using %s.\n",
+		    inet_ntoa(bifaddr));
+	}
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
 	if (options & F_POLICY) {
--- /usr/src/sbin/ping/ping.8.orig	Fri Jan  5 18:48:10 2007
+++ /usr/src/sbin/ping/ping.8	Fri Jan  5 18:55:50 2007
@@ -39,6 +39,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl AaDdfnoQqRrv
+.Op Fl b Ar bcastaddr
 .Op Fl c Ar count
 .Op Fl G Ar sweepmaxsize
 .Op Fl g Ar sweepminsize
@@ -112,6 +113,12 @@
 character in the output when any packet is received.
 This option is ignored
 if other format options are present.
+.It Fl b Ar bcastaddr
+Ping to the broadcast address (255.255.255.255). Argument
+.Ar bcastaddr
+specifies the broadcast address of the interface that will be
+used for transmission. This option is mutually exclusive with
+.Fl I .
 .It Fl c Ar count
 Stop after sending
 (and receiving)
@@ -165,6 +172,8 @@
 .It Fl I Ar iface
 Source multicast packets with the given interface address.
 This flag only applies if the ping destination is a multicast address.
+This option is mutually exclusive with
+.Fl b .
 .It Fl i Ar wait
 Wait
 .Ar wait


More information about the freebsd-net mailing list