public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS]  How to send UDP broadcast to 255.255.255.255?
@ 2009-06-15 17:42 Grant Edwards
  2009-06-15 20:36 ` Sergei Gavrikov
  2009-06-16  6:44 ` [ECOS] " Andrew Lunn
  0 siblings, 2 replies; 5+ messages in thread
From: Grant Edwards @ 2009-06-15 17:42 UTC (permalink / raw)
  To: ecos-discuss

I've been asked by one of my internal customers how to send a
UDP broadcast packet to IP address 255.255.255.255.

I tried setting the SO_BROADCAST option on the socket and then
using sendto() with a destination address of 255.255.255.255,
but it sends to the subnet broadcast address (in my case
10.255.255.255) not to the global broadcast address of
255.255.255.255 that I specified in the sendto() call.

The exact same code works fine on Linux (the destination
address in the packet on the wire is 255.255.255.255), so this
is apparently platform-dependent.  The code I'm using is shown
below.  I've tried it both with and without the "bind()" call,
and it does the same thing in both cases.

Any ideas?  Is this normal BSD stack behavior?  If so, on BSD
how does one send a global broadcast?


#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>

static void sendBroadcastUdp(void)
{
  int socket_fd;
  struct sockaddr_in encoder_addr;
  struct sockaddr_in my_addr;
  char send_buf[20];
  int broadcast=1;
  int packetSize = 5;
  int bytesSent;

  if ((socket_fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
    {
      diag_printf("socket() failed\n");
      return;
    }

  my_addr.sin_family = AF_INET;
  my_addr.sin_port = htons(12345);
  my_addr.sin_addr.s_addr = INADDR_ANY;
  memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);

  #if 0
  if (bind(socket_fd, (struct sockaddr *)&my_addr, sizeof my_addr))
    {
      diag_printf("bind() failed\n");
      close(socket_fd);
      return;
    }
  #endif

  //mark the socket for broadcasting

  if (setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast) == -1)
    {
      diag_printf("setsockopt (SO_BROADCAST) failed\n");
      close(socket_fd);
      return;
    }

  encoder_addr.sin_family = AF_INET;
  encoder_addr.sin_port = htons(12345);
  encoder_addr.sin_addr.s_addr = INADDR_BROADCAST;
  memset(encoder_addr.sin_zero, '\0', sizeof encoder_addr.sin_zero);

  if ((bytesSent = sendto(socket_fd, send_buf, packetSize, 0, (struct sockaddr *)&encoder_addr, sizeof encoder_addr)) == -1)
    {
      diag_printf("sendto() failed\n");
      close(socket_fd);
      return;
    }

  diag_printf("sent %d bytes to %s\n", bytesSent, inet_ntoa(encoder_addr.sin_addr));
  close(socket_fd);
}


-- 
Grant Edwards                   grante             Yow! I know th'MAMBO!!
                                  at               I have a TWO-TONE CHEMISTRY
                               visi.com            SET!!


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [ECOS]  How to send UDP broadcast to 255.255.255.255?
  2009-06-15 17:42 [ECOS] How to send UDP broadcast to 255.255.255.255? Grant Edwards
@ 2009-06-15 20:36 ` Sergei Gavrikov
  2009-06-15 22:14   ` [ECOS] " Grant Edwards
  2009-06-16  6:44 ` [ECOS] " Andrew Lunn
  1 sibling, 1 reply; 5+ messages in thread
From: Sergei Gavrikov @ 2009-06-15 20:36 UTC (permalink / raw)
  To: Grant Edwards; +Cc: ecos-discuss

Grant Edwards wrote:
> I've been asked by one of my internal customers how to send a
> UDP broadcast packet to IP address 255.255.255.255.
> 
> I tried setting the SO_BROADCAST option on the socket and then
> using sendto() with a destination address of 255.255.255.255,
> but it sends to the subnet broadcast address (in my case
> 10.255.255.255) not to the global broadcast address of
> 255.255.255.255 that I specified in the sendto() call.

[snip]

>   if ((bytesSent = sendto(socket_fd, send_buf, packetSize, 0, (struct sockaddr *)&encoder_addr, sizeof encoder_addr)) == -1)

Hi,

I noticed one thing only. What's about sendto's flags? they talk about
`MSG_DONTROUTE' sendto flag for your needs:

packages/net/tcpip/current/doc/sendto.html

perhaps, that's it.

Sergei

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [ECOS]  Re: How to send UDP broadcast to 255.255.255.255?
  2009-06-15 20:36 ` Sergei Gavrikov
@ 2009-06-15 22:14   ` Grant Edwards
  0 siblings, 0 replies; 5+ messages in thread
From: Grant Edwards @ 2009-06-15 22:14 UTC (permalink / raw)
  To: ecos-discuss

On 2009-06-15, Sergei Gavrikov <sergei.gavrikov@gmail.com> wrote:
> Grant Edwards wrote:
>> I've been asked by one of my internal customers how to send a
>> UDP broadcast packet to IP address 255.255.255.255.
>> 
>> I tried setting the SO_BROADCAST option on the socket and then
>> using sendto() with a destination address of 255.255.255.255,
>> but it sends to the subnet broadcast address (in my case
>> 10.255.255.255) not to the global broadcast address of
>> 255.255.255.255 that I specified in the sendto() call.
>
> [snip]
>
>>   if ((bytesSent = sendto(socket_fd, send_buf, packetSize, 0, (struct sockaddr *)&encoder_addr, sizeof encoder_addr)) == -1)
>
> Hi,
>
> I noticed one thing only. What's about sendto's flags? they talk about
> `MSG_DONTROUTE' sendto flag for your needs:
>
> packages/net/tcpip/current/doc/sendto.html
>
> perhaps, that's it.

I just tried it, and it doesn't change the behavior of
broadcasts. Specifying a destination address of 255.255.255.255
still produces a packet that's addressed to 10.255.255.255.

The description of MSG_DONTROUTE is

       Bypasses the usual routing table lookup and sends the
       packet directly to the interface described by the
       destination address. This is usually used only by
       diagnostic or routing programs.

In my case, the destination doesn't describe a particular
interface.  One might presume a broadcast sent to
255.255.255.255 would be sent out on all interfaces.
       
Google did find me a posting to a BSD mailing list that seemed
to claim that the option IP_ONESBCAST would do what I wanted to
do. I looked at the ip(4) man page on a FreeBSD 6.1 system, and
the description of IP_ONESBCAST didn't agree with what the
mailing list posting said.  I tested it on FreeBSD 6.1, and it
doesn't do anything relevent.  eCos doesn't have the
IP_ONESBCAST option anyway....

-- 
Grant Edwards                   grante             Yow! I own seven-eighths of
                                  at               all the artists in downtown
                               visi.com            Burbank!


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [ECOS]  How to send UDP broadcast to 255.255.255.255?
  2009-06-15 17:42 [ECOS] How to send UDP broadcast to 255.255.255.255? Grant Edwards
  2009-06-15 20:36 ` Sergei Gavrikov
@ 2009-06-16  6:44 ` Andrew Lunn
  2009-06-16 14:23   ` [ECOS] " Grant Edwards
  1 sibling, 1 reply; 5+ messages in thread
From: Andrew Lunn @ 2009-06-16  6:44 UTC (permalink / raw)
  To: Grant Edwards; +Cc: ecos-discuss

On Mon, Jun 15, 2009 at 05:41:54PM +0000, Grant Edwards wrote:
> I've been asked by one of my internal customers how to send a
> UDP broadcast packet to IP address 255.255.255.255.

Hi Grant

If you have a debugger handy, try putting a break point here:

src/sys/netinet/in_pcb.c
int
in_pcbladdr(inp, nam, plocal_sin)
        register struct inpcb *inp;
        struct sockaddr *nam;
        struct sockaddr_in **plocal_sin;
{
        struct in_ifaddr *ia;
        register struct sockaddr_in *sin = (struct sockaddr_in *)nam;

        if (nam->sa_len != sizeof (*sin))
                return (EINVAL);
        if (sin->sin_family != AF_INET)
                return (EAFNOSUPPORT);
        if (sin->sin_port == 0)
                return (EADDRNOTAVAIL);
        if (!TAILQ_EMPTY(&in_ifaddrhead)) {
                /*
                 * If the destination address is INADDR_ANY,
                 * use the primary local address.
                 * If the supplied address is INADDR_BROADCAST,
                 * and the primary interface supports broadcast,
                 * choose the broadcast address for that interface.
                 */
#define satosin(sa)     ((struct sockaddr_in *)(sa))
#define sintosa(sin)    ((struct sockaddr *)(sin))
#define ifatoia(ifa)    ((struct in_ifaddr *)(ifa))
                if (sin->sin_addr.s_addr == INADDR_ANY)
                    sin->sin_addr = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr;
                else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
                  (TAILQ_FIRST(&in_ifaddrhead)->ia_ifp->if_flags & IFF_BROADCAST))
                    sin->sin_addr = satosin(&TAILQ_FIRST(&in_ifaddrhead)->ia_broadaddr)->sin_addr;

Unfortunately, if this is the place the address is being changed, i
don't see an obvious way around this.

      Andrew

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [ECOS]  Re: How to send UDP broadcast to 255.255.255.255?
  2009-06-16  6:44 ` [ECOS] " Andrew Lunn
@ 2009-06-16 14:23   ` Grant Edwards
  0 siblings, 0 replies; 5+ messages in thread
From: Grant Edwards @ 2009-06-16 14:23 UTC (permalink / raw)
  To: ecos-discuss

On 2009-06-16, Andrew Lunn <andrew@lunn.ch> wrote:
> On Mon, Jun 15, 2009 at 05:41:54PM +0000, Grant Edwards wrote:
>> I've been asked by one of my internal customers how to send a
>> UDP broadcast packet to IP address 255.255.255.255.
>
> Hi Grant
>
> If you have a debugger handy, try putting a break point here:

I don't have one handy, but it certainly looks like the right
spot.

> src/sys/netinet/in_pcb.c
> int
> in_pcbladdr(inp, nam, plocal_sin)
>         register struct inpcb *inp;
>         struct sockaddr *nam;
>         struct sockaddr_in **plocal_sin;
> {
>         struct in_ifaddr *ia;
>         register struct sockaddr_in *sin = (struct sockaddr_in *)nam;
>
>         if (nam->sa_len != sizeof (*sin))
>                 return (EINVAL);
>         if (sin->sin_family != AF_INET)
>                 return (EAFNOSUPPORT);
>         if (sin->sin_port == 0)
>                 return (EADDRNOTAVAIL);
>         if (!TAILQ_EMPTY(&in_ifaddrhead)) {
>                 /*
>                  * If the destination address is INADDR_ANY,
>                  * use the primary local address.
>                  * If the supplied address is INADDR_BROADCAST,
>                  * and the primary interface supports broadcast,
>                  * choose the broadcast address for that interface.
>                  */
> #define satosin(sa)     ((struct sockaddr_in *)(sa))
> #define sintosa(sin)    ((struct sockaddr *)(sin))
> #define ifatoia(ifa)    ((struct in_ifaddr *)(ifa))
>                 if (sin->sin_addr.s_addr == INADDR_ANY)
>                     sin->sin_addr = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr;
>                 else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
>                   (TAILQ_FIRST(&in_ifaddrhead)->ia_ifp->if_flags & IFF_BROADCAST))
>                     sin->sin_addr = satosin(&TAILQ_FIRST(&in_ifaddrhead)->ia_broadaddr)->sin_addr;
>
> Unfortunately, if this is the place the address is being changed, i
> don't see an obvious way around this.


I've been doing some experiments on a FreeBSD 6.1 system, and
it won't allow applications to send a 255.255.255.255 broadcast
either.  In fact, it _requires_ you to specify the interface's
broadcast address as a destination before in order to broadcast
a packet.  FreeBSD 6.1 won't "convert" 255.255.255.255 into the
interface broadcast address the way that eCos does.

Still, the Linux implementation seems to be a lot more useful.
You can specify either 255.255.255.255 or the interface's
broadcast address as the destination, and the packet is
broadcast to that destination address.

I found complaints dating back many years regarding FreeBSD's
lack of ability to send broadcast UDP packets to
255.255.255.255.  It seems you have to use the raw socket
interface to do that.

-- 
Grant Edwards                   grante             Yow! Pardon me, but do you
                                  at               know what it means to be
                               visi.com            TRULY ONE with your BOOTH!


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-06-16 14:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-15 17:42 [ECOS] How to send UDP broadcast to 255.255.255.255? Grant Edwards
2009-06-15 20:36 ` Sergei Gavrikov
2009-06-15 22:14   ` [ECOS] " Grant Edwards
2009-06-16  6:44 ` [ECOS] " Andrew Lunn
2009-06-16 14:23   ` [ECOS] " Grant Edwards

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).