Re: message too long when sending broadcasts

2005-11-21 Thread Michael Voucko

 Berkeley-derived kernels do not allow a broadcast datagram to be
 fragmented. If the size of an IP datagram that is being sent to a
 broadcast address exceeds the outgoing interface MTU, EMSGSIZE is
 returned (pp. 233?234 of TCPv2). This is a policy decision that has
 existed since 4.2BSD. There is nothing that prevents a kernel from
 fragmenting a broadcast datagram, but the feeling is that broadcasting
 puts enough load on the network as it is, so there is no need to
 multiply this load by the number of fragments.  AIX, FreeBSD, and
 MacOS implement this limitation. Linux, Solaris, and HP-UX fragment
 datagrams sent to a broadcast address.

 Maybe it's worth adding this information somewhere to make it easier
 to find?

 It would also be quite easy to make this configurable -- the code in
 ip_output is fairly straight forward:

 /*
  * Look for broadcast address and
  * verify user is allowed to send
  * such a packet.
  */
 if (isbroadcast) {
 if ((ifp-if_flags  IFF_BROADCAST) == 0) {
 error = EADDRNOTAVAIL;
 goto bad;
 }
 if ((flags  IP_ALLOWBROADCAST) == 0) {
 error = EACCES;
 goto bad;
 }
 /* don't allow broadcast messages to be fragmented */
 if (ip-ip_len  ifp-if_mtu) {
 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;
 }

 We could add a global option, or maybe just an IP socket option.

I had quite a hard time to find this peace of information which makes me think 
that there aren't too many other application suffering from the inability to 
fragment?!
But if there will be setsockopt option for this feature, I'm happy to test it 
with heartbeat.


 Michael
___
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: message too long when sending broadcasts

2005-11-20 Thread Robert Watson


On Sun, 20 Nov 2005, Michael Voucko wrote:



Berkeley-derived kernels do not allow a broadcast datagram to be 
fragmented. If the size of an IP datagram that is being sent to a 
broadcast address exceeds the outgoing interface MTU, EMSGSIZE is 
returned (pp. 233?234 of TCPv2). This is a policy decision that has 
existed since 4.2BSD. There is nothing that prevents a kernel from 
fragmenting a broadcast datagram, but the feeling is that broadcasting 
puts enough load on the network as it is, so there is no need to 
multiply this load by the number of fragments.  AIX, FreeBSD, and 
MacOS implement this limitation. Linux, Solaris, and HP-UX fragment 
datagrams sent to a broadcast address.


Maybe it's worth adding this information somewhere to make it easier to 
find?


It would also be quite easy to make this configurable -- the code in 
ip_output is fairly straight forward:


/*
 * Look for broadcast address and
 * verify user is allowed to send
 * such a packet.
 */
if (isbroadcast) {
if ((ifp-if_flags  IFF_BROADCAST) == 0) {
error = EADDRNOTAVAIL;
goto bad;
}
if ((flags  IP_ALLOWBROADCAST) == 0) {
error = EACCES;
goto bad;
}
/* don't allow broadcast messages to be fragmented */
if (ip-ip_len  ifp-if_mtu) {
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;
}

We could add a global option, or maybe just an IP socket option.

Robert N M Watson
___
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: message too long when sending broadcasts

2005-11-19 Thread Doug White
On Wed, 16 Nov 2005, Michael Voucko wrote:

 Hi,

 I'm trying to install the latest version of heartbeat (linux-ha), which
 unfortunately is not available from the ports tree yet.
 Setup is two boxes running (5.4-STABLE FreeBSD from Oct 17 2005) both 
 connected
 to a hub with lnc NICs on a private 10.0.0.0/24 subnet (actually its only a
 'simulated hub' provided by VMWare if this matters).

 After some initial struggles configuration, build and installations works as
 expected - but now the most basic parts of this application won't work 
 anymore.
 When trying to use UDP broadcast messages for the heartbeat it would error out
 with Message too long for packets larger than 1472 bytes, in other words as
 soon as fragmentation of the package would be necessary (MTU is 1500).

 I received a code snippet from the heartbeat developers to isolate the problem
 (create sender and receiver socket, send broadcast packets of a certain size).
 To rule out VMware as the basic problem I tried real boxes but the problem
 persists.

 Is there any size restriction for UDP broadcast messages?
 Is there anything which prevents UDP broadcast from being fragmented?

 I searched RFCs, man pages for socket, setsockopt, ioctl, sendto and other
 places but did not find anything that could explain the behaviour (which seems
 to be no problem on other OS).

 Any pointers, comments?

From sendmsg(2):

 The address of the target is given by to with tolen specifying its size.
 The length of the message is given by len.  If the message is too long to
 pass atomically through the underlying protocol, the error EMSGSIZE is
 returned, and the message is not transmitted.

I remember debugging some funky behavior regarding fragmenting packets and
UDPv6 some time ago. I don't remember if a fix was committed or not.

-- 
Doug White|  FreeBSD: The Power to Serve
[EMAIL PROTECTED]  |  www.FreeBSD.org
___
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: message too long when sending broadcasts

2005-11-19 Thread Michael Voucko

I'm trying to install the latest version of heartbeat (linux-ha), which
unfortunately is not available from the ports tree yet.
Setup is two boxes running (5.4-STABLE FreeBSD from Oct 17 2005) both connected
to a hub with lnc NICs on a private 10.0.0.0/24 subnet (actually its only a
'simulated hub' provided by VMWare if this matters).

After some initial struggles configuration, build and installations works as
expected - but now the most basic parts of this application won't work anymore.
When trying to use UDP broadcast messages for the heartbeat it would error out
with Message too long for packets larger than 1472 bytes, in other words as
soon as fragmentation of the package would be necessary (MTU is 1500).

I received a code snippet from the heartbeat developers to isolate the problem
(create sender and receiver socket, send broadcast packets of a certain size).
To rule out VMware as the basic problem I tried real boxes but the problem
persists.

Is there any size restriction for UDP broadcast messages?
Is there anything which prevents UDP broadcast from being fragmented?

I searched RFCs, man pages for socket, setsockopt, ioctl, sendto and other
places but did not find anything that could explain the behaviour (which seems
to be no problem on other OS).

Any pointers, comments?




From sendmsg(2):


 The address of the target is given by to with tolen specifying its size.
 The length of the message is given by len.  If the message is too long to
 pass atomically through the underlying protocol, the error EMSGSIZE is
 returned, and the message is not transmitted.

I remember debugging some funky behavior regarding fragmenting packets and
UDPv6 some time ago. I don't remember if a fix was committed or not.


In the meantime I found the explaination.

Taken from
W. Richard Stevens
Unix Network Programming - Vol 1 - 3rd Edition: The Sockets Networking API

20.4 dg_cli Function Using Broadcasting
..
IP Fragmentation and Broadcasts

Berkeley-derived kernels do not allow a broadcast datagram to be fragmented.
If the size of an IP datagram that is being sent to a broadcast address exceeds
the outgoing interface MTU, EMSGSIZE is returned (pp. 233–234 of TCPv2).
This is a policy decision that has existed since 4.2BSD. There is nothing that
prevents a kernel from fragmenting a broadcast datagram, but the feeling is
that broadcasting puts enough load on the network as it is, so there is no need
to multiply this load by the number of fragments.

AIX, FreeBSD, and MacOS implement this limitation. Linux, Solaris, and HP-UX
fragment datagrams sent to a broadcast address.

Maybe it's worth adding this information somewhere to make it easier to find?

Michael
___
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to [EMAIL PROTECTED]


message too long when sending broadcasts

2005-11-16 Thread Michael Voucko

Hi,

I'm trying to install the latest version of heartbeat (linux-ha), which 
unfortunately is not available from the ports tree yet.
Setup is two boxes running (5.4-STABLE FreeBSD from Oct 17 2005) both connected 
to a hub with lnc NICs on a private 10.0.0.0/24 subnet (actually its only a 
'simulated hub' provided by VMWare if this matters).


After some initial struggles configuration, build and installations works as 
expected - but now the most basic parts of this application won't work anymore. 
When trying to use UDP broadcast messages for the heartbeat it would error out 
with Message too long for packets larger than 1472 bytes, in other words as 
soon as fragmentation of the package would be necessary (MTU is 1500).


I received a code snippet from the heartbeat developers to isolate the problem 
(create sender and receiver socket, send broadcast packets of a certain size). 
To rule out VMware as the basic problem I tried real boxes but the problem 
persists.


Is there any size restriction for UDP broadcast messages?
Is there anything which prevents UDP broadcast from being fragmented?

I searched RFCs, man pages for socket, setsockopt, ioctl, sendto and other 
places but did not find anything that could explain the behaviour (which seems 
to be no problem on other OS).


Any pointers, comments?

Thanks,
 Michael

N.B:
Code snippet is attached in case somebody cares to take a look - it works fine 
for me when using ./bcast-test -r -i lnc1 -p 1500 on the receiving box and

./bcast-test -r -i lnc1 -p XXX on the sending box for XXX  1473.
#include unistd.h
#include stdio.h
#include stdlib.h
#include sys/types.h
#include sys/socket.h
#include string.h
#include netinet/in.h
#include net/if.h
#include errno.h
#include sys/ioctl.h

#define PORT 694
#define MAXBUF 2048

void
usage(int argc, char ** argv)
{
printf(Usage: %s [-s] [-r] -p packetsize -i eth0/eth1/...\n, argv[0]);
printf(#default is to receive\n);
return;
}

int
create_recv_socket(char* ifname)
{
struct sockaddr_in my_addr;
int sockfd;
int one = 1;
struct ifreq i;


memset(my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (( sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
printf(Error getting socket: %s\n, strerror(errno));
exit(1);
}

if (setsockopt( sockfd, SOL_SOCKET,
SO_REUSEADDR, (const void*)one, sizeof(one))  0){
printf(Error setting socket option SO_REUSEADDR: %s\n,
   strerror(errno));
exit(1);
}

strcpy(i.ifr_name, ifname);

if (bind(sockfd, (struct sockaddr *)  my_addr, sizeof(struct sockaddr))
 0){
printf(Error binding socket: %s\n, strerror(errno));
exit(1);
}

return sockfd;
}


void
recv_packets(int sockfd, int packetsize)
{
int bufsize = packetsize + 100;
char buf[MAXBUF];
int n;
struct sockaddr_in theiraddr;
int len = sizeof(theiraddr);

while(1){

memset(buf, 0, MAXBUF);
if ((n = recvfrom(sockfd, buf, bufsize - 1, 0,
  (struct sockaddr*)theiraddr, len)) == -1){
printf(Error receiving from socket: %s\n, 
strerror(errno));
exit(1);
}
printf(Message received: (%d bytes)\n%s\n, n, buf);
}

}

int
create_send_socket(char* ifname)
{
int sockfd;
int one = 1;
struct ifreq i;
strcpy(i.ifr_name,ifname);

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) = 0) {
printf(Error in getting socket: %s, strerror(errno));
exit(1);
}


if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void*) one, 
sizeof(one)) == -1)
{
printf(Error setting socket option SO_BROADCAST: 
sockfd =%d , %s\n,
   sockfd, strerror(errno));
close(sockfd);
exit(1);
}

return sockfd;
}


int
get_baddr(struct sockaddr_in* baddr, char* ifname)
{
struct ifreq ifr;
int fd;
int return_val;

fd = socket (PF_INET, SOCK_DGRAM, 0);

if (fd 0) {
printf(Error opening socket: %s\n, strerror(errno));
exit(1);
}

strcpy (ifr.ifr_name, ifname);

return_val = ioctl(fd, SIOCGIFBRDADDR, ifr);
if (return_val == 0 )
{
if (ifr.ifr_broadaddr.sa_family == AF_INET)
{
struct sockaddr_in sin_ptr;
memcpy(sin_ptr, ifr.ifr_broadaddr,