icmp tweak for IO::Socket
[p5sagit/p5-mst-13.2.git] / ext / IO / lib / IO / Socket.pm
CommitLineData
774d564b 1# IO::Socket.pm
8add82fc 2#
774d564b 3# Copyright (c) 1996 Graham Barr <Graham.Barr@tiuk.ti.com>. All rights
4# reserved. This program is free software; you can redistribute it and/or
5# modify it under the same terms as Perl itself.
8add82fc 6
7package IO::Socket;
8
9=head1 NAME
10
27d4819a 11IO::Socket - Object interface to socket communications
8add82fc 12
13=head1 SYNOPSIS
14
15 use IO::Socket;
16
17=head1 DESCRIPTION
18
19C<IO::Socket> provides an object interface to creating and using sockets. It
20is built upon the L<IO::Handle> interface and inherits all the methods defined
21by L<IO::Handle>.
22
23C<IO::Socket> only defines methods for those operations which are common to all
24types of socket. Operations which are specified to a socket in a particular
25domain have methods defined in sub classes of C<IO::Socket>
26
7a4c00b4 27C<IO::Socket> will export all functions (and constants) defined by L<Socket>.
28
27d4819a 29=head1 CONSTRUCTOR
30
31=over 4
32
33=item new ( [ARGS] )
34
2085bf88 35Creates an C<IO::Socket>, which is a reference to a
27d4819a 36newly created symbol (see the C<Symbol> package). C<new>
37optionally takes arguments, these arguments are in key-value pairs.
38C<new> only looks for one key C<Domain> which tells new which domain
2085bf88 39the socket will be in. All other arguments will be passed to the
27d4819a 40configuration method of the package for that domain, See below.
41
42=back
43
44=head1 METHODS
45
8add82fc 46See L<perlfunc> for complete descriptions of each of the following
2085bf88 47supported C<IO::Socket> methods, which are just front ends for the
8add82fc 48corresponding built-in functions:
49
50 socket
51 socketpair
52 bind
53 listen
54 accept
55 send
56 recv
57 peername (getpeername)
58 sockname (getsockname)
59
60Some methods take slightly different arguments to those defined in L<perlfunc>
61in attempt to make the interface more flexible. These are
62
27d4819a 63=over 4
64
8add82fc 65=item accept([PKG])
66
67perform the system call C<accept> on the socket and return a new object. The
68new object will be created in the same class as the listen socket, unless
69C<PKG> is specified. This object can be used to communicate with the client
70that was trying to connect. In a scalar context the new socket is returned,
71or undef upon failure. In an array context a two-element array is returned
72containing the new socket and the peer address, the list will
73be empty upon failure.
74
75Additional methods that are provided are
76
77=item timeout([VAL])
78
79Set or get the timeout value associated with this socket. If called without
80any arguments then the current setting is returned. If called with an argument
81the current setting is changed and the previous value returned.
82
83=item sockopt(OPT [, VAL])
84
85Unified method to both set and get options in the SOL_SOCKET level. If called
27d4819a 86with one argument then getsockopt is called, otherwise setsockopt is called.
87
88=item sockdomain
89
7a4c00b4 90Returns the numerical number for the socket domain type. For example, for
27d4819a 91a AF_INET socket the value of &AF_INET will be returned.
92
93=item socktype
94
7a4c00b4 95Returns the numerical number for the socket type. For example, for
27d4819a 96a SOCK_STREAM socket the value of &SOCK_STREAM will be returned.
97
98=item protocol
99
100Returns the numerical number for the protocol being used on the socket, if
101known. If the protocol is unknown, as with an AF_UNIX socket, zero
102is returned.
103
104=back
8add82fc 105
106=cut
107
108
109require 5.000;
110
111use Config;
112use IO::Handle;
113use Socket 1.3;
114use Carp;
115use strict;
7a4c00b4 116use vars qw(@ISA $VERSION);
8add82fc 117use Exporter;
118
119@ISA = qw(IO::Handle);
120
8cc95fdb 121$VERSION = "1.1602";
8add82fc 122
123sub import {
124 my $pkg = shift;
125 my $callpkg = caller;
126 Exporter::export 'Socket', $callpkg, @_;
127}
128
129sub new {
130 my($class,%arg) = @_;
131 my $fh = $class->SUPER::new();
132
133 ${*$fh}{'io_socket_timeout'} = delete $arg{Timeout};
134
135 return scalar(%arg) ? $fh->configure(\%arg)
136 : $fh;
137}
138
27d4819a 139my @domain2pkg = ();
140
141sub register_domain {
142 my($p,$d) = @_;
774d564b 143 $domain2pkg[$d] = $p;
27d4819a 144}
145
8add82fc 146sub configure {
27d4819a 147 my($fh,$arg) = @_;
148 my $domain = delete $arg->{Domain};
149
150 croak 'IO::Socket: Cannot configure a generic socket'
151 unless defined $domain;
152
774d564b 153 croak "IO::Socket: Unsupported socket domain"
154 unless defined $domain2pkg[$domain];
27d4819a 155
7a4c00b4 156 croak "IO::Socket: Cannot configure socket in domain '$domain'"
157 unless ref($fh) eq "IO::Socket";
27d4819a 158
774d564b 159 bless($fh, $domain2pkg[$domain]);
8cc95fdb 160 $fh->configure($arg);
8add82fc 161}
162
163sub socket {
164 @_ == 4 or croak 'usage: $fh->socket(DOMAIN, TYPE, PROTOCOL)';
165 my($fh,$domain,$type,$protocol) = @_;
166
167 socket($fh,$domain,$type,$protocol) or
168 return undef;
169
774d564b 170 ${*$fh}{'io_socket_domain'} = $domain;
171 ${*$fh}{'io_socket_type'} = $type;
172 ${*$fh}{'io_socket_proto'} = $protocol;
173
8add82fc 174 $fh;
175}
176
177sub socketpair {
178 @_ == 4 || croak 'usage: IO::Socket->pair(DOMAIN, TYPE, PROTOCOL)';
179 my($class,$domain,$type,$protocol) = @_;
180 my $fh1 = $class->new();
181 my $fh2 = $class->new();
182
183 socketpair($fh1,$fh1,$domain,$type,$protocol) or
184 return ();
185
27d4819a 186 ${*$fh1}{'io_socket_type'} = ${*$fh2}{'io_socket_type'} = $type;
187 ${*$fh1}{'io_socket_proto'} = ${*$fh2}{'io_socket_proto'} = $protocol;
8add82fc 188
189 ($fh1,$fh2);
190}
191
192sub connect {
193 @_ == 2 || @_ == 3 or croak 'usage: $fh->connect(NAME) or $fh->connect(PORT, ADDR)';
194 my $fh = shift;
195 my $addr = @_ == 1 ? shift : sockaddr_in(@_);
196 my $timeout = ${*$fh}{'io_socket_timeout'};
197 local($SIG{ALRM}) = $timeout ? sub { undef $fh; }
198 : $SIG{ALRM} || 'DEFAULT';
199
760ac839 200 eval {
8add82fc 201 croak 'connect: Bad address'
202 if(@_ == 2 && !defined $_[1]);
203
204 if($timeout) {
205 defined $Config{d_alarm} && defined alarm($timeout) or
206 $timeout = 0;
207 }
208
760ac839 209 my $ok = connect($fh, $addr);
8add82fc 210
211 alarm(0)
212 if($timeout);
213
760ac839 214 croak "connect: timeout"
215 unless defined $fh;
8add82fc 216
760ac839 217 undef $fh unless $ok;
8add82fc 218 };
760ac839 219
8add82fc 220 $fh;
221}
222
223sub bind {
224 @_ == 2 || @_ == 3 or croak 'usage: $fh->bind(NAME) or $fh->bind(PORT, ADDR)';
225 my $fh = shift;
226 my $addr = @_ == 1 ? shift : sockaddr_in(@_);
227
228 return bind($fh, $addr) ? $fh
229 : undef;
230}
231
232sub listen {
233 @_ >= 1 && @_ <= 2 or croak 'usage: $fh->listen([QUEUE])';
234 my($fh,$queue) = @_;
235 $queue = 5
236 unless $queue && $queue > 0;
237
238 return listen($fh, $queue) ? $fh
239 : undef;
240}
241
242sub accept {
243 @_ == 1 || @_ == 2 or croak 'usage $fh->accept([PKG])';
244 my $fh = shift;
245 my $pkg = shift || $fh;
246 my $timeout = ${*$fh}{'io_socket_timeout'};
247 my $new = $pkg->new(Timeout => $timeout);
248 my $peer = undef;
249
250 eval {
251 if($timeout) {
252 my $fdset = "";
253 vec($fdset, $fh->fileno,1) = 1;
254 croak "accept: timeout"
255 unless select($fdset,undef,undef,$timeout);
256 }
257 $peer = accept($new,$fh);
258 };
259
260 return wantarray ? defined $peer ? ($new, $peer)
261 : ()
262 : defined $peer ? $new
263 : undef;
264}
265
266sub sockname {
267 @_ == 1 or croak 'usage: $fh->sockname()';
268 getsockname($_[0]);
269}
270
271sub peername {
272 @_ == 1 or croak 'usage: $fh->peername()';
273 my($fh) = @_;
274 getpeername($fh)
275 || ${*$fh}{'io_socket_peername'}
276 || undef;
277}
278
279sub send {
280 @_ >= 2 && @_ <= 4 or croak 'usage: $fh->send(BUF, [FLAGS, [TO]])';
281 my $fh = $_[0];
282 my $flags = $_[2] || 0;
283 my $peer = $_[3] || $fh->peername;
284
285 croak 'send: Cannot determine peer address'
286 unless($peer);
287
27d4819a 288 my $r = defined(getpeername($fh))
289 ? send($fh, $_[1], $flags)
290 : send($fh, $_[1], $flags, $peer);
8add82fc 291
292 # remember who we send to, if it was sucessful
293 ${*$fh}{'io_socket_peername'} = $peer
294 if(@_ == 4 && defined $r);
295
296 $r;
297}
298
299sub recv {
300 @_ == 3 || @_ == 4 or croak 'usage: $fh->recv(BUF, LEN [, FLAGS])';
301 my $sock = $_[0];
302 my $len = $_[2];
303 my $flags = $_[3] || 0;
304
305 # remember who we recv'd from
306 ${*$sock}{'io_socket_peername'} = recv($sock, $_[1]='', $len, $flags);
307}
308
309
310sub setsockopt {
311 @_ == 4 or croak '$fh->setsockopt(LEVEL, OPTNAME)';
312 setsockopt($_[0],$_[1],$_[2],$_[3]);
313}
314
315my $intsize = length(pack("i",0));
316
317sub getsockopt {
318 @_ == 3 or croak '$fh->getsockopt(LEVEL, OPTNAME)';
319 my $r = getsockopt($_[0],$_[1],$_[2]);
320 # Just a guess
321 $r = unpack("i", $r)
322 if(defined $r && length($r) == $intsize);
323 $r;
324}
325
326sub sockopt {
327 my $fh = shift;
328 @_ == 1 ? $fh->getsockopt(SOL_SOCKET,@_)
329 : $fh->setsockopt(SOL_SOCKET,@_);
330}
331
332sub timeout {
333 @_ == 1 || @_ == 2 or croak 'usage: $fh->timeout([VALUE])';
334 my($fh,$val) = @_;
335 my $r = ${*$fh}{'io_socket_timeout'} || undef;
336
337 ${*$fh}{'io_socket_timeout'} = 0 + $val
338 if(@_ == 2);
339
340 $r;
341}
342
27d4819a 343sub sockdomain {
344 @_ == 1 or croak 'usage: $fh->sockdomain()';
345 my $fh = shift;
774d564b 346 ${*$fh}{'io_socket_domain'};
27d4819a 347}
348
8add82fc 349sub socktype {
27d4819a 350 @_ == 1 or croak 'usage: $fh->socktype()';
351 my $fh = shift;
352 ${*$fh}{'io_socket_type'}
8add82fc 353}
354
27d4819a 355sub protocol {
356 @_ == 1 or croak 'usage: $fh->protocol()';
357 my($fh) = @_;
358 ${*$fh}{'io_socket_protocol'};
359}
360
8add82fc 361=head1 SUB-CLASSES
362
363=cut
364
365##
366## AF_INET
367##
368
369package IO::Socket::INET;
370
371use strict;
7a4c00b4 372use vars qw(@ISA);
8add82fc 373use Socket;
374use Carp;
375use Exporter;
376
377@ISA = qw(IO::Socket);
378
27d4819a 379IO::Socket::INET->register_domain( AF_INET );
380
8add82fc 381my %socket_type = ( tcp => SOCK_STREAM,
382 udp => SOCK_DGRAM,
8251ff82 383 icmp => SOCK_RAW,
8add82fc 384 );
385
386=head2 IO::Socket::INET
387
388C<IO::Socket::INET> provides a constructor to create an AF_INET domain socket
389and some related methods. The constructor can take the following options
390
2085bf88 391 PeerAddr Remote host address <hostname>[:<port>]
392 PeerPort Remote port or service <service>[(<no>)] | <no>
393 LocalAddr Local host bind address hostname[:port]
394 LocalPort Local host bind port <service>[(<no>)] | <no>
395 Proto Protocol name "tcp" | "udp" | ...
396 Type Socket type SOCK_STREAM | SOCK_DGRAM | ...
8add82fc 397 Listen Queue size for listen
7a4c00b4 398 Reuse Set SO_REUSEADDR before binding
8add82fc 399 Timeout Timeout value for various operations
400
27d4819a 401
7a4c00b4 402If C<Listen> is defined then a listen socket is created, else if the
403socket type, which is derived from the protocol, is SOCK_STREAM then
404connect() is called.
405
406The C<PeerAddr> can be a hostname or the IP-address on the
407"xx.xx.xx.xx" form. The C<PeerPort> can be a number or a symbolic
408service name. The service name might be followed by a number in
409parenthesis which is used if the service is not known by the system.
410The C<PeerPort> specification can also be embedded in the C<PeerAddr>
411by preceding it with a ":".
412
413Only one of C<Type> or C<Proto> needs to be specified, one will be
414assumed from the other. If you specify a symbolic C<PeerPort> port,
415then the constructor will try to derive C<Type> and C<Proto> from
416the service name.
8add82fc 417
7a4c00b4 418Examples:
419
420 $sock = IO::Socket::INET->new(PeerAddr => 'www.perl.org',
8cc95fdb 421 PeerPort => 'http(80)',
7a4c00b4 422 Proto => 'tcp');
423
424 $sock = IO::Socket::INET->new(PeerAddr => 'localhost:smtp(25)');
425
426 $sock = IO::Socket::INET->new(Listen => 5,
427 LocalAddr => 'localhost',
428 LocalPort => 9000,
429 Proto => 'tcp');
8add82fc 430
431=head2 METHODS
432
27d4819a 433=over 4
434
435=item sockaddr ()
8add82fc 436
437Return the address part of the sockaddr structure for the socket
438
27d4819a 439=item sockport ()
8add82fc 440
441Return the port number that the socket is using on the local host
442
27d4819a 443=item sockhost ()
8add82fc 444
445Return the address part of the sockaddr structure for the socket in a
446text form xx.xx.xx.xx
447
27d4819a 448=item peeraddr ()
449
450Return the address part of the sockaddr structure for the socket on
451the peer host
452
453=item peerport ()
454
455Return the port number for the socket on the peer host.
8add82fc 456
27d4819a 457=item peerhost ()
458
459Return the address part of the sockaddr structure for the socket on the
460peer host in a text form xx.xx.xx.xx
461
462=back
8add82fc 463
464=cut
465
8add82fc 466sub _sock_info {
467 my($addr,$port,$proto) = @_;
468 my @proto = ();
469 my @serv = ();
470
471 $port = $1
472 if(defined $addr && $addr =~ s,:([\w\(\)/]+)$,,);
473
474 if(defined $proto) {
475 @proto = $proto =~ m,\D, ? getprotobyname($proto)
476 : getprotobynumber($proto);
477
478 $proto = $proto[2] || undef;
479 }
480
481 if(defined $port) {
482 $port =~ s,\((\d+)\)$,,;
483
484 my $defport = $1 || undef;
485 my $pnum = ($port =~ m,^(\d+)$,)[0];
486
487 @serv= getservbyname($port, $proto[0] || "")
488 if($port =~ m,\D,);
489
490 $port = $pnum || $serv[2] || $defport || undef;
491
492 $proto = (getprotobyname($serv[3]))[2] || undef
493 if @serv && !$proto;
494 }
495
496 return ($addr || undef,
497 $port || undef,
498 $proto || undef
499 );
500}
501
27d4819a 502sub _error {
503 my $fh = shift;
7a4c00b4 504 $@ = join("",ref($fh),": ",@_);
505 carp $@ if $^W;
27d4819a 506 close($fh)
507 if(defined fileno($fh));
508 return undef;
509}
510
8add82fc 511sub configure {
512 my($fh,$arg) = @_;
513 my($lport,$rport,$laddr,$raddr,$proto,$type);
514
515
516 ($laddr,$lport,$proto) = _sock_info($arg->{LocalAddr},
517 $arg->{LocalPort},
518 $arg->{Proto});
519
520 $laddr = defined $laddr ? inet_aton($laddr)
521 : INADDR_ANY;
522
27d4819a 523 return _error($fh,"Bad hostname '",$arg->{LocalAddr},"'")
524 unless(defined $laddr);
525
8add82fc 526 unless(exists $arg->{Listen}) {
527 ($raddr,$rport,$proto) = _sock_info($arg->{PeerAddr},
528 $arg->{PeerPort},
529 $proto);
530 }
531
27d4819a 532 if(defined $raddr) {
533 $raddr = inet_aton($raddr);
534 return _error($fh,"Bad hostname '",$arg->{PeerAddr},"'")
535 unless(defined $raddr);
536 }
537
538 return _error($fh,'Cannot determine protocol')
8add82fc 539 unless($proto);
540
541 my $pname = (getprotobynumber($proto))[0];
542 $type = $arg->{Type} || $socket_type{$pname};
543
544 $fh->socket(AF_INET, $type, $proto) or
7a4c00b4 545 return _error($fh,"$!");
546
547 if ($arg->{Reuse}) {
548 $fh->sockopt(SO_REUSEADDR,1) or
549 return _error($fh);
550 }
8add82fc 551
552 $fh->bind($lport || 0, $laddr) or
7a4c00b4 553 return _error($fh,"$!");
8add82fc 554
555 if(exists $arg->{Listen}) {
556 $fh->listen($arg->{Listen} || 5) or
7a4c00b4 557 return _error($fh,"$!");
8add82fc 558 }
559 else {
27d4819a 560 return _error($fh,'Cannot determine remote port')
8251ff82 561 unless($rport || $type == SOCK_DGRAM || $type == SOCK_RAW);
8add82fc 562
563 if($type == SOCK_STREAM || defined $raddr) {
27d4819a 564 return _error($fh,'Bad peer address')
565 unless(defined $raddr);
8add82fc 566
27d4819a 567 $fh->connect($rport,$raddr) or
7a4c00b4 568 return _error($fh,"$!");
8add82fc 569 }
570 }
571
572 $fh;
573}
574
575sub sockaddr {
576 @_ == 1 or croak 'usage: $fh->sockaddr()';
577 my($fh) = @_;
578 (sockaddr_in($fh->sockname))[1];
579}
580
581sub sockport {
582 @_ == 1 or croak 'usage: $fh->sockport()';
583 my($fh) = @_;
584 (sockaddr_in($fh->sockname))[0];
585}
586
587sub sockhost {
588 @_ == 1 or croak 'usage: $fh->sockhost()';
589 my($fh) = @_;
590 inet_ntoa($fh->sockaddr);
591}
592
593sub peeraddr {
594 @_ == 1 or croak 'usage: $fh->peeraddr()';
595 my($fh) = @_;
596 (sockaddr_in($fh->peername))[1];
597}
598
599sub peerport {
600 @_ == 1 or croak 'usage: $fh->peerport()';
601 my($fh) = @_;
602 (sockaddr_in($fh->peername))[0];
603}
604
605sub peerhost {
606 @_ == 1 or croak 'usage: $fh->peerhost()';
607 my($fh) = @_;
608 inet_ntoa($fh->peeraddr);
609}
610
611##
612## AF_UNIX
613##
614
615package IO::Socket::UNIX;
616
617use strict;
618use vars qw(@ISA $VERSION);
619use Socket;
620use Carp;
621use Exporter;
622
623@ISA = qw(IO::Socket);
624
27d4819a 625IO::Socket::UNIX->register_domain( AF_UNIX );
626
8add82fc 627=head2 IO::Socket::UNIX
628
629C<IO::Socket::UNIX> provides a constructor to create an AF_UNIX domain socket
630and some related methods. The constructor can take the following options
631
632 Type Type of socket (eg SOCK_STREAM or SOCK_DGRAM)
633 Local Path to local fifo
634 Peer Path to peer fifo
635 Listen Create a listen socket
636
637=head2 METHODS
638
27d4819a 639=over 4
640
8add82fc 641=item hostpath()
642
7a4c00b4 643Returns the pathname to the fifo at the local end
8add82fc 644
645=item peerpath()
646
7a4c00b4 647Returns the pathanme to the fifo at the peer end
27d4819a 648
649=back
8add82fc 650
651=cut
652
653sub configure {
654 my($fh,$arg) = @_;
655 my($bport,$cport);
656
657 my $type = $arg->{Type} || SOCK_STREAM;
658
659 $fh->socket(AF_UNIX, $type, 0) or
660 return undef;
661
662 if(exists $arg->{Local}) {
663 my $addr = sockaddr_un($arg->{Local});
664 $fh->bind($addr) or
665 return undef;
666 }
667 if(exists $arg->{Listen}) {
668 $fh->listen($arg->{Listen} || 5) or
669 return undef;
670 }
671 elsif(exists $arg->{Peer}) {
672 my $addr = sockaddr_un($arg->{Peer});
673 $fh->connect($addr) or
674 return undef;
675 }
676
677 $fh;
678}
679
680sub hostpath {
681 @_ == 1 or croak 'usage: $fh->hostpath()';
27d4819a 682 my $n = $_[0]->sockname || return undef;
27d4819a 683 (sockaddr_un($n))[0];
8add82fc 684}
685
686sub peerpath {
687 @_ == 1 or croak 'usage: $fh->peerpath()';
27d4819a 688 my $n = $_[0]->peername || return undef;
27d4819a 689 (sockaddr_un($n))[0];
8add82fc 690}
691
7a4c00b4 692=head1 SEE ALSO
8add82fc 693
7a4c00b4 694L<Socket>, L<IO::Handle>
8add82fc 695
7a4c00b4 696=head1 AUTHOR
8add82fc 697
7a4c00b4 698Graham Barr E<lt>F<Graham.Barr@tiuk.ti.com>E<gt>
760ac839 699
8add82fc 700=head1 COPYRIGHT
701
774d564b 702Copyright (c) 1996 Graham Barr. All rights reserved. This program is free
8add82fc 703software; you can redistribute it and/or modify it under the same terms
704as Perl itself.
705
706=cut
707
7081; # Keep require happy