Question

I need to check if remote UDP port is opened. My part of code is:

sub scanUDP {
    my $address = shift;
    my $port = shift;
    my $udpSocket = new IO::Socket::INET (
                                        PeerAddr => $address,
                                        PeerPort => $port,
                                        Proto => 'udp',
                                        ) or return 0;
    $udpSocket -> send ('hello', 0);
    #........SOME CODE.............
    return 1;
}

..SOME CODE.. should check if I received ICMP packets "Host unreached" or "Port unreached" to check if port is opened. But how can I do it?

Was it helpful?

Solution 3

This is the code that works for me:

sub scanUDP {
    my $address = shift;
    my $port = shift;
    my $socket = new IO::Socket::INET (
                                        PeerAddr => $address,
                                        PeerPort => $port,
                                        Proto => 'udp',
                                        ) or return 0;
    $socket -> send('Hello',0);
    my $select = new IO::Select();
    $select -> add($socket);
    my @socket = $select -> can_read(1);
    if (@socket == 1) {
        $socket -> recv(my $temp, 1, 0) or return 0;
        return 1;
    }
    return 1;
}

OTHER TIPS

Generally you can't. UDP does not have a connected state, so it is in no way required to send you any reply to the packet you sent. And that's even when ignoring package loss. You may get a positive reply if you sent a valid request in whatever protocol you're accessing and the remote port is open, but the absence of such a reply can not be used to make any conclusions.

If you really get an ICMP unreachable back you will receive the error with a later send call (unless you peer is localhost, than you might get it with the first one already). But there is no guarantee that you will get an ICMP unreachable back at all, because either ICMP or the UDP itself might be filtered by a firewall.

It looks like it will not report the problem on windows this way, but you can use recv there instead of send (works on UNIX too). The error code is probably something specific to windows, ECONNREFUSED works only on UNIX:

use strict;
use warnings;
use IO::Socket::INET;

my $cl = IO::Socket::INET->new(
    PeerAddr => '192.168.122.42:12345', # definitly rejecting
    Proto => 'udp',
);
$cl->send('foo') or die "send failed: $!"; # first send will succeed
# wait some time to receive ICMP unreachable
sleep(1);
$cl->blocking(0);
if ( ! $cl->recv( my $buf,0)) {
    # will get ECONNREFUSED on UNIX, on Win the code is different
    warn "error $!" if ! $!{EAGAIN};
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top