1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
#!/usr/bin/perl
use warnings;
use strict;
use File::Temp qw(tempdir);
use File::Spec::Functions;
use IO::Socket;
use IO::Socket::UNIX;
use Socket;
use Config;
use Test::More;
plan skip_all => "UNIX domain sockets not implemented on $^O"
if ($^O =~ m/^(?:qnx|nto|vos|MSWin32|VMS)$/);
my $socketpath = catfile(tempdir( CLEANUP => 1 ), 'testsock');
# check the socketpath fits in sun_path.
#
# pack_sockaddr_un() just truncates the path, this may change, but how
# it will handle such a condition is undetermined (and we might need
# to work with older versions of Socket outside of a perl build)
# https://rt.cpan.org/Ticket/Display.html?id=116819
my $name = eval { pack_sockaddr_un($socketpath) };
if (defined $name) {
my ($packed_name) = eval { unpack_sockaddr_un($name) };
if (!defined $packed_name || $packed_name ne $socketpath) {
plan skip_all => "socketpath too long for sockaddr_un";
}
}
plan tests => 15;
# start testing stream sockets:
my $listener = IO::Socket::UNIX->new(Type => SOCK_STREAM,
Listen => 1,
Local => $socketpath);
ok(defined($listener), 'stream socket created');
my $p = $listener->protocol();
{
# the value of protocol isn't well defined for AF_UNIX, when we
# create the socket we supply 0, which leaves it up to the implementation
# to select a protocol, so we (now) don't save a 0 protocol during socket
# creation. This test then breaks if the implementation doesn't support
# SO_SOCKET (at least on AF_UNIX).
# This specifically includes NetBSD, Darwin and cygwin.
# This is a TODO instead of a skip so if these ever implement SO_PROTOCOL
# we'll be notified about the passing TODO so the test can be updated.
local $TODO = "$^O doesn't support SO_PROTOCOL on AF_UNIX"
if $^O =~ /^(netbsd|darwin|cygwin|hpux|solaris|dragonfly|os390)$/;
ok(defined($p), 'protocol defined');
}
my $d = $listener->sockdomain();
ok(defined($d), 'domain defined');
my $s = $listener->socktype();
ok(defined($s), 'type defined');
SKIP: {
skip "fork not available", 4
unless $Config{d_fork} || $Config{d_pseudofork};
my $cpid = fork();
if (0 == $cpid) {
# the child:
sleep(1);
my $connector = IO::Socket::UNIX->new(Peer => $socketpath);
exit(0);
} else {
ok(defined($cpid), 'spawned a child');
}
my $new = $listener->accept();
is($new->sockdomain(), $d, 'domain match');
SKIP: {
skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL });
skip "SO_PROTOCOL defined but not implemented", 1
if !defined $new->sockopt(Socket::SO_PROTOCOL);
is($new->protocol(), $p, 'protocol match');
}
SKIP: {
skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE });
skip "SO_TYPE defined but not implemented", 1
if !defined $new->sockopt(Socket::SO_TYPE);
is($new->socktype(), $s, 'type match');
}
unlink($socketpath);
wait();
}
undef $TODO;
SKIP: {
skip "datagram unix sockets not supported on $^O", 7
if $^O eq "haiku";
# now test datagram sockets:
$listener = IO::Socket::UNIX->new(Type => SOCK_DGRAM,
Local => $socketpath);
ok(defined($listener), 'datagram socket created');
$p = $listener->protocol();
{
# see comment above
local $TODO = "$^O doesn't support SO_PROTOCOL on AF_UNIX"
if $^O =~ /^(netbsd|darwin|cygwin|hpux|solaris|dragonfly|os390)$/;
ok(defined($p), 'protocol defined');
}
$d = $listener->sockdomain();
ok(defined($d), 'domain defined');
$s = $listener->socktype();
ok(defined($s), 'type defined');
my $new = IO::Socket::UNIX->new_from_fd($listener->fileno(), 'r+');
is($new->sockdomain(), $d, 'domain match');
SKIP: {
skip "no Socket::SO_PROTOCOL", 1 if !defined(eval { Socket::SO_PROTOCOL });
skip "SO_PROTOCOL defined but not implemented", 1
if !defined $new->sockopt(Socket::SO_PROTOCOL);
skip "SO_PROTOCOL returns chosen protocol on OpenBSD", 1
if $^O eq 'openbsd';
is($new->protocol(), $p, 'protocol match');
}
SKIP: {
skip "AIX: getsockopt(SO_TYPE) is badly broken on UDP/UNIX sockets", 1
if $^O eq "aix";
skip "no Socket::SO_TYPE", 1 if !defined(eval { Socket::SO_TYPE });
skip "SO_TYPE defined but not implemented", 1
if !defined $new->sockopt(Socket::SO_TYPE);
is($new->socktype(), $s, 'type match');
}
}
unlink($socketpath);
|