UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » Networking
  • » UDP socket bind to specific IP does not receive broadcast on Linux

#1 2008-11-12 06:59 PM

mc_hotmail
Member
Registered: 2008-11-12
Posts: 5

Re: UDP socket bind to specific IP does not receive broadcast on Linux

Hi,

While replying to another thread "bind() vs connect() ...", I came up with the following program.  Compile it with command "gcc -g bcast.c -o bcast" on Linux.  This program can act as a client when run with a dash as its parameter

    bcast -

To run as a server that bind to INADDR_ANY:

    bcast

or run as a server that bind to the specific IP address of the network card:

    bcast 192.168.0.1

What I don't understand is if the server is bind to INADDR_ANY, it can receive broadcast from anyone, including the broadcast "Hello" message from itself.  If it is bind to a specific IP address, it can NOT receive any broadcast packet.

Anyone knows why?  It seems to be an intentional rule in the Linux kernel.  This program always works on Windows, regardless whether the server address is bind to INADDR_ANY or specific IP.

Thanks

--MC

/* bcast.c */

#ifdef WIN32
# include <winsock2.h>
# include <io.h>
# define  socklen_t int
# define  sockopt_t char
#else
# include <netdb.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/time.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <unistd.h>
# include <time.h>
# define  sockopt_t int
#endif

#define PORT 2080
 
int main(int argc, char *argv[])
{
	int sockfd;
	char buf[30];
	struct sockaddr_in sendaddr;
	struct sockaddr_in recvaddr;
	int numbytes;
	socklen_t addr_len;
	int broadcast=1;

	if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
		perror("socket");
		exit(1);
	}
	if ((setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
			&broadcast, sizeof broadcast)) == -1) {
		perror("setsockopt - SO_SOCKET ");
		exit(1);
	}
	printf("Socket created\n");

	memset(&sendaddr, 0, sizeof sendaddr);
	sendaddr.sin_family = AF_INET;
	sendaddr.sin_port = htons(PORT);
	sendaddr.sin_addr.s_addr = INADDR_BROADCAST;

	if (argc > 1 && argv[1][0] == '-') { /* Broadcast as client */
		time_t now = time(NULL);
		numbytes = sendto(sockfd, ctime(&now), 24, 0,
				(struct sockaddr *)&sendaddr, sizeof sendaddr);
		printf("Broadcasted a packet: '%.*s'\n", 24, ctime(&now));
		exit(0);
	}

	memset(&recvaddr, 0, sizeof recvaddr);
	recvaddr.sin_family = AF_INET;
	recvaddr.sin_port = htons(PORT);
	recvaddr.sin_addr.s_addr = argc > 1 ? inet_addr(argv[1]) : INADDR_ANY;
	if (bind(sockfd, (struct sockaddr*)&recvaddr, sizeof recvaddr) == -1) {
		perror("bind");
		exit(1);
	}
	numbytes = sendto(sockfd, "Hello", 5 , 0,
			(struct sockaddr *)&sendaddr, sizeof sendaddr);

	for (;;) {
		int n;
		fd_set set;
		struct timeval time_500ms = { 0, 500*1000 };
		FD_ZERO(&set);
		FD_SET(sockfd, &set);

		n = select(sockfd+1, &set, NULL, NULL, &time_500ms);
		if (n < 0) {
			perror("select");
			break;
		}
		else if (n == 0) {
			printf("sleep(5)\n");
			sleep(5);
		}
		else if (!FD_ISSET(sockfd, &set)) {
			perror("FD_ISSET");
			break;
		}
		else {
			addr_len = sizeof sendaddr;
			if ((numbytes = recvfrom(sockfd, buf, sizeof buf, 0,
						(struct sockaddr *)&sendaddr, &addr_len)) > 0)
			{
				time_t now = time(NULL);
				printf("recvfrom: '%.*s' at %s\n", numbytes, buf, ctime(&now));
			}
			else
				perror("recvfrom");
		}
	}
	close(sockfd); 
	return 0;
}

Offline

#2 2008-11-12 11:32 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,826
Website

Re: UDP socket bind to specific IP does not receive broadcast on Linux

What I don't understand is if the server is bind to INADDR_ANY, it can receive broadcast from anyone, including the broadcast "Hello" message from itself. If it is bind to a specific IP address, it can NOT receive any broadcast packet.

That makes perfect sense to me and is what I'd expect...  When you bind to
INADDR_ANY, you are saying you are willing to accept traffic directed to any of your
local IPs/interfaces, but when you bind to a specific individual IP, you are saying you
only want traffic addressed to that IP...  And, while broadcast IPs are a bit special, it
still makes sense to me that a specific IP-bound socket wouldn't get broadcast
packets, since the destination IP doesn't match what you bound to...  If you really
only wanted to receive broadcasts from a specific network interface, you could use
setsockopt(SO_BINDTODEVICE) instead, and still bind() to INADDR_ANY...

But, this is likely one of those system-specific behaviors (of which there are a great
many ;-)), so I'm not surprised it behaves differently elsewhere...  (Nevermind the
fact that the elsewhere is Windoze, which has about as non-standard (and, by that
I mean, non-Unix) behavior as you can get... ;-)  I'd be more curious how BSD and
other real OS's behave...  But, even if they differ, that doesn't make one way or the
other "right", really...  Just yet another system-dependent behavior...)

Offline

#3 2008-11-13 04:57 AM

mc_hotmail
Member
Registered: 2008-11-12
Posts: 5

Re: UDP socket bind to specific IP does not receive broadcast on Linux

Rob,

The issue in doubt is what does it mean when a server binds to an IP address other than INADDR_ANY.  Your understanding is it means the server is only willing to accept packet addressed to that IP address, which would exclude broadcast packet.

My understanding of a server binding to an IP address is that it wants to receive traffics coming from that network interface, which would include broadcast packets coming from that interface.

It is the kernel's job to accept or ignore packets come from a network interface.  Since the kernel already accepted the broadcast packet from that network card, why then choose not to deliver it to the server listening on that IP address.  That does not seem intuitive to me.

I agree it may not be a right or wrong way to see this issue.  Although if there is a known standard the Linux kernel follows, I am interested to know.

Thanks

--MC

Offline

#4 2008-11-13 02:29 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,826
Website

Re: UDP socket bind to specific IP does not receive broadcast on Linux

My understanding of a server binding to an IP address is that it wants to receive traffics coming from that network interface, which would include broadcast packets coming from that interface.

Well, if that were there case, then there would be absolutely no point to having the
SO_BINDTODEVICE sockopt, would there?  We like to think of IPs and interfaces
having a one-to-one relationship, but that's really not necessarily true...  In fact, it's
quite easy to give a single interface multiple real IPs...  And, if you bound to only one
of those, are you going to say it's sensible for the kernel to deliver to you traffic that
is destined to one of the other IPs assigned to that interface?  I sure would hope it
doesn't do that...  Otherwise, it pretty much completely defeats the point of having the
separate IPs in the first place, which is to subdivide the interface into multiple distinctly
addressible spaces...  Ie: just because all traffic at the link layer (Ethernet) is tied
one-to-one with an interface, doesn't mean all traffic at the network layer (IP) needs to
necessarily be...

Of course, like I say, broadcast addresses are a bit special though, so I could see
some logic in wanting this behavior just for that...  In theory, by broadcasting, you're
saying everyone should get it, regardless of IP...  So, I could certainly see the sense
in a system passing broadcasts to apps bound only to specific (non-broadcast) IPs...
But, on the other hand, I can see the sense in another system NOT doing so, as
well...  It's one of those judgement call behaviors, which I don't think are clearly
defined in any standard anywhere, so everyone just sort of does what they feel
makes the most sense... *shrug*

Offline

#5 2008-11-15 05:01 PM

mc_hotmail
Member
Registered: 2008-11-12
Posts: 5

Re: UDP socket bind to specific IP does not receive broadcast on Linux

Rob,

I can argue this with SO_BROADCAST. If you allow a socket bind to a specific IP to receive broadcast if and only if that socket's SO_BROADCAST option is set, then we don't even need the SO_BINDTODEVICE option.

I believe guys in Microsoft thought this through and decided to do just that. "If you enable broadcast on the socket, you get broadcast packets sent to INADDR_ANY, period."  Less and more.

I just have to live with a few more lines of code just for Linux in my program, knowing that many more lines in the Linux kernel could have been eliminated as well.

Thanks for the discussion.

--MC

Offline

#6 2009-08-06 10:42 AM

searockcliff
Guest

Re: UDP socket bind to specific IP does not receive broadcast on Linux

I cannot work it out even I set the SO_BROADCAST flag.

What's your solution?

Socket bind to a specific ip address cannot receive broadcast udp packet.

#7 2009-08-06 05:27 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,230

Re: UDP socket bind to specific IP does not receive broadcast on Linux

Bind to INADDR_ANY and use SO_BINDTODEVICE instead.

Offline

#8 2009-08-13 04:58 AM

mc_hotmail
Member
Registered: 2008-11-12
Posts: 5

Re: UDP socket bind to specific IP does not receive broadcast on Linux

You need to be root to set SO_BINDTODEVICE on Linux. --MC

Offline

#9 2012-12-15 12:50 AM

dashesy
Member
Registered: 2012-12-15
Posts: 1

Re: UDP socket bind to specific IP does not receive broadcast on Linux

Just wanted to thank all of you in this discussion, I could not find better answer anywhere else.
At the end in my case I decided to bind to .255 broadcast address on Linux systems.

Offline

#10 2014-01-31 11:51 AM

Vishal
Guest

Re: UDP socket bind to specific IP does not receive broadcast on Linux

I am using ___SO_BROADCAST ___ option to broadcast udp packets to broadcast IP .255 but packets are sent via WAN interface but i want them to go to LAN interface. Is there is any way to acheive this.

#11 2014-01-31 01:31 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,826
Website

Re: UDP socket bind to specific IP does not receive broadcast on Linux

By ".255", I assume you mean the limited broadcast 255.255.255.255?  If so, then just use the actual subnet broadcast for the appropriate network associated with the LAN instead...  Eg: say your WAN subnet is 10.0.1.0/24 and your LAN is 10.0.2.0/24, then direct your broadcast packets at IP 10.0.2.255 instead of 255.255.255.255...

Offline

#12 2014-01-31 01:47 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,230

Re: UDP socket bind to specific IP does not receive broadcast on Linux

What are your WAN and LAN IP addresses, and what broadcast address do you use?
If you use 255.255.255.255 the default route will be used. If your LAN IP address is
10.0.0.1 with a netmask of 255.255.0.0, then you can broadcast on 10.0.255.255.

Edit: Rob was faster...

Last edited by i3839 (2014-01-31 01:48 PM)

Offline

  • Index
  • » Networking
  • » UDP socket bind to specific IP does not receive broadcast on Linux

Board footer

Powered by FluxBB