tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

receiving all-one broadcasts from INADDR_ANY

I'm tracking down a weird problem (on a self-written Captive Portal including 
a DHCP server) which works on -6, but doesn't on -8.

It seems to boil down to being unable to receive an UDP packet sent from 
the Unspecified Address to the all-one address in case it gets redirected 
by a NAT rdr rule. If I send from/to a unicast address, it works (I'm unable 
to test changing only the source or only the destination address). If I 
don't rdr, it works. On -6 it work with rdr and all-one.

Am I doing anything wrong?

I've got these rules in ipnat.conf (or not in the working case):
rdr vlan14 port 67 -> port 7641 udp
rdr vlan14 port 67 -> port 7641 udp

where is the server's address on vlan14 (of course, I have 
adapted local addresses on the other server)

I've these rules in ipf.conf:
pass in on vlan14 proto udp from any to any port=bootps
pass in on vlan14 proto udp from any to any port=7641

and use the attached progam for testing (changing the port number from 
67 to 7641).

Is this a regression between -6 and -8? Am I doing something that worked 
only by accident?

As I learnt I can tell dhcpd to listen ony on a sub-set of interfaces by 
specifying them on the command line, I probably can drop the rdr rule, 
but nevertheless would like to know what the problem is.
#include <err.h>
#include <unistd.h>
#include <stdio.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void) {
	int s;
	struct sockaddr_in sa;
	ssize_t len;
	char buf[1024];
        socklen_t sa_len;
	int one = 1;

	if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) err(1, "socket");
	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) == -1) err(1, "setsockopt(broadcast)");
	if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) == -1) err(1, "setsockopt(reuseport)");
	bzero(&sa, sizeof(sa));
	sa.sin_len = sizeof(sa);
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = INADDR_ANY;
	sa.sin_port = htons(67);
	if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) == -1) err(1, "bind");
	bzero(&sa, sizeof(sa));
	sa_len = sizeof(sa);
	if ((len = recvfrom(s, &buf, sizeof(buf), 0, (struct sockaddr *)&sa, &sa_len)) == -1) err(1, "recvfrom");
	printf("%d\n", len);

Home | Main Index | Thread Index | Old Index