comp.lang.ada
 help / color / mirror / Atom feed
* Broadcasting UDP
@ 2016-04-24 16:31 ahlan.marriott
  2016-04-24 17:22 ` Dmitry A. Kazakov
  2016-04-29 23:35 ` douty.chris
  0 siblings, 2 replies; 7+ messages in thread
From: ahlan.marriott @ 2016-04-24 16:31 UTC (permalink / raw)


I asked this question sometime ago but I can no longer find the post.
In any case it was never really resolved so let me try again.
I am looking for a platform independent Ada solution on how to broadcast a UDP packet.
I would be satisfied with a GNAT only solution, i.e. one that uses Gnat.Sockets and/or Gnat specific libraries.
Attempting to broadcast to the limited broadcast address 255.255.255.255 has no effect (under Windows at least)
To successfully broadcast one needs to use the subnet directed broadcast address.
As I want to support PCs that have multiple ethernet adapters this means that I must iterate over the ethernet adapters, discover my ethernet address and subnet for each adapter, calculate the broadcast address and then send the UDP packet to that address.
So far so good.
My problem is that I don't know how to iterate over my adapters and obtain the address and subnet mask for each adapter using just Ada.
Can anyone tell me how I can do this using Ada?

The solution I currently employ is to bind to a windows API.
However this is obviously not target independent.

If there is no Ada way of iterating over the ethernet adapters then I will have to do a separate implementation for each platform.
In which case I would be grateful if anyone could tell me how I can iterate my adapters under Linux and OSX.

Best wishes,
Ahlan

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

* Re: Broadcasting UDP
  2016-04-24 16:31 Broadcasting UDP ahlan.marriott
@ 2016-04-24 17:22 ` Dmitry A. Kazakov
  2016-04-25 14:18   ` ahlan
  2016-04-29 23:35 ` douty.chris
  1 sibling, 1 reply; 7+ messages in thread
From: Dmitry A. Kazakov @ 2016-04-24 17:22 UTC (permalink / raw)


On 2016-04-24 18:31, ahlan.marriott@gmail.com wrote:
> I asked this question sometime ago but I can no longer find the post.
> In any case it was never really resolved so let me try again.
> I am looking for a platform independent Ada solution on how to broadcast a UDP packet.
> I would be satisfied with a GNAT only solution, i.e. one that uses Gnat.Sockets and/or Gnat specific libraries.
> Attempting to broadcast to the limited broadcast address 255.255.255.255 has no effect (under Windows at least)
> To successfully broadcast one needs to use the subnet directed broadcast address.
> As I want to support PCs that have multiple ethernet adapters this
> means that I must iterate over the ethernet adapters, discover my
> ethernet address and subnet for each adapter, calculate the broadcast
> address and then send the UDP packet to that address.
> So far so good.
> My problem is that I don't know how to iterate over my adapters and
> obtain the address and subnet mask for each adapter using just Ada.
> Can anyone tell me how I can do this using Ada?

declare
    Host    : Host_Entry_Type := Get_Host_By_Name (Host_Name);
    Address : aliased Sock_Addr_Type;
begin
    for Index in 1..Addresses_Length (Host) loop
       Address.Addr := Addresses (Host, Index)));
       Address.Port := <port>;
       declare
          Socket : Socket_Type := No_Socket;
          Pier   : Sock_Addr_Type;
       begin
          Create_Socket (Socket, Family_Inet, Socket_Datagram);
          Set_Socket_Option
          (  Socket,
             Socket_Level,
             (Reuse_Address, True)
          );
          Set_Socket_Option
          (  Socket,
             Socket_Level,
             (Broadcast, True)
          );
          Set_Socket_Option
          (  Socket,
             Socket_Level,
             (Receive_Timeout, <timeout>)
          );
          Bind_Socket (Socket, Address);
          Address.Addr := Broadcast_Inet_Addr;
          Send_Socket (Socket, <request-packet>, Last, Address'Access);
          loop -- Collecting responses, time-limited <timeout>
             ...
             Receive_Socket (Socket, <response-packet>, Last, Pier);
             ...
          end loop;
          Close_Socket (Socket);
       end;
    end loop;
end;

> In which case I would be grateful if anyone could tell me how I can iterate my adapters under Linux

Under Linux it is through the proc file system, if I correctly remember. 
I don't have it in the head right now.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: Broadcasting UDP
  2016-04-24 17:22 ` Dmitry A. Kazakov
@ 2016-04-25 14:18   ` ahlan
  2016-04-25 14:51     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 7+ messages in thread
From: ahlan @ 2016-04-25 14:18 UTC (permalink / raw)


On Sunday, April 24, 2016 at 7:22:45 PM UTC+2, Dmitry A. Kazakov wrote:
> On 2016-04-24 18:31, ahlan.marriott@gmail.com wrote:
> > I asked this question sometime ago but I can no longer find the post.
> > In any case it was never really resolved so let me try again.
> > I am looking for a platform independent Ada solution on how to broadcast a UDP packet.
> > I would be satisfied with a GNAT only solution, i.e. one that uses Gnat.Sockets and/or Gnat specific libraries.
> > Attempting to broadcast to the limited broadcast address 255.255.255.255 has no effect (under Windows at least)
> > To successfully broadcast one needs to use the subnet directed broadcast address.
> > As I want to support PCs that have multiple ethernet adapters this
> > means that I must iterate over the ethernet adapters, discover my
> > ethernet address and subnet for each adapter, calculate the broadcast
> > address and then send the UDP packet to that address.
> > So far so good.
> > My problem is that I don't know how to iterate over my adapters and
> > obtain the address and subnet mask for each adapter using just Ada.
> > Can anyone tell me how I can do this using Ada?
> 
> declare
>     Host    : Host_Entry_Type := Get_Host_By_Name (Host_Name);
>     Address : aliased Sock_Addr_Type;
> begin
>     for Index in 1..Addresses_Length (Host) loop
>        Address.Addr := Addresses (Host, Index)));
>        Address.Port := <port>;
>        declare
>           Socket : Socket_Type := No_Socket;
>           Pier   : Sock_Addr_Type;
>        begin
>           Create_Socket (Socket, Family_Inet, Socket_Datagram);
>           Set_Socket_Option
>           (  Socket,
>              Socket_Level,
>              (Reuse_Address, True)
>           );
>           Set_Socket_Option
>           (  Socket,
>              Socket_Level,
>              (Broadcast, True)
>           );
>           Set_Socket_Option
>           (  Socket,
>              Socket_Level,
>              (Receive_Timeout, <timeout>)
>           );
>           Bind_Socket (Socket, Address);
>           Address.Addr := Broadcast_Inet_Addr;
>           Send_Socket (Socket, <request-packet>, Last, Address'Access);
>           loop -- Collecting responses, time-limited <timeout>
>              ...
>              Receive_Socket (Socket, <response-packet>, Last, Pier);
>              ...
>           end loop;
>           Close_Socket (Socket);
>        end;
>     end loop;
> end;
> 
> > In which case I would be grateful if anyone could tell me how I can iterate my adapters under Linux
> 
> Under Linux it is through the proc file system, if I correctly remember. 
> I don't have it in the head right now.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Dear Dmitry,

This of course works but by using Broadcast_Inet_Addr (255.255.255.255) then we actually transmit more UDP messages than is strictly necessary.

For example if I have two adapters one with 100.13.5.200 and the other 169.254.7.7 and I send a UDP broadcast on each adapter then four UDP messages are actually transmitted.
1) Src=100.13.5.200 Dest=255.255.255.255 on adapter 1
2) Src=100.13.5.200 Dest=255.255.255.255 on adapter 2
3) Src=169.254.7.7 Dest=255.255.255.255 on adapter 1
4) Src=169.254.7.7 Dest=255.255.255.255 on adapter 2

This is because the destination address 255.255.255.255 is for all adapters.
Whereas if I could somehow find out the subnet mask for the adapter I could refine the destination address to be a subnet directed broadcast address and thereby could prevent the unnecessary traffic.
In my example if the subnet for both adapters was 255.255.0.0 then the broadcast address for adapter 1 would be 100.13.255.255 and for adapter 2 169.254.255.255.

If I use subnet directed broadcast addresses then on my test PCs running Ms-Windows messages are only sent on the adapter if the subnet matches.
Ie only two messages are transmitted, one per adapter.

This is what I was aiming for.
However, although I can find out the host address for each adapter, I haven't been able to find out how I can determine out their subnet masks.

If I could find out the subnet masks I could derive the subnet directed broadcast addresses and use these as the destination addresses and thereby reduce the traffic.

Not by much I grant you but every little helps and besides it would be a little more elegant than using the crude broadcast to all on all adapters approach.

Any ideas?
MfG
Ahlan

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

* Re: Broadcasting UDP
  2016-04-25 14:18   ` ahlan
@ 2016-04-25 14:51     ` Dmitry A. Kazakov
  2016-04-25 17:11       ` ahlan.marriott
  0 siblings, 1 reply; 7+ messages in thread
From: Dmitry A. Kazakov @ 2016-04-25 14:51 UTC (permalink / raw)


On 25/04/2016 16:18, ahlan@marriott.org wrote:

> This of course works but by using Broadcast_Inet_Addr
> (255.255.255.255) then we actually transmit more UDP messages than is
> strictly necessary.
>
> For example if I have two adapters one with 100.13.5.200 and the
> other  169.254.7.7 and I send a UDP broadcast on each adapter then four UDP
> messages are actually transmitted.
> 1) Src=100.13.5.200 Dest=255.255.255.255 on adapter 1
> 2) Src=100.13.5.200 Dest=255.255.255.255 on adapter 2
> 3) Src=169.254.7.7 Dest=255.255.255.255 on adapter 1
> 4) Src=169.254.7.7 Dest=255.255.255.255 on adapter 2
>
> This is because the destination address 255.255.255.255 is for all adapters.

But the socket is bound to the address of a concrete adapter. 
Send_Socket should not leak through another adapter. It does not look right.

> If I could find out the subnet masks I could derive the subnet
> directed broadcast addresses and use these as the destination addresses
> and thereby reduce the traffic.

AFAIK there is no means for that in the Berkeley sockets.

> Not by much I grant you but every little helps and besides it would
> be  a little more elegant than using the crude broadcast to all on all
> adapters approach.

Broadcasts with alien source address is not a big problem. I hope you 
are not doing anything but network discovery over broadcast.

> Any ideas?

Maybe, there is something with network settings (bridging etc). 
Broadcast packets should not cross segment boundaries.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Broadcasting UDP
  2016-04-25 14:51     ` Dmitry A. Kazakov
@ 2016-04-25 17:11       ` ahlan.marriott
  2016-04-26 16:21         ` ahlan
  0 siblings, 1 reply; 7+ messages in thread
From: ahlan.marriott @ 2016-04-25 17:11 UTC (permalink / raw)


On Monday, 25 April 2016 16:51:36 UTC+2, Dmitry A. Kazakov  wrote:
> On 25/04/2016 16:18, ahlan@marriott.org wrote:
> 
> > This of course works but by using Broadcast_Inet_Addr
> > (255.255.255.255) then we actually transmit more UDP messages than is
> > strictly necessary.
> >
> > For example if I have two adapters one with 100.13.5.200 and the
> > other  169.254.7.7 and I send a UDP broadcast on each adapter then four UDP
> > messages are actually transmitted.
> > 1) Src=100.13.5.200 Dest=255.255.255.255 on adapter 1
> > 2) Src=100.13.5.200 Dest=255.255.255.255 on adapter 2
> > 3) Src=169.254.7.7 Dest=255.255.255.255 on adapter 1
> > 4) Src=169.254.7.7 Dest=255.255.255.255 on adapter 2
> >
> > This is because the destination address 255.255.255.255 is for all adapters.
> 
> But the socket is bound to the address of a concrete adapter. 
> Send_Socket should not leak through another adapter. It does not look right.
> 
> > If I could find out the subnet masks I could derive the subnet
> > directed broadcast addresses and use these as the destination addresses
> > and thereby reduce the traffic.
> 
> AFAIK there is no means for that in the Berkeley sockets.
> 
> > Not by much I grant you but every little helps and besides it would
> > be  a little more elegant than using the crude broadcast to all on all
> > adapters approach.
> 
> Broadcasts with alien source address is not a big problem. I hope you 
> are not doing anything but network discovery over broadcast.
> 
> > Any ideas?
> 
> Maybe, there is something with network settings (bridging etc). 
> Broadcast packets should not cross segment boundaries.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Dear Dmitry,

We are indeed only doing network discovery so these superfluous broadcasts with alien source addresses shouldn't be a problem - just not very nice ;-)
It seems that under Windows-Xp (my test machines) the adapter is selected according to the destination address and adapter subnet mask and not on source address.
I'll try it out on a Win10 machine tomorrow to check whether this is a Windows issue or a legacy issue.
Either way it isn't terribly important especially if there isn't an easy way to get the adapter subnet masks.

I just thought I'd ask the experts before giving up.
Many thanks,
MfG
Ahlan

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

* Re: Broadcasting UDP
  2016-04-25 17:11       ` ahlan.marriott
@ 2016-04-26 16:21         ` ahlan
  0 siblings, 0 replies; 7+ messages in thread
From: ahlan @ 2016-04-26 16:21 UTC (permalink / raw)


On Monday, April 25, 2016 at 7:11:37 PM UTC+2, ahlan.m...@gmail.com wrote:
> On Monday, 25 April 2016 16:51:36 UTC+2, Dmitry A. Kazakov  wrote:
> > On 25/04/2016 16:18, ahlan@marriott.org wrote:
> > 
> > > This of course works but by using Broadcast_Inet_Addr
> > > (255.255.255.255) then we actually transmit more UDP messages than is
> > > strictly necessary.
> > >
> > > For example if I have two adapters one with 100.13.5.200 and the
> > > other  169.254.7.7 and I send a UDP broadcast on each adapter then four UDP
> > > messages are actually transmitted.
> > > 1) Src=100.13.5.200 Dest=255.255.255.255 on adapter 1
> > > 2) Src=100.13.5.200 Dest=255.255.255.255 on adapter 2
> > > 3) Src=169.254.7.7 Dest=255.255.255.255 on adapter 1
> > > 4) Src=169.254.7.7 Dest=255.255.255.255 on adapter 2
> > >
> > > This is because the destination address 255.255.255.255 is for all adapters.
> > 
> > But the socket is bound to the address of a concrete adapter. 
> > Send_Socket should not leak through another adapter. It does not look right.
> > 
> > > If I could find out the subnet masks I could derive the subnet
> > > directed broadcast addresses and use these as the destination addresses
> > > and thereby reduce the traffic.
> > 
> > AFAIK there is no means for that in the Berkeley sockets.
> > 
> > > Not by much I grant you but every little helps and besides it would
> > > be  a little more elegant than using the crude broadcast to all on all
> > > adapters approach.
> > 
> > Broadcasts with alien source address is not a big problem. I hope you 
> > are not doing anything but network discovery over broadcast.
> > 
> > > Any ideas?
> > 
> > Maybe, there is something with network settings (bridging etc). 
> > Broadcast packets should not cross segment boundaries.
> > 
> > -- 
> > Regards,
> > Dmitry A. Kazakov
> > http://www.dmitry-kazakov.de
> 
> Dear Dmitry,
> 
> We are indeed only doing network discovery so these superfluous broadcasts with alien source addresses shouldn't be a problem - just not very nice ;-)
> It seems that under Windows-Xp (my test machines) the adapter is selected according to the destination address and adapter subnet mask and not on source address.
> I'll try it out on a Win10 machine tomorrow to check whether this is a Windows issue or a legacy issue.
> Either way it isn't terribly important especially if there isn't an easy way to get the adapter subnet masks.
> 
> I just thought I'd ask the experts before giving up.
> Many thanks,
> MfG
> Ahlan

FYI,

Using the destination address to select the adapter or adapters seems to be a feature of Win-Xp. The production of broadcast messages with alien sources addresses does not occur with Win-10 and according to my colleagues does not occur with Win7-64.

So it looks like Microsoft fixed this problem many years ago.
Those of us that insist that things never got better than Win-2000 will have to live with a few bad packets ;-)

MfG
Ahlan

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

* Re: Broadcasting UDP
  2016-04-24 16:31 Broadcasting UDP ahlan.marriott
  2016-04-24 17:22 ` Dmitry A. Kazakov
@ 2016-04-29 23:35 ` douty.chris
  1 sibling, 0 replies; 7+ messages in thread
From: douty.chris @ 2016-04-29 23:35 UTC (permalink / raw)


On Sunday, April 24, 2016 at 9:31:49 AM UTC-7, ahlan.m...@gmail.com wrote:
[cut]
> If there is no Ada way of iterating over the ethernet adapters then I will have to do a separate implementation for each platform.
> In which case I would be grateful if anyone could tell me how I can iterate my adapters under Linux and OSX.
> 
> Best wishes,
> Ahlan

Dmitry and other have shown you good code, but networking in general and your requirement in particular are inherently platform-specific. You will need to consult your target OS documentation to learn how to discover available network interfaces. You might create some generic Ada wrapper over this, but each OS will have its own method of enumerating interfaces.

Honestly I don't remember how to do it on Linux. Take a look at SIOCGIFCONF in the netdevice(7) man page on Linux or netintro(4) man page on OS X. I don't have a Windows machine.

Good luck,
Chris


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

end of thread, other threads:[~2016-04-29 23:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-24 16:31 Broadcasting UDP ahlan.marriott
2016-04-24 17:22 ` Dmitry A. Kazakov
2016-04-25 14:18   ` ahlan
2016-04-25 14:51     ` Dmitry A. Kazakov
2016-04-25 17:11       ` ahlan.marriott
2016-04-26 16:21         ` ahlan
2016-04-29 23:35 ` douty.chris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox