WSL2 Debian socket Operation not supported - perl

Im trying to open a socket from Perl on Debian in WSL2 and it gives me an operation not supported, whereas it is fine on Debian in a VMWare VM.
Diagnostics from my application are as follows:
On Debian on 5.15.79.1-microsoft-standard-WSL2 #1 SMP Wed Nov 23 01:01:46 UTC 2022 x86_64 it does this:
init_sockets...
127.0.0.1:9996 => TH::accept_ftp_dat_session
[::1]:9996 => TH::accept_ftp_dat_session
127.0.0.1:4203 => TH::accept_ftp_cmd_session
[::1]:4203 => TH::accept_ftp_cmd_session
127.0.0.1:4200 => TH::accept_telnet_session
[::1]:4200 => TH::accept_telnet_session
127.0.0.1:4201 => TH::accept_telnet_session
[::1]:4201 => TH::accept_telnet_session
127.0.0.1:7979 => TH::accept_finger_session
[::1]:7979 => TH::accept_finger_session
127.0.0.1:4202 => TH::accept_telnet_session
[::1]:4202 => TH::accept_telnet_session
www-data/http.socket => TH::accept_http_session
Operation not supported at ./src/th_networking.pm line 1033.
On Debian 5.10.149-2 (2022-10-21) x86_64 on VM it does this:
init_sockets...
127.0.0.1:4200 => TH::accept_telnet_session
[::1]:4200 => TH::accept_telnet_session
127.0.0.1:9996 => TH::accept_ftp_dat_session
[::1]:9996 => TH::accept_ftp_dat_session
127.0.0.1:4203 => TH::accept_ftp_cmd_session
[::1]:4203 => TH::accept_ftp_cmd_session
127.0.0.1:7979 => TH::accept_finger_session
[::1]:7979 => TH::accept_finger_session
127.0.0.1:4201 => TH::accept_telnet_session
[::1]:4201 => TH::accept_telnet_session
127.0.0.1:4202 => TH::accept_telnet_session
[::1]:4202 => TH::accept_telnet_session
www-data/http.socket => TH::accept_http_session
proxied.socket => TH::accept_proxied_session
The relevant code is:
sub init_socket
{
my ( $sockaddr ) = #_;
my $family = sockaddr_family($sockaddr);
my $socket;
if ( $family == &AF_UNIX )
{
socket $socket, $family, &SOCK_STREAM, &IPPROTO_IP or die $!;
}
else
{
socket $socket, $family, &SOCK_STREAM, &IPPROTO_TCP or die $!;
setsockopt $socket, &SOL_SOCKET, &SO_REUSEADDR, 1 or die $!;
setsockopt $socket, &SOL_SOCKET, &SO_LINGER, pack( 'ii', 1, 0 ) or die $!;
setsockopt $socket, &IPPROTO_IPV6, &IPV6_V6ONLY, 1 or die $! if $family == &AF_INET6;
}
fcntl $socket, &F_SETFL, &O_NONBLOCK or die $!;
bind $socket, $sockaddr or die $!;
listen $socket, 5 or die $!;
return $socket;
}
It fails at the bind $socket, $sockaddr or die $!; line above.
I have tried WSL1 and WSL2 because I read WSL2 doesnt support AF, but that just gives a different error. Anyone can give me a clue on what to do?

Under WSL2 you may find your home or working directory mapped to something like /mnt/c/Users/username, which is a Windows filesystem not a linux filesystem. Windows filesystems dont support AF_UNIX sockets and consequently if you try to create one it fails.
The solution is to move you working development directory in to the linux filesystem, such as under /home. After doing the you can create AF_UNIX sockets. However, this fs is not mappable to Windows and so cant directly be accessed by Windows hosted IDEs such as VSCode which renders the whole WSL2 as a dev environment for this kind of thing a bit useless.

Related

Perl script error Can't use an undefined value as a symbol reference at ./sendEvent.pl line 66

Hello everyone i am new to perl scripting and below is my perl script
#!/usr/bin/perl
#use strict;
use warnings;
use 5.010;
I am getting the error
Can't use an undefined value as a symbol reference at ./sendEvent.pl line 66.
can anyone please tell me what is the issue?
It seems as though your socket isn't connected, as that's where the undefined reference is being generated.
Try ensuring that your socket is opened with the IO::Socket call...
$sock = IO::Socket::INET->new(PeerAddr => "$hostname",
PeerPort => "$port",
Proto => 'tcp')
or die "can't connect to port $port on $hostname: $!";
or somesuch.
See where that gets you. At the very least you'll know whether the socket connects correctly.
Attn: OP
Suggestion: use of hash simplifies typing and make code more readable
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use IO::Socket;
use Getopt::Long qw(GetOptions);
use Data::Dumper;
my %unit;
my #keys = qw(host port source name value part ptype module);
my #threshold = ("1000000");
# Defaults to avoid typing parameters
%unit = (
host => 'igloz118',
port => '2010',
source => 'APG_HEALTH',
name => 'RawValueCount',
value => '1000002',
part => 'APG',
ptype => 'APG-Frontend',
module => 'connecting',
devtype => 'Host',
group => 'group',
dname => '.lss.emc.com'
);
GetOptions(
'host|h=s' => \$unit{host},
'port|p=s' => \$unit{port},
'source|s=s' => \$unit{source},
'name|n=s' => \$unit{name},
'value|v=s' => \$unit{value},
'part|p=s' => \$unit{part},
'ptype|pt=s' => \$unit{ptype},
'module|m=s' => \$unit{module}
) or die "Usage: $0 --n NAME\n";
$unit{device} = $unit{host}.$unit{dname};
say '::: Parameters :::::';
printf "%-8s = %s\n", $_, $unit{$_} for #keys;
say '::::::::::::::::::::';
my $sock = IO::Socket::INET->new(
PeerAddr => $unit{hostname},
PeerPort => $unit{port},
Proto => 'tcp'
) or die "can't connect to port $unit{port} on $unit{host}: $!";;
#keys = qw/group variable value device devtype module part parttype name threshold source/;
for (my $i = 0; $i <=0 ; $i++) {
my($timestamp,$raw);
$timestamp = time;
$unit{threshold} = $threshold[$i];
$unit{variable} = join '.', #unit{qw/source device part name/};
$raw = join "\t", ( '+r', $timestamp, #unit{#keys} );
print "$raw";
print $sock "$raw";
}
close($sock);

perl socket: increment port if in use

I have the following code:
use IO::Socket::INET;
use Sys::Hostname;
use Socket;
my($addr)=inet_ntoa((gethostbyname(hostname))[4]);
my $port_to_use = 7777;
my $socket = new IO::Socket::INET (
LocalHost => $addr,
LocalPort => $port_to_use,
Proto => 'tcp',
Listen => 5,
Reuse => 1
);
die "cannot create socket $!\n" unless $socket;
my $client_socket = $socket->accept();
if i start this in one screen and start another one in the other screen, i get an error:
cannot create socket Address already in use
instead of dying, i would like to try using different port (increment by 1) until it can find the one to use.
I've try to convert the die line with eval but im not able to catch it
any suggestions?
Use a Loop:
use IO::Socket::INET;
use Sys::Hostname;
use Socket;
my($addr)=inet_ntoa((gethostbyname(hostname))[4]);
my $port_to_use = 7776;
my $fail =1;
my $socket;
while ($fail == 1){
$port_to_use++;
$fail = 0;
warn $port_to_use;
$socket = IO::Socket::INET->new (
LocalHost => $addr,
LocalPort => $port_to_use,
Proto => 'tcp',
Listen => 5,
Reuse => 0
) or $fail =1;
}
warn $socket->accept();
Here is a tidier alternative which actually checks to make sure the failure to bind to a given port was due to the port being in use. It also limits the port range to check. If you use the code in the other answer, and, if for some reason, the machine is not allowing your application to bind to any ports, you are going to get stuck in an infinite loop. It may also cause your application to bind to ports that should otherwise have been left alone etc.
#!/usr/bin/env perl
use strict;
use warnings;
use Carp qw( croak );
use Errno qw( EADDRINUSE );
use IO::Socket::INET;
use Sys::Hostname qw( hostname );
use Socket;
# These can come from a config file or command line
# See also https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Dynamic.2C_private_or_ephemeral_ports
# https://unix.stackexchange.com/a/39784/2371
my #port_range = (0xC000, 0xFFFF);
my $addr = inet_ntoa( (gethostbyname(hostname) )[4]);
my $socket;
TRY_PORT:
for my $port ($port_range[0] .. $port_range[1]) {
warn "Trying port $port\n";
$socket = IO::Socket::INET->new(
LocalHost => $addr,
LocalPort => $port,
Proto => 'tcp',
Listen => 7,
Reuse => 0,
);
if ($socket) {
warn "Bound to port $port\n";
last TRY_PORT;
}
if ( EADDRINUSE != $! ) {
croak "Cannot bind to port '$port': $!";
}
warn "Port in use, trying the next one\n";
}
$socket->accept
or croak "...";
# ...

How to catch the error without exiting from the script?

The below script exit when the peer port is not listening. I don't want it to exist instead it needs to keep trying. I know 'die' below will cause this, but is there a better way to capture the error without exiting.
my $socket = new IO::Socket::INET (
PeerHost => $properties{peer_host},
PeerPort => $properties{peer_port},
Proto => 'tcp',
);
die "cannot connect to the server $!\n" unless $socket;
while(1){
#send something to the port
}
Output:
cannot connect to the server Connection refused
Alternatives to die might be helpful: http://perldoc.perl.org/Carp.html
and warn:
http://perldoc.perl.org/functions/warn.html
you can use warn
my $socket = new IO::Socket::INET (
PeerHost => $properties{peer_host},
PeerPort => $properties{peer_port},
Proto => 'tcp',
);
warn "cannot connect to the server $#\n" unless $socket;
while(1){
#send something to the port
}

use IO::Socket::IP ??? how to make a client in perl Ipv6

I have been trying to find a simple client ipv6 script
that would work with Evens server script , of course I
dont know what Im doing, so all I can do is rewrite someone
else's work until I know what Im doing ...
so here is a server script that works on Microsoft widows server
use IO::Socket::IP -register;
my $sock = IO::Socket->new(
Domain => PF_INET6,
LocalHost => "::1",
Listen => 1,
) or die "Cannot create socket - $#\n";
print "Created a socket of type " . ref($sock) . "\n";
{
$in = <STDIN>;
print $in->$sock;
redo }
of course the $in->$sock is not working, cause I dont know how to send
data using just $sock ???
so I need to know how to send information properly and
what I need is A client script to connect to the above script
using the ipv6 protocol
can anyone help with this ???
I would like to be able to send information from one
perl program to another perl program using this
being able to send information back and forth would
be Ideal ...
Thanks in advance
-Mark
That's a server socket (Listen => 1), so you have to accept a connection.
use IO::Socket::IP -register;
my $listen_sock = IO::Socket::IP->new(
LocalHost => "::1", # bind()
Listen => 1, # listen()
) or die "Cannot create socket - $#\n";
print("Listening to ".$listen_sock->sockhost()." "
.$listen_sock->sockport()."\n");
while (1) {
my $sock = $listen_sock->accept()
or die $!;
print("Connection received from ".$sock->peerhost()." "
.$sock->peerport()."\n");
while (<$sock>) {
print $sock "echo: $_";
}
}
A client:
use IO::Socket::IP -register;
#ARGV == 2 or die("usage");
my ($host, $port) = #ARGV;
my $sock = IO::Socket::IP->new(
PeerHost => $host, # \ bind()
PeerPort => $port, # /
) or die "Cannot create socket - $#\n";
print $sock "Hello, world!\n";
$sock->shutdown(1); # Done writing.
print while <$sock>;
The comments indicate the underlying system call used to perform the action.

Can't figure out how to fix this script in perl

I'm running this script in perl and correctly putting in the id and port. however, I keep getting "scalar found where operator expected at line 16 near"'skype://1024,'$ARGV"
#!usr/perl/bin
use LWP::UserAgent;
system("color a");
system("title Skype <<");
system("cls");
if(!$ARGV[0]||!$ARGV[1]) {
print q {
Usage : perl skype.pl [userid] [port=1024,80,433]
};
}
else {
use IO::Socket;
my $sock = new IO::Socket::INET (
PeerAddr => 'skype://'.$ARGV[0],
PeerPort => 'skype://1024,'$ARGV[1],
Proto => 'tcp',
);
die "Video Call Error: $!\n" unless $sock;
print $sock "skype://0x77656263616d5f647269766572\n";
system("start ".$sock);
}
# jvoid(document.write(document.currentUser.id));
You have a typo there:
PeerPort => 'skype://1024,'$ARGV[1],
Should be:
PeerPort => 'skype://1024,'.$ARGV[1],
# ^--- missing period