File Coverage

blib/lib/IO/Socket/Packet.pm
Criterion Covered Total %
statement 67 130 51.5
branch 16 58 27.5
condition 5 7 71.4
subroutine 18 28 64.2
pod 18 19 94.7
total 124 242 51.2


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2009-2025 -- leonerd@leonerd.org.uk
5              
6             package IO::Socket::Packet 0.12;
7              
8 3     3   408175 use v5.14;
  3         12  
9 3     3   12 use warnings;
  3         11  
  3         179  
10 3     3   15 use base qw( IO::Socket );
  3         5  
  3         1830  
11              
12 3     3   56742 use Carp;
  3         6  
  3         167  
13              
14 3     3   997 use POSIX qw( EAGAIN );
  3         14340  
  3         20  
15 3     3   4220 use Socket qw( AF_INET SOCK_STREAM SOCK_RAW );
  3         8  
  3         805  
16              
17 3         6297 use Socket::Packet qw(
18             AF_PACKET ETH_P_ALL
19             pack_sockaddr_ll unpack_sockaddr_ll
20             pack_packet_mreq
21             unpack_tpacket_stats
22             siocgstamp siocgstampns
23             siocgifindex siocgifname
24             recv_len
25              
26             SOL_PACKET
27              
28             PACKET_ADD_MEMBERSHIP
29             PACKET_DROP_MEMBERSHIP
30             PACKET_STATISTICS
31              
32             PACKET_MR_MULTICAST
33             PACKET_MR_PROMISC
34             PACKET_MR_ALLMULTI
35 3     3   654 );
  3         6  
36              
37             __PACKAGE__->register_domain( AF_PACKET );
38              
39             =head1 NAME
40              
41             C - Object interface to C domain sockets
42              
43             =head1 SYNOPSIS
44              
45             use IO::Socket::Packet;
46             use Socket::Packet qw( unpack_sockaddr_ll );
47              
48             my $sock = IO::Socket::Packet->new( IfIndex => 0 );
49              
50             while( my ( $protocol, $ifindex, $hatype, $pkttype, $addr ) =
51             $sock->recv_unpack( my $packet, 8192, 0 ) ) {
52              
53             ...
54             }
55              
56             =head1 DESCRIPTION
57              
58             This class provides an object interface to C sockets on Linux. It
59             is built upon L and inherits all the methods defined by this base
60             class.
61              
62             =cut
63              
64             =head1 CONSTRUCTOR
65              
66             =cut
67              
68             =head2 new
69              
70             $sock = IO::Socket::Packet->new( %args );
71              
72             Creates a new C object. If any arguments are passed it
73             will be configured to contain a newly created socket handle, and be Ced
74             as required by the arguments. The recognised arguments are:
75              
76             =over 8
77              
78             =item Type => INT
79              
80             The socktype to use; should be either C or C. It not
81             supplied a default of C will be used.
82              
83             =item Protocol => INT
84              
85             Ethernet protocol number to bind to. To capture all protocols, use the
86             C constant (or omit this key, which implies that as a default).
87              
88             =item IfIndex => INT
89              
90             If supplied, binds the socket to the specified interface index. To bind to all
91             interfaces, use 0 (or omit this key, which implies that as a default).
92              
93             =item IfName => STRING
94              
95             If supplied, binds the socket to the interface with the specified name.
96              
97             =back
98              
99             =cut
100              
101             sub configure
102             {
103 3     3 0 17335 my $self = shift;
104 3         10 my ( $arg ) = @_;
105              
106 3   50     28 my $type = $arg->{Type} || SOCK_RAW;
107              
108 3 50       30 $self->socket( AF_PACKET, $type, 0 ) or return undef;
109              
110             # bind() arguments
111 3         280 my ( $protocol, $ifindex );
112              
113 3 50       13 $protocol = $arg->{Protocol} if exists $arg->{Protocol};
114 3 100       15 $ifindex = $arg->{IfIndex} if exists $arg->{IfIndex};
115              
116 3 50 66     20 if( !defined $ifindex and exists $arg->{IfName} ) {
117 1         18 $ifindex = siocgifindex( $self, $arg->{IfName} );
118 1 50       33 defined $ifindex or return undef;
119             }
120              
121 3 50 100     47 $self->bind( pack_sockaddr_ll(
    50          
122             defined $protocol ? $protocol : ETH_P_ALL,
123             $ifindex || 0,
124             0, 0, '' ) ) or return undef;
125              
126 3         81 return $self;
127             }
128              
129             =head1 METHODS
130              
131             =cut
132              
133             =head2 recv_len
134              
135             ( $addr, $len ) = $sock->recv_len( $buffer, $maxlen, $flags );
136              
137             Similar to Perl's C builtin, except it returns the packet length as an
138             explict return value. This may be useful if C<$flags> contains the
139             C flag, obtaining the true length of the packet on the wire, even
140             if this is longer than the data written in the buffer.
141              
142             =cut
143              
144             # don't actually need to implement it; the imported symbol works fine
145              
146             =head2 recv_unpack
147              
148             ( $protocol, $ifindex, $hatype, $pkttype, $addr, $len ) =
149             $sock->recv_unpack( $buffer, $size, $flags );
150              
151             This method is a combination of C and C. If it
152             successfully receives a packet, it unpacks the address and returns the fields
153             from it, and the length of the received packet. If it fails, it returns an
154             empty list.
155              
156             If the ring-buffer has been set using C, it will automatically
157             be used by this method.
158              
159             =cut
160              
161             sub recv_unpack
162             {
163 0     0 1 0 my $self = shift;
164              
165 0 0       0 if( defined ${*$self}{packet_rx_ring} ) {
  0         0  
166 0 0       0 defined $self->wait_ring_frame( my $buffer, \my %info ) or return;
167              
168             # Copy to caller
169 0         0 $_[0] = $buffer;
170              
171 0         0 $self->done_ring_frame;
172              
173 0         0 ${*$self}{packet_ts_sec} = $info{tp_sec};
  0         0  
174 0         0 ${*$self}{packet_ts_nsec} = $info{tp_nsec};
  0         0  
175              
176             return ( $info{sll_protocol},
177             $info{sll_ifindex},
178             $info{sll_hatype},
179             $info{sll_pkttype},
180             $info{sll_addr},
181 0         0 $info{tp_len} );
182             }
183              
184 0 0       0 my ( $addr, $len ) = $self->recv_len( @_ ) or return;
185 0         0 return unpack_sockaddr_ll( $addr ), $len;
186             }
187              
188             =head2 protocol
189              
190             $protocol = $sock->protocol;
191              
192             Returns the ethertype protocol the socket is bound to.
193              
194             =cut
195              
196             sub protocol
197             {
198 2     2 1 11391 my $self = shift;
199 2         15 return (unpack_sockaddr_ll($self->sockname))[0];
200             }
201              
202             =head2 ifindex
203              
204             $ifindex = $sock->ifindex;
205              
206             Returns the interface index the socket is bound to.
207              
208             =cut
209              
210             sub ifindex
211             {
212 5     5 1 3860 my $self = shift;
213 5         25 return (unpack_sockaddr_ll($self->sockname))[1];
214             }
215              
216             =head2 ifname
217              
218             $ifname = $sock->ifname;
219              
220             Returns the name of the interface the socket is bound to.
221              
222             =cut
223              
224             sub ifname
225             {
226 3     3 1 1421 my $self = shift;
227 3         11 return siocgifname( $self, $self->ifindex );
228             }
229              
230             =head2 hatype
231              
232             $hatype = $sock->hatype;
233              
234             Returns the hardware address type for the interface the socket is bound to.
235              
236             =cut
237              
238             sub hatype
239             {
240 2     2 1 1107 my $self = shift;
241 2         10 return (unpack_sockaddr_ll($self->sockname))[2];
242             }
243              
244             =head2 timestamp
245              
246             $time = $sock->timestamp;
247              
248             ( $sec, $usec ) = $sock->timestamp;
249              
250             Returns the timestamp of the last received packet on the socket (as obtained
251             by the C C). In scalar context, returns a single
252             floating-point value in UNIX epoch seconds. In list context, returns the
253             number of seconds, and the number of microseconds.
254              
255             If the ring-buffer has been set using C, this method returns
256             the timestamp of the last packet received from it.
257              
258             =cut
259              
260             sub timestamp
261             {
262 1     1 1 525 my $self = shift;
263              
264 1 50       3 if( defined ${*$self}{packet_ts_sec} ) {
  1         8  
265 0         0 my $sec = delete ${*$self}{packet_ts_sec};
  0         0  
266 0         0 my $nsec = delete ${*$self}{packet_ts_nsec};
  0         0  
267              
268 0 0       0 return wantarray ? ( $sec, int($nsec/1000) ) : $sec + $nsec/1_000_000_000;
269             }
270              
271 1         727 return siocgstamp( $self );
272             }
273              
274             =head2 timestamp_nano
275              
276             $time = $sock->timestamp_nano;
277              
278             ( $sec, $nsec ) = $sock->timestamp_nano;
279              
280             Returns the nanosecond-precise timestamp of the last received packet on the
281             socket (as obtained by the C C). In scalar context,
282             returns a single floating-point value in UNIX epoch seconds. In list context,
283             returns the number of seconds, and the number of nanoseconds.
284              
285             If the ring-buffer has been set using C, this method returns
286             the timestamp of the last packet received from it.
287              
288             =cut
289              
290             sub timestamp_nano
291             {
292 0     0 1 0 my $self = shift;
293              
294 0 0       0 if( defined ${*$self}{packet_ts_sec} ) {
  0         0  
295 0         0 my $sec = delete ${*$self}{packet_ts_sec};
  0         0  
296 0         0 my $nsec = delete ${*$self}{packet_ts_nsec};
  0         0  
297              
298 0 0       0 return wantarray ? ( $sec, $nsec ) : $sec + $nsec/1_000_000_000;
299             }
300              
301 0         0 return siocgstampns( $self );
302             }
303              
304             =head1 INTERFACE NAME UTILITIES
305              
306             The following methods are utilities around C and C.
307             If called on an object, they use the encapsulated socket. If called as class
308             methods, they will create a temporary socket to pass to the kernel, then close
309             it again.
310              
311             =cut
312              
313             =head2 ifname2index
314              
315             $ifindex = $sock->ifname2index( $ifname );
316              
317             $ifindex = IO::Socket::Packet->ifname2index( $ifname );
318              
319             Returns the name for the given interface index, or C if it doesn't
320             exist.
321              
322             =cut
323              
324             sub ifname2index
325             {
326 1     1 1 8542 my $self = shift;
327 1         4 my ( $ifname ) = @_;
328              
329 1         2 my $sock;
330 1 50       4 if( ref $self ) {
331 0         0 $sock = $self;
332             }
333             else {
334 1 50       49 socket( $sock, AF_INET, SOCK_STREAM, 0 ) or
335             croak "Cannot socket(AF_INET) - $!";
336             }
337              
338 1         64 return siocgifindex( $sock, $ifname );
339             }
340              
341             =head2 ifindex2name
342              
343             $ifname = $sock->ifindex2name( $ifindex );
344              
345             $ifname = IO::Socket::Packet->ifindex2name( $ifindex );
346              
347             Returns the index for the given interface name, or C if it doesn't
348             exist.
349              
350             =cut
351              
352             sub ifindex2name
353             {
354 2     2 1 293045 my $self = shift;
355 2         15 my ( $ifindex ) = @_;
356              
357 2         5 my $sock;
358 2 50       7 if( ref $self ) {
359 0         0 $sock = $self;
360             }
361             else {
362 2 50       107 socket( $sock, AF_INET, SOCK_STREAM, 0 ) or
363             croak "Cannot socket(AF_INET) - $!";
364             }
365              
366 2         92 return siocgifname( $sock, $ifindex );
367             }
368              
369             sub _make_sockopt_int
370             {
371 3     3   6 my ( $optname ) = @_;
372              
373             # IO::Socket automatically handles the pack/unpack in this case
374              
375             sub {
376 2     2   19375 my $sock = shift;
377              
378 2 100       12 if( @_ ) {
379 1         30 $sock->setsockopt( SOL_PACKET, $optname, $_[0] );
380             }
381             else {
382 1         14 return $sock->getsockopt( SOL_PACKET, $optname );
383             }
384 3         21 };
385             }
386              
387             =head1 SOCKET OPTION ACCESSORS
388              
389             =cut
390              
391             =head2 add_multicast
392              
393             $sock->add_multicast( $addr, $ifindex );
394              
395             Adds the given multicast address on the given interface index. If the
396             interface index is not supplied, C<< $sock->ifindex >> is used.
397              
398             =cut
399              
400             sub add_multicast
401             {
402 0     0 1 0 my $self = shift;
403 0         0 my ( $addr, $ifindex ) = @_;
404 0 0       0 defined $ifindex or $ifindex = $self->ifindex;
405              
406 0         0 $self->setsockopt( SOL_PACKET, PACKET_ADD_MEMBERSHIP,
407             pack_packet_mreq( $ifindex, PACKET_MR_MULTICAST, $addr )
408             );
409             }
410              
411             =head2 drop_multicast
412              
413             $sock->drop_multicast( $addr, $ifindex );
414              
415             Drops the given multicast address on the given interface index. If the
416             interface index is not supplied, C<< $sock->ifindex >> is used.
417              
418             =cut
419              
420             sub drop_multicast
421             {
422 0     0 1 0 my $self = shift;
423 0         0 my ( $addr, $ifindex ) = @_;
424 0 0       0 defined $ifindex or $ifindex = $self->ifindex;
425              
426 0         0 $self->setsockopt( SOL_PACKET, PACKET_DROP_MEMBERSHIP,
427             pack_packet_mreq( $ifindex, PACKET_MR_MULTICAST, $addr )
428             );
429             }
430              
431             =head2 promisc
432              
433             $sock->promisc( $promisc, $ifindex );
434              
435             Sets or clears the PACKET_MR_PROMISC flag on the given interface. If the
436             interface index is not supplied, C<< $sock->ifindex >> is used.
437              
438             =cut
439              
440             sub promisc
441             {
442 0     0 1 0 my $self = shift;
443 0         0 my ( $value, $ifindex ) = @_;
444 0 0       0 defined $ifindex or $ifindex = $self->ifindex;
445              
446 0 0       0 $self->setsockopt( SOL_PACKET, $value ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
447             pack_packet_mreq( $ifindex, PACKET_MR_PROMISC, "" )
448             );
449             }
450              
451             =head2 allmulti
452              
453             $sock->allmulti( $allmulti, $ifindex );
454              
455             Sets or clears the PACKET_MR_ALLMULTI flag on the given interface. If the
456             interface index is not supplied, C<< $sock->ifindex >> is used.
457              
458             =cut
459              
460             sub allmulti
461             {
462 0     0 1 0 my $self = shift;
463 0         0 my ( $value, $ifindex ) = @_;
464 0 0       0 defined $ifindex or $ifindex = $self->ifindex;
465              
466 0 0       0 $self->setsockopt( SOL_PACKET, $value ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
467             pack_packet_mreq( $ifindex, PACKET_MR_ALLMULTI, "" )
468             );
469             }
470              
471             =head2 statistics
472              
473             $stats = $sock->statistics;
474              
475             Returns the socket statistics. This will be a two-field hash containing
476             counts C, the total number of packets the socket has seen, and
477             C, the number of packets that could not stored because the buffer was
478             full.
479              
480             =cut
481              
482             sub statistics
483             {
484 1     1 1 683 my $self = shift;
485              
486 1 50       6 my $stats = $self->getsockopt( SOL_PACKET, PACKET_STATISTICS )
487             or return;
488              
489 1         23 my %stats;
490 1         10 @stats{qw( packets drops)} = unpack_tpacket_stats( $stats );
491              
492 1         15 return \%stats;
493             }
494              
495             =head2 origdev
496              
497             $val = $sock->origdev;
498              
499             $sock->origdev( $val );
500              
501             Return or set the value of the C socket option.
502              
503             =cut
504              
505             if( defined &Socket::Packet::PACKET_ORIGDEV ) {
506             *origdev = _make_sockopt_int( Socket::Packet::PACKET_ORIGDEV() );
507             }
508              
509             =head1 RING-BUFFER METHODS
510              
511             These methods operate on the high-performance memory-mapped capture buffer.
512              
513             An example of how to use these methods for packet capture is included in the
514             module distribution; see F for more detail.
515              
516             =cut
517              
518             =head2 setup_rx_ring
519              
520             $size = $sock->setup_rx_ring( $frame_size, $frame_nr, $block_size );
521              
522             Sets up the ring-buffer on the object. This method is identical to the
523             C function C, except that the ring-buffer
524             variable is stored transparently within the C<$sock> object; the caller does
525             not need to manage it.
526              
527             Once this buffer is enabled, the C, C and
528             C methods will automatically use it instead of the regular
529             C+C interface.
530              
531             =cut
532              
533             sub setup_rx_ring
534             {
535 0     0 1   my $self = shift;
536 0           my ( $frame_size, $frame_nr, $block_size ) = @_;
537              
538 0           my $ret = Socket::Packet::setup_rx_ring( $self, $frame_size, $frame_nr, $block_size );
539 0 0         ${*$self}{packet_rx_ring} = 1 if defined $ret;
  0            
540              
541 0           return $ret;
542             }
543              
544             =head2 get_ring_frame
545              
546             $len = $sock->get_ring_frame( $buffer, \%info );
547              
548             Receives the next packet from the ring-buffer. If there are no packets waiting
549             it will return undef. This method aliases the C<$buffer> variable to the
550             Ced packet buffer.
551              
552             For detail on the C<%info> hash, see L's C
553             function.
554              
555             Once the caller has finished with the C<$buffer> data, the C
556             method should be called to hand the frame buffer back to the kernel.
557              
558             =cut
559              
560             sub get_ring_frame
561             {
562 0     0 1   my $self = shift;
563              
564 0           return Socket::Packet::get_ring_frame( $self, $_[0], $_[1] );
565             }
566              
567             =head2 wait_ring_frame
568              
569             $len = $sock->wait_ring_frame( $buffer, \%info );
570              
571             If a packet is ready, this method sets C<$buffer> and C<%info> as per the
572             C method. If there are no packets waiting and the socket is
573             in blocking mode, it will C on the socket until a packet is
574             available. If the socket is in non-blocking mode, it will return false with
575             C<$!> set to C.
576              
577             For detail on the C<%info> hash, see L's C
578             function.
579              
580             Once the caller has finished with the C<$buffer> data, the C
581             method should be called to hand the frame buffer back to the kernel.
582              
583             =cut
584              
585             sub wait_ring_frame
586             {
587 0     0 1   my $self = shift;
588              
589 0           my $len;
590 0           while( !defined( $len = $self->get_ring_frame( $_[0], $_[1] ) ) ) {
591 0 0         $! = EAGAIN, return if not $self->blocking;
592              
593 0           my $rvec = '';
594 0           vec( $rvec, fileno $self, 1 ) = 1;
595 0 0         select( $rvec, undef, undef, undef ) or return;
596             }
597              
598 0           return $len;
599             }
600              
601             =head2 done_ring_frame
602              
603             $sock->done_ring_frame;
604              
605             Hands the current ring-buffer frame back to the kernel.
606              
607             =cut
608              
609             sub done_ring_frame
610             {
611 0     0 1   my $self = shift;
612              
613 0           Socket::Packet::done_ring_frame( $self );
614             }
615              
616             =head1 SEE ALSO
617              
618             =over 4
619              
620             =item *
621              
622             L - interface to Linux's C socket family
623              
624             =back
625              
626             =head1 AUTHOR
627              
628             Paul Evans
629              
630             =cut
631              
632             0x55AA;