191f110e0Safresh1#!/usr/bin/perl 291f110e0Safresh1 391f110e0Safresh1use warnings; 491f110e0Safresh1use strict; 591f110e0Safresh1 691f110e0Safresh1use File::Temp qw(tempdir); 791f110e0Safresh1use File::Spec::Functions; 891f110e0Safresh1use IO::Socket; 991f110e0Safresh1use IO::Socket::UNIX; 1091f110e0Safresh1use Socket; 1191f110e0Safresh1use Config; 1291f110e0Safresh1use Test::More; 1391f110e0Safresh1 1491f110e0Safresh1plan skip_all => "UNIX domain sockets not implemented on $^O" 1591f110e0Safresh1 if ($^O =~ m/^(?:qnx|nto|vos|MSWin32|VMS)$/); 1691f110e0Safresh1 1791f110e0Safresh1my $socketpath = catfile(tempdir( CLEANUP => 1 ), 'testsock'); 1891f110e0Safresh1 195759b3d2Safresh1# check the socketpath fits in sun_path. 205759b3d2Safresh1# 215759b3d2Safresh1# pack_sockaddr_un() just truncates the path, this may change, but how 225759b3d2Safresh1# it will handle such a condition is undetermined (and we might need 235759b3d2Safresh1# to work with older versions of Socket outside of a perl build) 245759b3d2Safresh1# https://rt.cpan.org/Ticket/Display.html?id=116819 255759b3d2Safresh1 265759b3d2Safresh1my $name = eval { pack_sockaddr_un($socketpath) }; 275759b3d2Safresh1if (defined $name) { 285759b3d2Safresh1 my ($packed_name) = eval { unpack_sockaddr_un($name) }; 295759b3d2Safresh1 if (!defined $packed_name || $packed_name ne $socketpath) { 305759b3d2Safresh1 plan skip_all => "socketpath too long for sockaddr_un"; 315759b3d2Safresh1 } 325759b3d2Safresh1} 335759b3d2Safresh1 345759b3d2Safresh1plan tests => 15; 355759b3d2Safresh1 3691f110e0Safresh1# start testing stream sockets: 3791f110e0Safresh1my $listener = IO::Socket::UNIX->new(Type => SOCK_STREAM, 3891f110e0Safresh1 Listen => 1, 3991f110e0Safresh1 Local => $socketpath); 4091f110e0Safresh1ok(defined($listener), 'stream socket created'); 4191f110e0Safresh1 4291f110e0Safresh1my $p = $listener->protocol(); 4356d68f1eSafresh1{ 4456d68f1eSafresh1 # the value of protocol isn't well defined for AF_UNIX, when we 4556d68f1eSafresh1 # create the socket we supply 0, which leaves it up to the implementation 4656d68f1eSafresh1 # to select a protocol, so we (now) don't save a 0 protocol during socket 4756d68f1eSafresh1 # creation. This test then breaks if the implementation doesn't support 4856d68f1eSafresh1 # SO_SOCKET (at least on AF_UNIX). 4956d68f1eSafresh1 # This specifically includes NetBSD, Darwin and cygwin. 5056d68f1eSafresh1 # This is a TODO instead of a skip so if these ever implement SO_PROTOCOL 5156d68f1eSafresh1 # we'll be notified about the passing TODO so the test can be updated. 5256d68f1eSafresh1 local $TODO = "$^O doesn't support SO_PROTOCOL on AF_UNIX" 53eac174f2Safresh1 if $^O =~ /^(netbsd|darwin|cygwin|hpux|solaris|dragonfly|os390|gnu)$/; 5491f110e0Safresh1 ok(defined($p), 'protocol defined'); 5556d68f1eSafresh1} 5691f110e0Safresh1my $d = $listener->sockdomain(); 5791f110e0Safresh1ok(defined($d), 'domain defined'); 5891f110e0Safresh1my $s = $listener->socktype(); 5991f110e0Safresh1ok(defined($s), 'type defined'); 6091f110e0Safresh1 6191f110e0Safresh1SKIP: { 6291f110e0Safresh1 skip "fork not available", 4 6391f110e0Safresh1 unless $Config{d_fork} || $Config{d_pseudofork}; 6491f110e0Safresh1 6591f110e0Safresh1 my $cpid = fork(); 6691f110e0Safresh1 if (0 == $cpid) { 6791f110e0Safresh1 # the child: 6891f110e0Safresh1 sleep(1); 6991f110e0Safresh1 my $connector = IO::Socket::UNIX->new(Peer => $socketpath); 7091f110e0Safresh1 exit(0); 7191f110e0Safresh1 } else { 7291f110e0Safresh1 ok(defined($cpid), 'spawned a child'); 7391f110e0Safresh1 } 7491f110e0Safresh1 7591f110e0Safresh1 my $new = $listener->accept(); 7691f110e0Safresh1 7791f110e0Safresh1 is($new->sockdomain(), $d, 'domain match'); 7891f110e0Safresh1 SKIP: { 7991f110e0Safresh1 skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL }); 8091f110e0Safresh1 skip "SO_PROTOCOL defined but not implemented", 1 8191f110e0Safresh1 if !defined $new->sockopt(Socket::SO_PROTOCOL); 8291f110e0Safresh1 is($new->protocol(), $p, 'protocol match'); 8391f110e0Safresh1 } 8491f110e0Safresh1 SKIP: { 8591f110e0Safresh1 skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE }); 8691f110e0Safresh1 skip "SO_TYPE defined but not implemented", 1 8791f110e0Safresh1 if !defined $new->sockopt(Socket::SO_TYPE); 8891f110e0Safresh1 is($new->socktype(), $s, 'type match'); 8991f110e0Safresh1 } 9091f110e0Safresh1 9191f110e0Safresh1 unlink($socketpath); 9291f110e0Safresh1 wait(); 9391f110e0Safresh1} 9491f110e0Safresh1 9591f110e0Safresh1undef $TODO; 9691f110e0Safresh1SKIP: { 9791f110e0Safresh1 skip "datagram unix sockets not supported on $^O", 7 9891f110e0Safresh1 if $^O eq "haiku"; 9991f110e0Safresh1 # now test datagram sockets: 10091f110e0Safresh1 $listener = IO::Socket::UNIX->new(Type => SOCK_DGRAM, 10191f110e0Safresh1 Local => $socketpath); 10291f110e0Safresh1 ok(defined($listener), 'datagram socket created'); 10391f110e0Safresh1 10491f110e0Safresh1 $p = $listener->protocol(); 10556d68f1eSafresh1 { 10656d68f1eSafresh1 # see comment above 10756d68f1eSafresh1 local $TODO = "$^O doesn't support SO_PROTOCOL on AF_UNIX" 108eac174f2Safresh1 if $^O =~ /^(netbsd|darwin|cygwin|hpux|solaris|dragonfly|os390|gnu)$/; 10991f110e0Safresh1 ok(defined($p), 'protocol defined'); 11056d68f1eSafresh1 } 11191f110e0Safresh1 $d = $listener->sockdomain(); 11291f110e0Safresh1 ok(defined($d), 'domain defined'); 11391f110e0Safresh1 $s = $listener->socktype(); 11491f110e0Safresh1 ok(defined($s), 'type defined'); 11591f110e0Safresh1 11691f110e0Safresh1 my $new = IO::Socket::UNIX->new_from_fd($listener->fileno(), 'r+'); 11791f110e0Safresh1 11891f110e0Safresh1 is($new->sockdomain(), $d, 'domain match'); 11991f110e0Safresh1 SKIP: { 12091f110e0Safresh1 skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL }); 12191f110e0Safresh1 skip "SO_PROTOCOL defined but not implemented", 1 12291f110e0Safresh1 if !defined $new->sockopt(Socket::SO_PROTOCOL); 123*fac98b93Safresh1 skip "SO_PROTOCOL returns chosen protocol on OpenBSD", 1 124*fac98b93Safresh1 if $^O eq 'openbsd'; 12591f110e0Safresh1 is($new->protocol(), $p, 'protocol match'); 12691f110e0Safresh1 } 12791f110e0Safresh1 SKIP: { 12891f110e0Safresh1 skip "AIX: getsockopt(SO_TYPE) is badly broken on UDP/UNIX sockets", 1 12991f110e0Safresh1 if $^O eq "aix"; 13091f110e0Safresh1 skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE }); 13191f110e0Safresh1 skip "SO_TYPE defined but not implemented", 1 13291f110e0Safresh1 if !defined $new->sockopt(Socket::SO_TYPE); 13391f110e0Safresh1 is($new->socktype(), $s, 'type match'); 13491f110e0Safresh1 } 13591f110e0Safresh1} 13691f110e0Safresh1unlink($socketpath); 137