Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 370355 | Differences between
and this patch

Collapse All | Expand All

(-)Net-Server-0.99.ori/lib/Net/Server/Proto/SSL.pm (-80 / +183 lines)
Lines 23-34 Link Here
23
23
24
use strict;
24
use strict;
25
use vars qw($VERSION $AUTOLOAD @ISA);
25
use vars qw($VERSION $AUTOLOAD @ISA $have_inet6 $io_socket_module);
26
use Net::Server::Proto::TCP ();
26
use IO::Socket;
27
eval { require IO::Socket::SSL; };
27
28
$@ && warn "Module IO::Socket::SSL is required for SSL.";
28
BEGIN {
29
  eval {
30
    require Socket6; import Socket6;
31
    require IO::Socket::INET6;
32
    $io_socket_module = 'IO::Socket::INET6';
33
    $have_inet6 = 1;
34
  } or do {
35
    require IO::Socket::INET;
36
    $io_socket_module = 'IO::Socket::INET';
37
  };
38
  @ISA = ( $io_socket_module );
39
}
40
41
eval {
42
  require IO::Socket::SSL; import IO::Socket::SSL;
43
  # we could add IO::Socket::SSL to a local copy of @ISA just before calling
44
  # start_SSL and do away with the $io_socket_module trick later, but this
45
  # causes perl 5.12.2 to crash, so do it the way it likes it
46
  unshift(@ISA, qw(IO::Socket::SSL));  1;
47
} or do {
48
  warn "Module IO::Socket::SSL is required for SSL: $@";
49
};
29
50
30
$VERSION = $Net::Server::VERSION; # done until separated
51
$VERSION = $Net::Server::VERSION; # done until separated
31
@ISA = qw(IO::Socket::SSL);
32
52
53
# additional protocol specific arguments
54
my @ssl_args = qw(
55
    SSL_use_cert
56
    SSL_verify_mode
57
    SSL_key_file
58
    SSL_cert_file
59
    SSL_ca_path
60
    SSL_ca_file
61
    SSL_cipher_list
62
    SSL_passwd_cb
63
    SSL_max_getline_length
64
    SSL_error_callback
65
);
33
66
34
sub object {
67
sub object {
Lines 40-48 Link Here
40
  my $host;
73
  my $host;
41
74
42
  ### allow for things like "domain.com:80"
75
  local($1,$2);
43
  if( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
76
  ### allow for things like "[::1]:80" or "[host.example.com]:80"
77
  if( $port =~ m/^\[([^\]]*)\]:(\w+)$/ ){
78
    ($host,$port) = ($1,$2);
79
80
  ### allow for things like "host.example.com:80"
81
  }elsif( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
44
    ($host,$port) = ($1,$2);
82
    ($host,$port) = ($1,$2);
45
83
46
  ### allow for things like "80"
84
  ### allow for things like "80" or "http"
47
  }elsif( $port =~ /^(\w+)$/ ){
85
  }elsif( $port =~ /^(\w+)$/ ){
48
    ($host,$port) = ($default_host,$1);
86
    ($host,$port) = ($default_host,$1);
Lines 53-135 Link Here
53
  }
91
  }
54
92
55
  # read any additional protocol specific arguments
93
  ### collect bind addresses along with their address family for all hosts
56
  my @ssl_args = qw(
94
  my @bind_tuples;
57
      SSL_server
95
  if( $host =~ /^\d{1,3}(?:\.\d{1,3}){3}\z/ ){
58
      SSL_use_cert
96
    push(@bind_tuples, [AF_INET,$host,$port]);
59
      SSL_verify_mode
97
  }elsif( $host =~ /:/ ){
60
      SSL_key_file
98
    die "No IO::Socket::INET6, cannot bind to [$host]:$port"  if !$have_inet6;
61
      SSL_cert_file
99
    push(@bind_tuples, [AF_INET6,$host,$port]);
62
      SSL_ca_path
100
  }elsif( !$have_inet6 ){
63
      SSL_ca_file
101
    push(@bind_tuples, [AF_INET,$host,$port]);
64
      SSL_cipher_list
102
  }elsif( $have_inet6 && $host =~ /\*/ ){
65
      SSL_passwd_cb
103
    push(@bind_tuples, [AF_INET6,$host,$port], [AF_INET,$host,$port]);
66
      SSL_max_getline_length
104
  }else{  # we do have IO::Socket::INET6, it handles inet6 as well as inet
67
  );
105
    # obtain a list of IP addresses for $host, resolve port name
68
  my %args;
106
    my @res1 = getaddrinfo($host, $port,
69
  $args{$_} = \$prop->{$_} for @ssl_args;
107
                           AF_UNSPEC, SOCK_STREAM, 0, AI_PASSIVE);
70
  $server->configure(\%args);
108
    die "Unresolvable [$host]:$port: $res1[0]"  if @res1 < 5;
71
109
    while (@res1 >= 5) {
72
  my $sock = $class->new;
110
      my($afam, $socktype, $proto, $saddr, $canonname);
73
  $sock->NS_host($host);
111
      ($afam, $socktype, $proto, $saddr, $canonname, @res1) = @res1;
74
  $sock->NS_port($port);
112
      my @res2 = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV);
75
  $sock->NS_proto('SSL');
113
      die "getnameinfo failed on [$host]:$port: $res2[0]"  if @res2 < 2;
114
      my($hostip,$portnum) = @res2;
115
      $server->log(4,"Resolved [$host]:$port -> [$hostip]:$portnum, AF $afam");
116
      push(@bind_tuples, [$afam,$hostip,$portnum]);
117
    }
118
  }
76
119
77
  for my $key (@ssl_args) {
120
  my @sockets_list;
78
    my $val = defined($prop->{$key}) ? $prop->{$key} : $server->can($key) ? $server->$key($host, $port, 'SSL') : undef;
121
  ### create a socket for each specified bind address and family
79
    $sock->$key($val);
122
  foreach my $tuple ( @bind_tuples ){
123
    my $afamily;  # address family (AF_* constants)
124
    my $pfamily;  # socket protocol family (PF_* constants)
125
    ($afamily,$host,$port) = @$tuple;
126
    my $sock;
127
    if( $have_inet6 ){
128
      # Using IO::Socket::INET6 to handle both the IPv4 and IPv6.
129
      # Constants PF_INET/PF_INET6 (protocol family) usually happen to have
130
      # the same value as AF_INET/AF_INET6 (address family) constants.
131
      # Still, better safe than sorry:
132
      $pfamily = $afamily == AF_INET  ? PF_INET
133
               : $afamily == AF_INET6 ? PF_INET6 : $afamily;
134
      $server->log(3,"Using IO::Socket::INET6 for [$host]:$port, PF $pfamily");
135
      $sock = IO::Socket::INET6->new(Domain => $pfamily);  # inet or inet6
136
    }else{
137
      $pfamily = PF_INET;
138
      $server->log(3,"Using IO::Socket::INET for [$host]:$port, PF $pfamily");
139
      $sock = IO::Socket::INET->new();  # inet socket (IPv4 only)
140
    }
141
142
    if ($sock) {
143
      ### create the handle under this package
144
      bless $sock, $class;
145
146
      $sock->NS_host($host);
147
      $sock->NS_port($port);
148
      $sock->NS_proto('SSL');
149
      $sock->NS_family($pfamily);  # socket protocol family
150
151
      for my $key (@ssl_args) {
152
        my $val = defined($prop->{$key}) ? $prop->{$key} : $server->can($key) ? $server->$key($host, $port, 'SSL') : undef;
153
        $sock->$key($val);
154
      }
155
      push @sockets_list, $sock;
156
    }
80
  }
157
  }
81
158
82
  return $sock;
159
  ### returns any number of sockets,
160
  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
161
  return !wantarray ? $sockets_list[0] : @sockets_list;
83
}
162
}
84
163
85
sub log_connect {
164
sub log_connect {
86
  my $sock = shift;
165
  my $sock = shift;
87
  my $server = shift;
166
  my $server  = shift;
88
  my $host   = $sock->NS_host;
167
  my $host    = $sock->NS_host; 
89
  my $port   = $sock->NS_port;
168
  my $port    = $sock->NS_port;
90
  my $proto  = $sock->NS_proto;
169
  my $proto   = $sock->NS_proto;
91
 $server->log(2,"Binding to $proto port $port on host $host\n");
170
  my $pfamily = $sock->NS_family || 0;
171
  $server->log(2,"Binding to $proto port $port on host $host, PF $pfamily\n");
92
}
172
}
93
173
94
### connect the first time
174
### bind the first time
95
sub connect {
175
sub connect {
96
  my $sock   = shift;
176
  my $sock    = shift;
97
  my $server = shift;
177
  my $server  = shift;
98
  my $prop   = $server->{server};
178
  my $prop    = $server->{server};
99
179
100
  my $host  = $sock->NS_host;
180
  my $host    = $sock->NS_host;
101
  my $port  = $sock->NS_port;
181
  my $port    = $sock->NS_port;
102
182
  my $pfamily = $sock->NS_family || 0;
103
  my %args = ();
104
  $args{LocalPort} = $port;                  # what port to bind on
105
  $args{Proto}     = 'tcp';                  # what procol to use
106
  $args{LocalAddr} = $host if $host !~ /\*/; # what local address (* is all)
107
  $args{Listen}    = $prop->{listen};        # how many connections for kernel to queue
108
  $args{Reuse}     = 1;  # allow us to rebind the port on a restart
109
110
  ### add in any ssl specific properties
111
  foreach ( keys %$prop ){
112
    next unless /^SSL_/;
113
    $args{$_} = $prop->{$_};
114
  }
115
116
  ### connect to the sock
117
  $sock->SUPER::configure(\%args)
118
    or $server->fatal("Can't connect to SSL port $port on $host [$!]");
119
120
  $server->fatal("Back sock [$!]!".caller())
121
    unless $sock;
122
183
184
  my %args;
185
  $args{LocalPort} = $port;
186
  $args{Proto}     = 'tcp';
187
  $args{LocalAddr} = $host if $host !~ /\*/;  # * is all
188
  $args{Domain}    = $pfamily  if $have_inet6 && $pfamily;
189
  $args{Listen}    = $prop->{listen};
190
  $args{Reuse}     = 1;
191
192
  ### bind to the sock using the underlying IO Socket module
193
  { local @ISA = ( $io_socket_module );
194
    $sock->SUPER::configure(\%args)
195
      or $server->fatal("Can't bind to SSL port $port on $host [$!]");
196
    $server->fatal("Bad sock [$!]!".caller())  if !$sock;
197
  }
123
}
198
}
124
199
125
### connect on a sig -HUP
200
### connect on a sig -HUP
126
sub reconnect {
201
sub reconnect {
127
  my $sock = shift;
202
  my ($sock, $fd, $server) = @_;
128
  my $fd   = shift;
129
  my $server = shift;
130
131
  $sock->fdopen( $fd, 'w' )
132
    or $server->fatal("Error opening to file descriptor ($fd) [$!]");
133
203
204
  my $host    = $sock->NS_host; 
205
  my $port    = $sock->NS_port;
206
  my $proto   = $sock->NS_proto;
207
  my $pfamily = $sock->NS_family || 0;
208
209
  $server->log(3,"Reassociating file descriptor $fd ".
210
                 "with socket $proto on [$host]:port, PF $pfamily\n");
211
212
  ### fdopen cannot be used on a IO::Socket::SSL object!!!
213
  ### use fdopen() from the underlying IO Socket package
214
  { local @ISA = ( $io_socket_module );
215
    $sock->fdopen( $fd, 'w' )
216
      or $server->fatal("Error opening to file descriptor ($fd) [$!]");
217
  }
134
}
218
}
135
219
Lines 137-148 Link Here
137
sub accept {
221
sub accept {
138
  my $sock = shift;
222
  my $sock = shift;
139
  my $client = $sock->SUPER::accept();
223
  my $client;
140
224
141
  ### pass items on
225
  ### fdopen (in reconnect) cannot be used on an IO::Socket::SSL object,
142
  if( defined($client) ){
226
  ### which is why we accept first and upgrade to SSL later
143
    bless $client, ref($sock);
227
144
    $client->NS_proto( $sock->NS_proto );
228
  ### accept() with the underlying IO Socket package, upgrade to SSL later
229
  { local @ISA = ( $io_socket_module );
230
    $client = $sock->SUPER::accept();
145
  }
231
  }
146
232
233
  if( defined $client ){
234
    $client->NS_proto( $sock->NS_proto );
235
    $client->NS_family( $sock->NS_family );
236
    $client->NS_host( $sock->NS_host );
237
    $client->NS_port( $sock->NS_port );
238
239
    ### must bless the upgraded SSL object into our package
240
    ### to be able to reference its NS_* properties later
241
    __PACKAGE__->start_SSL($client,
242
      SSL_error_trap => sub { my($sock,$msg) = @_;
243
                              die "Error upgrading socket to SSL: $msg" },
244
      SSL_server => 1,
245
      map { defined $sock->$_() ? ($_,$sock->$_()) : () } @ssl_args,
246
    ) or die "Upgrading socket to SSL failed: ".IO::Socket::SSL::errstr();
247
248
  }
147
  return $client;
249
  return $client;
148
}
250
}
Lines 158-161 Link Here
158
              $sock->NS_port,
260
              $sock->NS_port,
159
              $sock->NS_proto,
261
              $sock->NS_proto,
262
              !$have_inet6 || !$sock->NS_family ? () : $sock->NS_family,
160
              );
263
              );
161
}
264
}
Lines 165-169 Link Here
165
  my $sock = shift;
268
  my $sock = shift;
166
  my $t = "Ref = \"" .ref($sock) . "\"\n";
269
  my $t = "Ref = \"" .ref($sock) . "\"\n";
167
  foreach my $prop ( qw(NS_proto NS_port NS_host) ){
270
  foreach my $prop ( qw(NS_proto NS_port NS_host NS_family) ){
168
    $t .= "  $prop = \"" .$sock->$prop()."\"\n";
271
    $t .= "  $prop = \"" .$sock->$prop()."\"\n";
169
  }
272
  }
Lines 180-184 Link Here
180
  }
283
  }
181
284
182
  if( $prop =~ /^(NS_proto|NS_port|NS_host)$/ ){
285
  if( $prop =~ /^(NS_proto|NS_port|NS_host|NS_family|SSL_\w+)$/ ){
183
    no strict 'refs';
286
    no strict 'refs';
184
    * { __PACKAGE__ ."::". $prop } = sub {
287
    * { __PACKAGE__ ."::". $prop } = sub {
Lines 216-221 Link Here
216
319
217
This original SSL module was experimental.  It has been superceeded by
320
This original SSL module was experimental.  It has been superceeded by
218
Net::Server::Proto::SSLEAY If anybody has any successes or ideas for
321
Net::Server::Proto::SSLEAY. If anybody has any successes or ideas for
219
improvment under SSL, please email <paul@seamons.com>.
322
improvement under SSL, please email <paul@seamons.com>.
220
323
221
Protocol module for Net::Server.  This module implements a
324
Protocol module for Net::Server.  This module implements a
(-)Net-Server-0.99.ori/lib/Net/Server/Proto/SSLEAY.pm (-119 / +227 lines)
Lines 23-176 Link Here
23
23
24
use strict;
24
use strict;
25
use vars qw($VERSION $AUTOLOAD @ISA);
25
use vars qw($VERSION $AUTOLOAD @ISA $have_inet6);
26
use IO::Socket::INET;
27
use Fcntl ();
26
use Fcntl ();
28
use Errno ();
27
use Errno ();
29
use Socket ();
28
use Socket ();
29
use IO::Socket;
30
30
31
BEGIN {
31
BEGIN {
32
    eval { require Net::SSLeay };
32
  eval {
33
    $@ && warn "Module Net::SSLeay is required for SSLeay.";
33
    require Socket6; import Socket6;
34
    # Net::SSLeay gets mad if we call these multiple times - the question is - who will call them multiple times?
34
    require IO::Socket::INET6;
35
    for my $sub (qw(load_error_strings SSLeay_add_ssl_algorithms ENGINE_load_builtin_engines ENGINE_register_all_complete randomize)) {
35
    @ISA = qw(IO::Socket::INET6);
36
        Net::SSLeay->can($sub)->();
36
    $have_inet6 = 1;
37
    }
37
  } or do {
38
    require IO::Socket::INET;
39
    @ISA = qw(IO::Socket::INET);
40
  };
41
  eval { require Net::SSLeay };
42
  $@ && warn "Module Net::SSLeay is required for SSLeay.";
43
  # Net::SSLeay gets mad if we call these multiple times - the question is - who will call them multiple times?
44
  for my $sub (qw(load_error_strings SSLeay_add_ssl_algorithms ENGINE_load_builtin_engines ENGINE_register_all_complete randomize)) {
45
    Net::SSLeay->can($sub)->();
46
  }
38
}
47
}
39
48
40
$VERSION = $Net::Server::VERSION; # done until separated
49
$VERSION = $Net::Server::VERSION; # done until separated
41
@ISA = qw(IO::Socket::INET);
50
51
# additional protocol specific arguments
52
my @ssl_args = qw(
53
    SSL_use_cert
54
    SSL_verify_mode
55
    SSL_key_file
56
    SSL_cert_file
57
    SSL_ca_path
58
    SSL_ca_file
59
    SSL_cipher_list
60
    SSL_passwd_cb
61
    SSL_max_getline_length
62
    SSL_error_callback
63
);
42
64
43
sub object {
65
sub object {
44
    my $type  = shift;
66
  my $type  = shift;
45
    my $class = ref($type) || $type || __PACKAGE__;
67
  my $class = ref($type) || $type || __PACKAGE__;
46
68
47
    my ($default_host,$port,$server) = @_;
69
  my ($default_host,$port,$server) = @_;
48
    my $prop = $server->{'server'};
70
  my $host;
49
    my $host;
71
  my $prop = $server->{'server'};
50
72
51
    if ($port =~ m/^([\w\.\-\*\/]+):(\w+)$/) { # allow for things like "domain.com:80"
73
  local($1,$2);
52
        ($host, $port) = ($1, $2);
74
  ### allow for things like "[::1]:80" or "[host.example.com]:80"
53
    }
75
  if( $port =~ m/^\[([^\]]*)\]:(\w+)$/ ){
54
    elsif ($port =~ /^(\w+)$/) { # allow for things like "80"
76
    ($host,$port) = ($1,$2);
55
        ($host, $port) = ($default_host, $1);
77
56
    }
78
  ### allow for things like "host.example.com:80"
57
    else {
79
  }elsif( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
58
        $server->fatal("Undeterminate port \"$port\" under ".__PACKAGE__);
80
    ($host,$port) = ($1,$2);
59
    }
81
60
82
  ### allow for things like "80" or "http"
61
    # read any additional protocol specific arguments
83
  }elsif( $port =~ /^(\w+)$/ ){
62
    my @ssl_args = qw(
84
    ($host,$port) = ($default_host,$1);
63
        SSL_server
85
64
        SSL_use_cert
86
  ### don't know that style of port
65
        SSL_verify_mode
87
  }else{
66
        SSL_key_file
88
    $server->fatal("Undeterminate port \"$port\" under ".__PACKAGE__);
67
        SSL_cert_file
89
  }
68
        SSL_ca_path
90
69
        SSL_ca_file
91
  ### collect bind addresses along with their address family for all hosts
70
        SSL_cipher_list
92
  my @bind_tuples;
71
        SSL_passwd_cb
93
  if( $host =~ /^\d{1,3}(?:\.\d{1,3}){3}\z/ ){
72
        SSL_error_callback
94
    push(@bind_tuples, [AF_INET,$host,$port]);
73
        SSL_max_getline_length
95
  }elsif( $host =~ /:/ ){
74
    );
96
    die "No IO::Socket::INET6, cannot bind to [$host]:$port"  if !$have_inet6;
75
    my %args;
97
    push(@bind_tuples, [AF_INET6,$host,$port]);
76
    $args{$_} = \$prop->{$_} for @ssl_args;
98
  }elsif( !$have_inet6 ){
77
    $server->configure(\%args);
99
    push(@bind_tuples, [AF_INET,$host,$port]);
78
100
  }elsif( $have_inet6 && $host =~ /\*/ ){
79
    my $sock = $class->new;
101
    push(@bind_tuples, [AF_INET6,$host,$port], [AF_INET,$host,$port]);
80
    $sock->NS_host($host);
102
  }else{  # we do have IO::Socket::INET6, it handles inet6 as well as inet
81
    $sock->NS_port($port);
103
    # obtain a list of IP addresses for $host, resolve port name
82
    $sock->NS_proto('SSLEAY');
104
    my @res1 = getaddrinfo($host, $port,
105
                           AF_UNSPEC, SOCK_STREAM, 0, AI_PASSIVE);
106
    die "Unresolvable [$host]:$port: $res1[0]"  if @res1 < 5;
107
    while (@res1 >= 5) {
108
      my($afam, $socktype, $proto, $saddr, $canonname);
109
      ($afam, $socktype, $proto, $saddr, $canonname, @res1) = @res1;
110
      my @res2 = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV);
111
      die "getnameinfo failed on [$host]:$port: $res2[0]"  if @res2 < 2;
112
      my($hostip,$portnum) = @res2;
113
      $server->log(4,"Resolved [$host]:$port -> [$hostip]:$portnum, AF $afam");
114
      push(@bind_tuples, [$afam,$hostip,$portnum]);
115
    }
116
  }
117
118
  my @sockets_list;
119
  ### create a socket for each specified bind address and family
120
  foreach my $tuple ( @bind_tuples ){
121
    my $afamily;  # address family (AF_* constants)
122
    my $pfamily;  # socket protocol family (PF_* constants)
123
    ($afamily,$host,$port) = @$tuple;
124
    my $sock;
125
    if( $have_inet6 ){
126
      # Using IO::Socket::INET6 to handle both the IPv4 and IPv6.
127
      # Constants PF_INET/PF_INET6 (protocol family) usually happen to have
128
      # the same value as AF_INET/AF_INET6 (address family) constants.
129
      # Still, better safe than sorry:
130
      $pfamily = $afamily == AF_INET  ? PF_INET
131
               : $afamily == AF_INET6 ? PF_INET6 : $afamily;
132
      $server->log(3,"Using IO::Socket::INET6 for [$host]:$port, PF $pfamily");
133
      $sock = IO::Socket::INET6->new(Domain => $pfamily);  # inet or inet6
134
    }else{
135
      $pfamily = PF_INET;
136
      $server->log(3,"Using IO::Socket::INET for [$host]:$port, PF $pfamily");
137
      $sock = IO::Socket::INET->new();  # inet socket (IPv4 only)
138
    }
139
140
    if ($sock) {
141
      bless $sock, $class;
142
143
      $sock->NS_host($host);
144
      $sock->NS_port($port);
145
      $sock->NS_proto('SSLEAY');
146
      $sock->NS_family($pfamily);  # socket protocol family
83
147
84
    for my $key (@ssl_args) {
148
      for my $key (@ssl_args) {
85
        my $val = defined($prop->{$key}) ? $prop->{$key} : $server->can($key) ? $server->$key($host, $port, 'SSLEAY') : undef;
149
        my $val = defined($prop->{$key}) ? $prop->{$key} : $server->can($key) ? $server->$key($host, $port, 'SSLEAY') : undef;
86
        $sock->$key($val);
150
        $sock->$key($val);
151
      }
152
      push @sockets_list, $sock;
87
    }
153
    }
154
  }
88
155
89
    return $sock;
156
  ### returns any number of sockets,
157
  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
158
  return !wantarray ? $sockets_list[0] : @sockets_list;
90
}
159
}
91
160
92
sub log_connect {
161
sub log_connect {
93
    my $sock = shift;
162
  my $sock = shift;
94
    my $server = shift;
163
  my $server  = shift;
95
    my $host   = $sock->NS_host;
164
  my $host    = $sock->NS_host; 
96
    my $port   = $sock->NS_port;
165
  my $port    = $sock->NS_port;
97
    my $proto  = $sock->NS_proto;
166
  my $proto   = $sock->NS_proto;
98
    $server->log(2,"Binding to $proto port $port on host $host\n");
167
  my $pfamily = $sock->NS_family || 0;
168
  $server->log(2,"Binding to $proto port $port on host $host, PF $pfamily\n");
99
}
169
}
100
170
101
###----------------------------------------------------------------###
171
###----------------------------------------------------------------###
102
172
103
sub connect { # connect the first time
173
### bind the first time
104
    my $sock   = shift;
174
sub connect {
105
    my $server = shift;
175
  my $sock    = shift;
106
    my $prop   = $server->{'server'};
176
  my $server  = shift;
107
177
  my $prop    = $server->{server};
108
    my $host  = $sock->NS_host;
178
109
    my $port  = $sock->NS_port;
179
  my $host    = $sock->NS_host;
110
180
  my $port    = $sock->NS_port;
111
    my %args;
181
  my $pfamily = $sock->NS_family || 0;
112
    $args{'LocalPort'} = $port;
182
113
    $args{'Proto'}     = 'tcp';
183
  my %args;
114
    $args{'LocalAddr'} = $host if $host !~ /\*/; # * is all
184
  $args{LocalPort} = $port;
115
    $args{'Listen'}    = $prop->{'listen'};
185
  $args{Proto}     = 'tcp';
116
    $args{'Reuse'}     = 1;
186
  $args{LocalAddr} = $host if $host !~ /\*/;  # * is all
117
187
  $args{Domain}    = $pfamily  if $have_inet6 && $pfamily;
118
    $sock->SUPER::configure(\%args) || $server->fatal("Can't connect to SSL port $port on $host [$!]");
188
  $args{Listen}    = $prop->{listen};
119
    $server->fatal("Bad sock [$!]!".caller()) if ! $sock;
189
  $args{Reuse}     = 1;
120
190
121
    if ($port == 0 && ($port = $sock->sockport)) {
191
  $sock->SUPER::configure(\%args)
122
        $sock->NS_port($port);
192
    or $server->fatal("Can't bind to SSL port $port on $host [$!]");
123
        $server->log(2,"Bound to auto-assigned port $port");
193
  $server->fatal("Bad sock [$!]!".caller())  if !$sock;
124
    }
194
125
195
  my $actual_port = $sock->sockport;
126
    $sock->bind_SSL($server);
196
  # $port may be a service name, compare as strings
127
}
197
  if( $actual_port && (!defined $port || $actual_port ne $port) ){
128
198
    $sock->NS_port($actual_port);
129
sub reconnect { # connect on a sig -HUP
199
    if( $port =~ /^0*\z/ ){
130
    my ($sock, $fd, $server) = @_;
200
      $server->log(2,"Bound to auto-assigned port $actual_port");
131
    my $resp = $sock->fdopen( $fd, 'w' ) || $server->fatal("Error opening to file descriptor ($fd) [$!]");
201
    }else{
132
    $sock->bind_SSL($server);
202
      $server->log(3,"Bound to service \"$port\", port number $actual_port");
133
    return $resp;
203
    }
204
  }
205
206
  $sock->bind_SSL($server);
207
}
208
209
### reassociate sockets with inherited file descriptors on a sig -HUP
210
sub reconnect {
211
  my ($sock, $fd, $server) = @_;
212
213
  my $host    = $sock->NS_host; 
214
  my $port    = $sock->NS_port;
215
  my $proto   = $sock->NS_proto;
216
  my $pfamily = $sock->NS_family || 0;
217
218
  $server->log(3,"Reassociating file descriptor $fd ".
219
                 "with socket $proto on [$host]:port, PF $pfamily\n");
220
  my $resp = $sock->fdopen( $fd, 'w' )
221
    or $server->fatal("Error opening to file descriptor ($fd) [$!]");
222
  $sock->bind_SSL($server);
223
  return $resp;
134
}
224
}
135
225
136
sub bind_SSL {
226
sub bind_SSL {
137
    my ($sock, $server) = @_;
227
  my ($sock, $server) = @_;
138
    my $ctx = Net::SSLeay::CTX_new();  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_new");
228
  my $ctx = Net::SSLeay::CTX_new();  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_new");
139
229
140
    Net::SSLeay::CTX_set_options($ctx, Net::SSLeay::OP_ALL());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_set_options");
230
  Net::SSLeay::CTX_set_options($ctx, Net::SSLeay::OP_ALL());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_set_options");
141
231
142
    # 0x1:  SSL_MODE_ENABLE_PARTIAL_WRITE
232
  # 0x1:  SSL_MODE_ENABLE_PARTIAL_WRITE
143
    # 0x10: SSL_MODE_RELEASE_BUFFERS (ignored before OpenSSL v1.0.0)
233
  # 0x10: SSL_MODE_RELEASE_BUFFERS (ignored before OpenSSL v1.0.0)
144
    Net::SSLeay::CTX_set_mode($ctx, 0x11);  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_set_mode");
234
  Net::SSLeay::CTX_set_mode($ctx, 0x11);  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_set_mode");
145
235
146
    # Load certificate. This will prompt for a password if necessary.
236
  # Load certificate. This will prompt for a password if necessary.
147
    my $file_key  = $sock->SSL_key_file  || die "SSLeay missing SSL_key_file.\n";
237
  my $file_key  = $sock->SSL_key_file  || die "SSLeay missing SSL_key_file.\n";
148
    my $file_cert = $sock->SSL_cert_file || die "SSLeay missing SSL_cert_file.\n";
238
  my $file_cert = $sock->SSL_cert_file || die "SSLeay missing SSL_cert_file.\n";
149
    Net::SSLeay::CTX_use_RSAPrivateKey_file($ctx, $file_key,  Net::SSLeay::FILETYPE_PEM());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_use_RSAPrivateKey_file");
239
  Net::SSLeay::CTX_use_RSAPrivateKey_file($ctx, $file_key,  Net::SSLeay::FILETYPE_PEM());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_use_RSAPrivateKey_file");
150
    Net::SSLeay::CTX_use_certificate_file(  $ctx, $file_cert, Net::SSLeay::FILETYPE_PEM());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_use_certificate_file");
240
  Net::SSLeay::CTX_use_certificate_file(  $ctx, $file_cert, Net::SSLeay::FILETYPE_PEM());  $sock->SSLeay_check_fatal("SSLeay bind_SSL CTX_use_certificate_file");
151
    $sock->SSLeay_context($ctx);
241
  $sock->SSLeay_context($ctx);
152
}
242
}
153
243
154
sub close {
244
sub close {
155
    my $sock = shift;
245
  my $sock = shift;
156
    if ($sock->SSLeay_is_client) {
246
  if ($sock->SSLeay_is_client) {
157
        Net::SSLeay::free($sock->SSLeay);
247
    Net::SSLeay::free($sock->SSLeay);
158
    } else {
248
  } else {
159
        Net::SSLeay::CTX_free($sock->SSLeay_context);
249
    Net::SSLeay::CTX_free($sock->SSLeay_context);
160
    }
250
  }
161
    $sock->SSLeay_check_fatal("SSLeay close free");
251
  $sock->SSLeay_check_fatal("SSLeay close free");
162
    return $sock->SUPER::close(@_);
252
  return $sock->SUPER::close(@_);
163
}
253
}
164
254
165
sub accept {
255
sub accept {
166
    my $sock = shift;
256
  my $sock = shift;
167
    my $client = $sock->SUPER::accept;
257
  my $client = $sock->SUPER::accept;
168
    if (defined $client) {
258
  if (defined $client) {
169
        $client->NS_proto($sock->NS_proto);
259
    $client->NS_proto( $sock->NS_proto );
170
        $client->SSLeay_context($sock->SSLeay_context);
260
    $client->NS_family( $sock->NS_family );
171
        $client->SSLeay_is_client(1);
261
    $client->NS_host( $sock->NS_host );
172
    }
262
    $client->NS_port( $sock->NS_port );
263
    $client->SSLeay_context( $sock->SSLeay_context );
264
    $client->SSLeay_is_client(1);
265
  }
173
266
174
    return $client;
267
  return $client;
175
}
268
}
176
269
Lines 281-284 Link Here
281
}
374
}
282
375
376
sub sysread {
377
    my ($client, $buf, $size, $offset) = @_;
378
    warn "sysread is not supported by Net::Server::Proto::SSLEAY";
379
    # not quite right, usable only for testing:
380
    my ($ok, $read) = $client->read_until($size, $/, 1);
381
    substr($_[1], $offset || 0, defined($buf) ? length($buf) : 0, $read);
382
    # should return the number of bytes actually read, 0 at end of file, or
383
    # undef if there was an error (in the latter case $! should also be set)
384
    return length $read;
385
}
386
283
sub getline {
387
sub getline {
284
    my $client = shift;
388
    my $client = shift;
Lines 331-335 Link Here
331
}
435
}
332
436
333
sub sysread  { die "sysread is not supported by Net::Server::Proto::SSLEAY" }
334
sub syswrite { die "syswrite is not supported by Net::Server::Proto::SSLEAY" }
437
sub syswrite { die "syswrite is not supported by Net::Server::Proto::SSLEAY" }
335
438
Lines 338-342 Link Here
338
sub hup_string {
441
sub hup_string {
339
    my $sock = shift;
442
    my $sock = shift;
340
    return join "|", map{$sock->$_()} qw(NS_host NS_port NS_proto);
443
    return join("|",
444
                $sock->NS_host,
445
                $sock->NS_port,
446
                $sock->NS_proto,
447
                !$have_inet6 || !$sock->NS_family ? () : $sock->NS_family,
448
              );
341
}
449
}
342
450
Lines 344-348 Link Here
344
    my $sock = shift;
452
    my $sock = shift;
345
    my $t = "Ref = \"" .ref($sock) . "\"\n";
453
    my $t = "Ref = \"" .ref($sock) . "\"\n";
346
    foreach my $prop ( qw(NS_proto NS_port NS_host SSLeay_context SSLeay_is_client) ){
454
    foreach my $prop ( qw(NS_proto NS_port NS_host NS_family SSLeay_context SSLeay_is_client) ){
347
        $t .= "  $prop = \"" .$sock->$prop()."\"\n";
455
        $t .= "  $prop = \"" .$sock->$prop()."\"\n";
348
    }
456
    }
Lines 354-358 Link Here
354
    my $prop = $AUTOLOAD =~ /::([^:]+)$/ ? $1 : die "Missing property in AUTOLOAD.";
462
    my $prop = $AUTOLOAD =~ /::([^:]+)$/ ? $1 : die "Missing property in AUTOLOAD.";
355
    die "Unknown method or property [$prop]"
463
    die "Unknown method or property [$prop]"
356
        if $prop !~ /^(NS_proto|NS_port|NS_host|SSLeay_context|SSLeay_is_client|SSL_\w+)$/;
464
        if $prop !~ /^(NS_proto|NS_port|NS_host|NS_family|SSLeay_context|SSLeay_is_client|SSL_\w+)$/;
357
465
358
    no strict 'refs';
466
    no strict 'refs';
(-)Net-Server-0.99.ori/lib/Net/Server/Proto/TCP.pm (-42 / +129 lines)
Lines 23-31 Link Here
23
23
24
use strict;
24
use strict;
25
use vars qw($VERSION $AUTOLOAD @ISA);
25
use vars qw($VERSION $AUTOLOAD @ISA $have_inet6);
26
use IO::Socket ();
26
use IO::Socket;
27
28
BEGIN {
29
  eval {
30
    require Socket6; import Socket6;
31
    require IO::Socket::INET6;
32
    @ISA = qw(IO::Socket::INET6);
33
    $have_inet6 = 1;
34
  } or do {
35
    require IO::Socket::INET;
36
    @ISA = qw(IO::Socket::INET);
37
  };
38
}
27
39
28
$VERSION = $Net::Server::VERSION; # done until separated
40
$VERSION = $Net::Server::VERSION; # done until separated
29
@ISA = qw(IO::Socket::INET);
30
41
31
sub object {
42
sub object {
Lines 36-44 Link Here
36
  my $host;
47
  my $host;
37
48
38
  ### allow for things like "domain.com:80"
49
  local($1,$2);
39
  if( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
50
  ### allow for things like "[::1]:80" or "[host.example.com]:80"
51
  if( $port =~ m/^\[([^\]]*)\]:(\w+)$/ ){
52
    ($host,$port) = ($1,$2);
53
54
  ### allow for things like "host.example.com:80"
55
  }elsif( $port =~ m/^([\w\.\-\*\/]+):(\w+)$/ ){
40
    ($host,$port) = ($1,$2);
56
    ($host,$port) = ($1,$2);
41
57
42
  ### allow for things like "80"
58
  ### allow for things like "80" or "http"
43
  }elsif( $port =~ /^(\w+)$/ ){
59
  }elsif( $port =~ /^(\w+)$/ ){
44
    ($host,$port) = ($default_host,$1);
60
    ($host,$port) = ($default_host,$1);
Lines 49-111 Link Here
49
  }
65
  }
50
66
51
  ### create the handle under this package
67
  ### collect bind addresses along with their address family for all hosts
52
  my $sock = $class->SUPER::new();
68
  my @bind_tuples;
69
  if( $host =~ /^\d{1,3}(?:\.\d{1,3}){3}\z/ ){
70
    push(@bind_tuples, [AF_INET,$host,$port]);
71
  }elsif( $host =~ /:/ ){
72
    die "No IO::Socket::INET6, cannot bind to [$host]:$port"  if !$have_inet6;
73
    push(@bind_tuples, [AF_INET6,$host,$port]);
74
  }elsif( !$have_inet6 ){
75
    push(@bind_tuples, [AF_INET,$host,$port]);
76
  }elsif( $have_inet6 && $host =~ /\*/ ){
77
    push(@bind_tuples, [AF_INET6,$host,$port], [AF_INET,$host,$port]);
78
  }else{  # we do have IO::Socket::INET6, it handles inet6 as well as inet
79
    # obtain a list of IP addresses for $host, resolve port name
80
    my @res1 = getaddrinfo($host, $port,
81
                           AF_UNSPEC, SOCK_STREAM, 0, AI_PASSIVE);
82
    die "Unresolvable [$host]:$port: $res1[0]"  if @res1 < 5;
83
    while (@res1 >= 5) {
84
      my($afam, $socktype, $proto, $saddr, $canonname);
85
      ($afam, $socktype, $proto, $saddr, $canonname, @res1) = @res1;
86
      my @res2 = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV);
87
      die "getnameinfo failed on [$host]:$port: $res2[0]"  if @res2 < 2;
88
      my($hostip,$portnum) = @res2;
89
      $server->log(4,"Resolved [$host]:$port -> [$hostip]:$portnum, AF $afam");
90
      push(@bind_tuples, [$afam,$hostip,$portnum]);
91
    }
92
  }
93
94
  my @sockets_list;
95
  ### create a socket for each specified bind address and family
96
  foreach my $tuple ( @bind_tuples ){
97
    my $afamily;  # address family (AF_* constants)
98
    my $pfamily;  # socket protocol family (PF_* constants)
99
    ($afamily,$host,$port) = @$tuple;
100
    my $sock;
101
    if( $have_inet6 ){
102
      # Using IO::Socket::INET6 to handle both the IPv4 and IPv6.
103
      # Constants PF_INET/PF_INET6 (protocol family) usually happen to have
104
      # the same value as AF_INET/AF_INET6 (address family) constants.
105
      # Still, better safe than sorry:
106
      $pfamily = $afamily == AF_INET  ? PF_INET
107
               : $afamily == AF_INET6 ? PF_INET6 : $afamily;
108
      $server->log(3,"Using IO::Socket::INET6 for [$host]:$port, PF $pfamily");
109
      $sock = IO::Socket::INET6->new(Domain => $pfamily);  # inet or inet6
110
    }else{
111
      $pfamily = PF_INET;
112
      $server->log(3,"Using IO::Socket::INET for [$host]:$port, PF $pfamily");
113
      $sock = IO::Socket::INET->new();  # inet socket (IPv4 only)
114
    }
53
115
54
  ### store some properties
116
    if ($sock) {
55
  $sock->NS_host($host);
117
      ### create the handle under this package
56
  $sock->NS_port($port);
118
      bless $sock, $class;
57
  $sock->NS_proto('TCP');
119
120
      ### store some properties
121
      $sock->NS_host($host);
122
      $sock->NS_port($port);
123
      $sock->NS_proto('TCP');
124
      $sock->NS_family($pfamily);  # socket protocol family
125
      push @sockets_list, $sock;
126
    }
127
  }
58
128
59
  return $sock;
129
  ### returns any number of sockets,
130
  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
131
  return !wantarray ? $sockets_list[0] : @sockets_list;
60
}
132
}
61
133
62
sub log_connect {
134
sub log_connect {
63
  my $sock = shift;
135
  my $sock = shift;
64
  my $server = shift;
136
  my $server  = shift;
65
  my $host   = $sock->NS_host; 
137
  my $host    = $sock->NS_host; 
66
  my $port   = $sock->NS_port;
138
  my $port    = $sock->NS_port;
67
  my $proto  = $sock->NS_proto;
139
  my $proto   = $sock->NS_proto;
68
 $server->log(2,"Binding to $proto port $port on host $host\n");
140
  my $pfamily = $sock->NS_family || 0;
141
  $server->log(2,"Binding to $proto port $port on host $host, PF $pfamily\n");
69
}
142
}
70
143
71
### connect the first time
144
### bind the first time
72
sub connect {
145
sub connect {
73
  my $sock   = shift;
146
  my $sock    = shift;
74
  my $server = shift;
147
  my $server  = shift;
75
  my $prop   = $server->{server};
148
  my $prop    = $server->{server};
149
150
  my $host    = $sock->NS_host;
151
  my $port    = $sock->NS_port;
152
  my $pfamily = $sock->NS_family || 0;
76
153
77
  my $host  = $sock->NS_host;
154
  my %args;
78
  my $port  = $sock->NS_port;
79
80
  my %args = ();
81
  $args{LocalPort} = $port;                  # what port to bind on
155
  $args{LocalPort} = $port;                  # what port to bind on
82
  $args{Proto}     = 'tcp';                  # what procol to use
156
  $args{Proto}     = 'tcp';                  # what procol to use
83
  $args{LocalAddr} = $host if $host !~ /\*/; # what local address (* is all)
157
  $args{LocalAddr} = $host if $host !~ /\*/; # what local address (* is all)
158
  $args{Domain}    = $pfamily  if $have_inet6 && $pfamily;
84
  $args{Listen}    = $prop->{listen};        # how many connections for kernel to queue
159
  $args{Listen}    = $prop->{listen};        # how many connections for kernel to queue
85
  $args{Reuse}     = 1;  # allow us to rebind the port on a restart
160
  $args{Reuse}     = 1;  # allow us to rebind the port on a restart
86
161
87
  ### connect to the sock
162
  ### bind the sock
88
  $sock->SUPER::configure(\%args)
163
  $sock->SUPER::configure(\%args)
89
    or $server->fatal("Can't connect to TCP port $port on $host [$!]");
164
    or $server->fatal("Can't bind to TCP port $port on $host [$!]");
165
  $server->fatal("Bad sock [$!]!".caller())  if !$sock;
90
166
91
  if ($port == 0 && ($port = $sock->sockport)) {
167
  my $actual_port = $sock->sockport;
92
    $sock->NS_port($port);
168
  # $port may be a service name, compare as strings
93
    $server->log(2,"Bound to auto-assigned port $port");
169
  if( $actual_port && (!defined $port || $actual_port ne $port) ){
170
    $sock->NS_port($actual_port);
171
    if( $port =~ /^0*\z/ ){
172
      $server->log(2,"Bound to auto-assigned port $actual_port");
173
    }else{
174
      $server->log(3,"Bound to service \"$port\", port number $actual_port");
175
    }
94
  }
176
  }
95
177
96
  $server->fatal("Back sock [$!]!".caller())
97
    unless $sock;
98
99
}
178
}
100
179
101
### connect on a sig -HUP
180
### reassociate sockets with inherited file descriptors on a sig -HUP
102
sub reconnect {
181
sub reconnect {
103
  my $sock = shift;
182
  my ($sock, $fd, $server) = @_;
104
  my $fd   = shift;
105
  my $server = shift;
106
183
184
  my $host    = $sock->NS_host; 
185
  my $port    = $sock->NS_port;
186
  my $proto   = $sock->NS_proto;
187
  my $pfamily = $sock->NS_family || 0;
188
189
  $server->log(3,"Reassociating file descriptor $fd ".
190
                 "with socket $proto on [$host]:port, PF $pfamily\n");
107
  $sock->fdopen( $fd, 'w' )
191
  $sock->fdopen( $fd, 'w' )
108
    or $server->fatal("Error opening to file descriptor ($fd) [$!]");
192
    or $server->fatal("Error opening to file descriptor ($fd) [$!]");
109
110
}
193
}
111
194
Lines 116-121 Link Here
116
199
117
  ### pass items on
200
  ### pass items on
118
  if( defined($client) ){
201
  if( defined $client ){
119
    $client->NS_proto( $sock->NS_proto );
202
    $client->NS_proto( $sock->NS_proto );
203
    $client->NS_family( $sock->NS_family );
204
    $client->NS_host( $sock->NS_host );
205
    $client->NS_port( $sock->NS_port );
120
  }
206
  }
121
207
Lines 157-160 Link Here
157
              $sock->NS_port,
243
              $sock->NS_port,
158
              $sock->NS_proto,
244
              $sock->NS_proto,
245
              !$have_inet6 || !$sock->NS_family ? () : $sock->NS_family,
159
              );
246
              );
160
}
247
}
Lines 164-168 Link Here
164
  my $sock = shift;
251
  my $sock = shift;
165
  my $t = "Ref = \"" .ref($sock) . "\"\n";
252
  my $t = "Ref = \"" .ref($sock) . "\"\n";
166
  foreach my $prop ( qw(NS_proto NS_port NS_host) ){
253
  foreach my $prop ( qw(NS_proto NS_port NS_host NS_family) ){
167
    $t .= "  $prop = \"" .$sock->$prop()."\"\n";
254
    $t .= "  $prop = \"" .$sock->$prop()."\"\n";
168
  }
255
  }
Lines 179-183 Link Here
179
  }
266
  }
180
267
181
  if( $prop =~ /^(NS_proto|NS_port|NS_host|NS_recv_len|NS_recv_flags)$/ ){
268
  if( $prop =~ /^(NS_proto|NS_port|NS_host|NS_family|NS_recv_len|NS_recv_flags)$/ ){
182
    no strict 'refs';
269
    no strict 'refs';
183
    * { __PACKAGE__ ."::". $prop } = sub {
270
    * { __PACKAGE__ ."::". $prop } = sub {
(-)Net-Server-0.99.ori/lib/Net/Server/Proto/UDP.pm (-19 / +23 lines)
Lines 35-43 Link Here
35
  my $class = ref($type) || $type || __PACKAGE__;
35
  my $class = ref($type) || $type || __PACKAGE__;
36
36
37
  my $sock = $class->SUPER::object( @_ );
38
39
  $sock->NS_proto('UDP');
40
41
  ### set a few more parameters
42
  my($default_host,$port,$server) = @_;
37
  my($default_host,$port,$server) = @_;
43
  my $prop = $server->{server};
38
  my $prop = $server->{server};
Lines 62-94 Link Here
62
    && $prop->{udp_broadcast};
57
    && $prop->{udp_broadcast};
63
58
64
  $sock->NS_recv_len(   $prop->{udp_recv_len} );
59
  my @sockets_list = $class->SUPER::object( @_ );
65
  $sock->NS_recv_flags( $prop->{udp_recv_flags} );
66
60
67
  return $sock;
61
  foreach my $sock ( @sockets_list ){
62
    $sock->NS_proto('UDP');
63
    $sock->NS_recv_len(   $prop->{udp_recv_len} );
64
    $sock->NS_recv_flags( $prop->{udp_recv_flags} );
65
  }
66
67
  ### returns any number of sockets,
68
  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
69
  return !wantarray ? $sockets_list[0] : @sockets_list;
68
}
70
}
69
71
70
72
71
### connect the first time
73
### bind the first time
72
### doesn't support the listen or the reuse option
74
### doesn't support the listen or the reuse option
73
sub connect {
75
sub connect {
74
  my $sock   = shift;
76
  my $sock    = shift;
75
  my $server = shift;
77
  my $server  = shift;
76
  my $prop   = $server->{server};
78
  my $prop    = $server->{server};
77
79
78
  my $host  = $sock->NS_host;
80
  my $host    = $sock->NS_host;
79
  my $port  = $sock->NS_port;
81
  my $port    = $sock->NS_port;
82
  my $pfamily = $sock->NS_family || 0;
80
83
81
  my %args = ();
84
  my %args;
82
  $args{LocalPort} = $port;                  # what port to bind on
85
  $args{LocalPort} = $port;                  # what port to bind on
83
  $args{Proto}     = 'udp';                  # what procol to use
86
  $args{Proto}     = 'udp';                  # what procol to use
84
  $args{LocalAddr} = $host if $host !~ /\*/; # what local address (* is all)
87
  $args{LocalAddr} = $host if $host !~ /\*/; # what local address (* is all)
88
  $args{Domain} = $pfamily  if $Net::Server::Proto::TCP::have_inet6 && $pfamily;
85
  $args{Reuse}     = 1;  # allow us to rebind the port on a restart
89
  $args{Reuse}     = 1;  # allow us to rebind the port on a restart
86
  $args{Broadcast} = 1 if $prop->{udp_broadcast};
90
  $args{Broadcast} = 1 if $prop->{udp_broadcast};
87
91
88
  ### connect to the sock
92
  ### bind to the sock
89
  $sock->SUPER::configure(\%args)
93
  $sock->SUPER::configure(\%args)
90
    or $server->fatal("Can't connect to UDP port $port on $host [$!]");
94
    or $server->fatal("Can't bind to UDP port $port on $host [$!]");
91
95
92
  $server->fatal("Back sock [$!]!".caller())
96
  $server->fatal("Bad sock [$!]!".caller())
93
    unless $sock;
97
    unless $sock;
94
98
(-)Net-Server-0.99.ori/lib/Net/Server/Proto.pm (-7 / +22 lines)
Lines 69-73 Link Here
69
69
70
70
71
  ### return an object of that procol class
71
  ### returns any number of objects (socket),
72
  ### one for each protocol family (PF_INET or PF_INET6) and each bind address
72
  return $proto_class->object($default_host,$port,$server);
73
  return $proto_class->object($default_host,$port,$server);
73
74
Lines 84-88 Link Here
84
=head1 SYNOPSIS
85
=head1 SYNOPSIS
85
86
86
  # Net::Server::Proto and its accompianying modules are not
87
  # Net::Server::Proto and its accompanying modules are not
87
  # intended to be used outside the scope of Net::Server.
88
  # intended to be used outside the scope of Net::Server.
88
89
Lines 103-107 Link Here
103
  
104
  
104
  ### Net::Server::Proto will attempt to interface with
105
  ### Net::Server::Proto will attempt to interface with
105
  ### sub modules named simillar to Net::Server::Proto::TCP
106
  ### sub modules named similar to Net::Server::Proto::TCP
106
  ### Individual sub modules will be loaded by
107
  ### Individual sub modules will be loaded by
107
  ### Net::Server::Proto as they are needed.
108
  ### Net::Server::Proto as they are needed.
Lines 225-232 Link Here
225
The port is the most important argument passed to the sub
226
The port is the most important argument passed to the sub
226
module classes and to Net::Server::Proto itself.  For tcp,
227
module classes and to Net::Server::Proto itself.  For tcp,
227
udp, and ssl style ports, the form is generally
228
udp, and ssl style ports, the form is generally host:port/protocol
228
host:port/protocol, host|port|protocol, host/port, or port.
229
or [host]:port/protocol, host|port|protocol, host/port, or port.
229
For unix the form is generally socket_file|type|unix or 
230
If I<host> is a numerical IPv6 address it must be enclosed in square
230
socket_file.  
231
brackets to avoid ambiguity in parsing a port number, e.g.: "[::1]:80".
232
For unix sockets the form is generally socket_file|type|unix or socket_file.
233
234
A socket protocol family PF_INET or PF_INET6 is derived from a specified
235
address family of the binding address. A PF_INET socket can only accept
236
IPv4 connections. A PF_INET6 socket accepts IPv6 connections, but may also
237
accept IPv4 connections, depending on OS and its settings. For example,
238
on FreeBSD systems setting a sysctl net.inet6.ip6.v6only to 0 will allow
239
IPv4 connections to a PF_INET6 socket.
240
241
The Net::Server::Proto::object method returns a list of objects corresponding
242
to created sockets. For Unix and INET sockets the list typically contains
243
just one element, but may return multiple objects when multiple protocol
244
families are allowed or when a host name resolves to multiple local
245
binding addresses.
231
246
232
You can see what Net::Server::Proto parsed out by looking at
247
You can see what Net::Server::Proto parsed out by looking at
(-)Net-Server-0.99.ori/lib/Net/Server.pm (-32 / +58 lines)
Lines 26-30 Link Here
26
use strict;
26
use strict;
27
use vars qw($VERSION);
27
use vars qw($VERSION);
28
use Socket qw(inet_aton inet_ntoa AF_INET AF_UNIX SOCK_DGRAM SOCK_STREAM);
28
use Socket qw(AF_INET AF_UNIX SOCK_DGRAM SOCK_STREAM);
29
use IO::Socket ();
29
use IO::Socket ();
30
use IO::Select ();
30
use IO::Select ();
Lines 356-361 Link Here
356
  push @{ $prop->{host} }, (($prop->{host}->[-1]) x (@{ $prop->{port} } - @{ $prop->{host}})); # augment hosts with as many as port
356
  push @{ $prop->{host} }, (($prop->{host}->[-1]) x (@{ $prop->{port} } - @{ $prop->{host}})); # augment hosts with as many as port
357
  foreach my $host (@{ $prop->{host} }) {
357
  foreach my $host (@{ $prop->{host} }) {
358
    $host = '*' if ! defined $host || ! length $host;;
358
    local $1;
359
    $host = ($host =~ /^([\w\.\-\*\/]+)$/) ? $1 : $self->fatal("Unsecure host \"$host\"");
359
    if (!defined $host || $host eq '' || $host eq '*') {
360
      $host = '*';
361
    } elsif ($host =~ /^\[([\w\/.:-]+)\]$/ || $host =~ /^([\w\/.:-]+)$/) {
362
      $host = $1;
363
    } else {
364
      $self->fatal("Unsecure host \"$host\"");
365
    }
360
  }
366
  }
361
367
Lines 377-386 Link Here
377
    my $host  = $prop->{host}->[$i];
383
    my $host  = $prop->{host}->[$i];
378
    my $proto = $prop->{proto}->[$i];
384
    my $proto = $prop->{proto}->[$i];
379
    if ($port ne 0 && $bound{"$host/$port/$proto"}++) {
385
    if ($port ne "0" && $bound{"$host/$port/$proto"}++) {
380
      $self->log(2, "Duplicate configuration (".(uc $proto)." port $port on host $host - skipping");
386
      $self->log(2, "Duplicate configuration (".(uc $proto)." port $port on host $host - skipping");
381
      next;
387
      next;
382
    }
388
    }
383
    my $obj = $self->proto_object($host, $port, $proto) || next;
389
    my @obj_list = $self->proto_object($host, $port, $proto);
384
    push @{ $prop->{sock} }, $obj;
390
    for my $obj (@obj_list) {
391
      push @{ $prop->{sock} }, $obj  if $obj;
392
    }
385
  }
393
  }
386
  if (! @{ $prop->{sock} }) {
394
  if (! @{ $prop->{sock} }) {
Lines 397-401 Link Here
397
}
405
}
398
406
399
### method for invoking procol specific bindings
407
### method for invoking procol specific bindings;
408
### returns any number of sockets,
409
### one for each protocol family (PF_INET or PF_INET6) and each bind address
400
sub proto_object {
410
sub proto_object {
401
  my $self = shift;
411
  my $self = shift;
Lines 440-445 Link Here
440
  }
450
  }
441
451
442
  ### if more than one port we'll need to select on it
452
  ### if more than one socket we'll need to select on it;
443
  if( @{ $prop->{port} } > 1 || $prop->{multi_port} ){
453
  ### note there may be more than one socket per port,
454
  ### one for each protocol family (PF_INET and PF_INET6)
455
  if( @{ $prop->{sock} } > 1 || $prop->{multi_port} ){
444
    $prop->{multi_port} = 1;
456
    $prop->{multi_port} = 1;
445
    $prop->{select} = IO::Select->new();
457
    $prop->{select} = IO::Select->new();
Lines 748-752 Link Here
748
    return;
760
    return;
749
  } elsif ($self->isa('Net::Server::INET')) {
761
  } elsif ($self->isa('Net::Server::INET')) {
750
    $prop->{sockaddr} = $ENV{'REMOTE_HOST'} || '0.0.0.0';
762
    # since we do not know a socket protocol family, we are unable
763
    # to choose between '0.0.0.0' and '::' as an unspecified address
764
    $prop->{sockaddr} = $ENV{'REMOTE_HOST'} || '0.0.0.0';  # or is is a '::' ?
751
    $prop->{peeraddr} = '0.0.0.0';
765
    $prop->{peeraddr} = '0.0.0.0';
752
    $prop->{sockhost} = $prop->{peerhost} = 'inetd.server';
766
    $prop->{sockhost} = $prop->{peerhost} = 'inetd.server';
Lines 756-767 Link Here
756
770
757
  ### read information about this connection
771
  ### read information about this connection
758
  my $sockname = getsockname( $sock );
772
  my $sockname = $sock->sockname;
759
  if( $sockname ){
773
  if( $sockname ){
760
    ($prop->{sockport}, $prop->{sockaddr})
774
    $prop->{sockaddr} = $sock->sockhost;
761
      = Socket::unpack_sockaddr_in( $sockname );
775
    $prop->{sockport} = $sock->sockport;
762
    $prop->{sockaddr} = inet_ntoa( $prop->{sockaddr} );
763
764
  }else{
776
  }else{
765
    ### does this only happen from command line?
777
    ### does this only happen from command line?
778
    # since we do not know a socket protocol family, we are unable
779
    # to choose between '0.0.0.0' and '::' as an unspecified address
766
    $prop->{sockaddr} = $ENV{'REMOTE_HOST'} || '0.0.0.0';
780
    $prop->{sockaddr} = $ENV{'REMOTE_HOST'} || '0.0.0.0';
767
    $prop->{sockhost} = 'inet.test';
781
    $prop->{sockhost} = 'inet.test';
Lines 773-788 Link Here
773
  if( $prop->{udp_true} ){
787
  if( $prop->{udp_true} ){
774
    $proto_type = 'UDP';
788
    $proto_type = 'UDP';
775
    ($prop->{peerport} ,$prop->{peeraddr})
789
    ($prop->{peerport}, $prop->{peeraddrn}) =
776
      = Socket::sockaddr_in( $prop->{udp_peer} );
790
      $sock->sockdomain == AF_INET ? Socket::sockaddr_in($prop->{udp_peer})
777
  }elsif( $prop->{peername} = getpeername( $sock ) ){
791
                                 : Socket6::sockaddr_in6($prop->{udp_peer});
778
    ($prop->{peerport}, $prop->{peeraddr})
792
    $prop->{peeraddr} = Socket6->UNIVERSAL::can('inet_ntop')
779
      = Socket::unpack_sockaddr_in( $prop->{peername} );
793
                   ? Socket6::inet_ntop($sock->sockdomain, $prop->{peeraddrn})
780
  }
794
                   : inet_ntoa( $prop->{peeraddrn} );
781
795
  }elsif( $prop->{peername} = $sock->peername ){
782
  if( $prop->{peername} || $prop->{udp_true} ){
796
    $prop->{peeraddrn} = $sock->peeraddr;  # binary
783
    $prop->{peeraddr} = inet_ntoa( $prop->{peeraddr} );
797
    $prop->{peeraddr} = $sock->peerhost;   # ascii
784
798
    $prop->{peerport} = $sock->peerport;
785
    if( defined $prop->{reverse_lookups} ){
799
  }
786
      $prop->{peerhost} = gethostbyaddr( inet_aton($prop->{peeraddr}), AF_INET );
800
801
  if( $prop->{peeraddrn} ){
802
    if( !defined $prop->{reverse_lookups} ){
803
      # no reverse DNS resolving
804
    }elsif( Socket6->UNIVERSAL::can('getnameinfo') ){
805
      my @res = Socket6::getnameinfo( $prop->{peeraddrn}, 0 );
806
      $prop->{peerhost} = $res[0]  if @res > 1;
807
    }else{
808
      $prop->{peerhost} = gethostbyaddr( $prop->{peeraddrn}, AF_INET );
787
    }
809
    }
788
    $prop->{peerhost} = '' unless defined $prop->{peerhost};
810
    $prop->{peerhost} = '' unless defined $prop->{peerhost};
Lines 790-793 Link Here
790
  }else{
812
  }else{
791
    ### does this only happen from command line?
813
    ### does this only happen from command line?
814
    # since we do not know a socket protocol family, we are unable
815
    # to choose between '0.0.0.0' and '::' as an unspecified address
792
    $prop->{peeraddr} = '0.0.0.0';
816
    $prop->{peeraddr} = '0.0.0.0';
793
    $prop->{peerhost} = 'inet.test';
817
    $prop->{peerhost} = 'inet.test';
Lines 796-801 Link Here
796
820
797
  $self->log(3,$self->log_time
821
  $self->log(3,$self->log_time
798
             ." CONNECT $proto_type Peer: \"$prop->{peeraddr}:$prop->{peerport}\""
822
             ." CONNECT $proto_type Peer: \"[$prop->{peeraddr}]:$prop->{peerport}\""
799
             ." Local: \"$prop->{sockaddr}:$prop->{sockport}\"\n");
823
             ." Local: \"[$prop->{sockaddr}]:$prop->{sockport}\"\n");
800
824
801
}
825
}
Lines 1141-1149 Link Here
1141
  foreach my $sock ( @{ $prop->{sock} } ){
1165
  foreach my $sock ( @{ $prop->{sock} } ){
1142
1166
1143
    ### duplicate the sock
1167
    ### duplicate the socket descriptor
1144
    my $fd = POSIX::dup($sock->fileno)
1168
    my $fd = POSIX::dup($sock->fileno)
1145
      or $self->fatal("Can't dup socket [$!]");
1169
      or $self->fatal("Can't dup socket [$!]");
1146
1170
1147
    ### hold on to the socket copy until exec
1171
    ### hold on to the socket copy until exec;
1172
    ### just temporary: any socket domain will do,
1173
    ### forked process will decide to use IO::Socket::INET6 if necessary
1148
    $prop->{_HUP}->[$i] = IO::Socket::INET->new;
1174
    $prop->{_HUP}->[$i] = IO::Socket::INET->new;
1149
    $prop->{_HUP}->[$i]->fdopen($fd, 'w')
1175
    $prop->{_HUP}->[$i]->fdopen($fd, 'w')
Lines 1153-1157 Link Here
1153
    $prop->{_HUP}->[$i]->fcntl( Fcntl::F_SETFD(), my $flags = "" );
1179
    $prop->{_HUP}->[$i]->fcntl( Fcntl::F_SETFD(), my $flags = "" );
1154
1180
1155
    ### save host,port,proto, and file descriptor
1181
    ### save file descriptor and host|port|proto|family
1156
    push @fd, $fd .'|'. $sock->hup_string;
1182
    push @fd, $fd .'|'. $sock->hup_string;
1157
1183
(-)Net-Server-0.99.ori/lib/Net/Server.pod (-13 / +42 lines)
Lines 556-574 Link Here
556
bound at server startup.  May be of the form
556
bound at server startup.  May be of the form
557
C<host:port/proto>, C<host:port>, C<port/proto>, or C<port>,
557
C<host:port/proto>, C<host:port>, C<port/proto>, or C<port>,
558
where I<host> represents a hostname residing on the local
558
where I<host> represents a hostname residing on the local box,
559
box, where I<port> represents either the number of the port
559
where I<port> represents either the number of the port (eg. "80")
560
(eg. "80") or the service designation (eg.  "http"), and
560
or the service designation (eg. "http"), and where I<proto>
561
where I<proto> represents the protocol to be used.  See
561
represents the protocol to be used. See L<Net::Server::Proto>.
562
L<Net::Server::Proto>.  If you are working with unix sockets,
562
563
you may also specify C<socket_file|unix> or
563
An explicit I<host> given in a port specification overrides
564
C<socket_file|type|unix> where type is SOCK_DGRAM or
564
a default binding address (a C<host> setting, see below).
565
SOCK_STREAM.  If the protocol is not specified, I<proto> will
565
The I<host> part may be enclosed in square brackets, but when it is
566
a numerical IPv6 address it B<must> be enclosed in square brackets
567
to avoid ambiguity in parsing a port number, e.g.: "[::1]:80".
568
569
If you are working with unix sockets, you may also specify
570
C<socket_file|unix> or C<socket_file|type|unix> where type is SOCK_DGRAM
571
or SOCK_STREAM.  If the protocol is not specified, I<proto> will
566
default to the C<proto> specified in the arguments.  If C<proto> is not
572
default to the C<proto> specified in the arguments.  If C<proto> is not
567
specified there it will default to "tcp".  If I<host> is not
573
specified there it will default to "tcp".  If I<host> is not
568
specified, I<host> will default to C<host> specified in the
574
specified, I<host> will default to C<host> specified in the
569
arguments.  If C<host> is not specified there it will
575
arguments.  If C<host> is not specified there it will default to "*".
570
default to "*".  Default port is 20203.  Configuration passed
576
Default port is 20203.  Configuration passed to new or run may be either
571
to new or run may be either a scalar containing a single port
577
a scalar containing a single port number or an arrayref of ports.
572
number or an arrayref of ports.
578
579
On an IPv6-enabled host where a module IO::Socket::INET6 is installed
580
the "*" implies two listening sockets, one for each of the protocols
581
(PF_INET and PF_INET6) and is equivalent to specifying two ports, bound
582
to an 'unspecified' address of each address family ("0.0.0.0" and "::").
583
If listening on an INET6 socket is not desired despite IO::Socket::INET6
584
module being available, please supply the 'unspecifed' INET (IPv4) address
585
'0.0.0.0' as a I<host>, either in the C<port> or in the C<host> argument.
586
587
An INET socket can only accept IPv4 connections. An INET6 socket accepts
588
IPv6 connections, but may also accept IPv4 connections depending on
589
OS and its settings. For example, on FreeBSD systems setting a sysctl
590
net.inet6.ip6.v6only to 0 will allow IPv4 connections to an INET6 socket.
591
If this is the case, specifying "::" as a binding address instead of a "*"
592
might be desired to reduce the number of sockets needed. Note that a
593
textual representation of a peer's IPv4 address as connected to an INET6
594
socket will typically be in a form of an IPv4-mapped IPv6 addresses,
595
e.g. "::FFFF:127.0.0.1" .
596
597
Restricting binding to a loopback interface on systems where an INET6
598
socket does not accept IPv4 connections requires creating two sockets,
599
one bound to address "127.0.0.1" and the other bound to address "::1".
573
600
574
On systems that support it, a port value of 0 may be used to ask
601
On systems that support it, a port value of 0 may be used to ask
Lines 583-587 Link Here
583
Local host or addr upon which to bind port.  If a value of '*' is
610
Local host or addr upon which to bind port.  If a value of '*' is
584
given, the server will bind that port on all available addresses
611
given, the server will bind that port on all available addresses
585
on the box.  See L<Net::Server::Proto>. See L<IO::Socket>.  Configuration
612
on the box.  The C<host> argument provides a default local host
613
address if the C<port> argument omits a host specification.
614
See L<Net::Server::Proto>. See L<IO::Socket>.  Configuration
586
passed to new or run may be either a scalar containing a single
615
passed to new or run may be either a scalar containing a single
587
host or an arrayref of hosts - if the hosts array is shorter than
616
host or an arrayref of hosts - if the hosts array is shorter than

Return to bug 370355