Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I am on Windows and using Strawberry Perl, and I also have a Windows virtual machine (VM) installed on my machine. The VM creates a network interface with the description "VirtualBox Host-Only Ethernet Adapter", and its IPv4 is: 192.168.56.1 (I configured the VM's network to run in bridge adapter mode, so the VM has an Ethernet interface at address 192.168.1.12). Normally, I use a wireless interface with an IPv4 address at 192.168.1.6.

I want to broadcast in the local subnet. So I ran this code:

use strict; use warnings; use IO::Socket::INET; my $broadcast_address = '255.255.255.255'; my $socket = IO::Socket::INET->new( Proto => 'udp', Broadcast => 1, LocalPort => 8888, PeerAddr => $broadcast_address, PeerPort => 9999, ) or die "Could not create socket: $!\n"; my $message = "Broadcast message!"; $socket->send($message) or die "Send error: $IO::Socket::errstr\n"; my $hostAddr = $socket->sockhost(); my $hostPort = $socket->sockport(); print "Broadcast message sent from address $hostAddr:$hostPort\n"; $socket->close();

The problem is it printed this out: "Broadcast message sent from address 192.168.56.1:8888".. The receiver couldn't receive the broadcast message from 192.168.56.1 address, but if I changed the $broadcast_address to 192.168.1.255, it would work.

I diagnosed that the Perl module automatically chooses 192.168.56.1 as the main IP address and then uses it to send messages. How do I get rid of that? And how to make the wireless interface the chosen?

Thanks in advance.

Replies are listed 'Best First'.
Re: Broadcast when host machine contains virtual interface
by NERDVANA (Priest) on Aug 29, 2024 at 02:08 UTC
    It sounds like you just need it to bind to the wireless address? So LocalAddr => "192.168.1.6", in your constructor.

    But also, as you already identified the broadcast address for your subnet works, why not just use that?

      I want to make it as generic as possible so that it can work on other private IP addresses as well, like 192.168.1.7 or 172.16.1.2. In that case, binding 192.168.1.6 and 192.168.1.255 won't work.

        Well, as far as I know you can only broadcast to one interface at a time. So, you have to decide which subnet is the intended destination so the kernel knows which interface to use for it, either by inspecting all the available networks and guessing, or by having the user provide you with the subnet-specific broadcast address. You could inspect the routing table looking for the default gateway and use that network, but this would give unwanted results if you ran it *on* the gateway host because then you'd be broadcasting to the Internet. You could guess if you *were* the gateway based on whether any interface has a ".1" IP address, but then that fails for your virtual machine scenario where the workstation is a client on the wireless network but also a gateway for the VMs' network.

        The other option is to create one socket bound to each subnet and then send the broadcast packet to each of them.

        Or, who knows, there may be tricks I don't know about to get a single broadcast message out via multiple interfaces at once. IPv6 has an awful lot of features I haven't read up on.

Re: Broadcast when host machine contains virtual interface
by Anonymous Monk on Aug 29, 2024 at 15:19 UTC

    After searching for a while, I came up with this solution. First, we create a dummy socket which has the "PeerAddr" points to a reserved IP address. In my case, I tested with 192.168.0.0. Then use "sockhost" method to get the local IP address which is 192.168.1.6. Next we bind the "HostAddr" to the result of "sockhost". So that when the "PeerAddr" is set to 255.255.255.255, it will be the same as 192.168.1.255.

    Here is the code:

    sub localIPAddress { my $socket = new IO::Socket::INET ( Proto => 'udp', PeerAddr => '192.168.0.0', ); my $localAddress = $socket->sockhost(); $socket->close(); return $localAddress; } my $socket = IO::Socket::INET->new( Proto => 'udp', Broadcast => 1, LocalAddr => localIPAddress(), LocalPort => 8888, PeerAddr => '255.255.255.255', PeerPort => 9999, ) or die "Could not create socket: $!\n";