File Coverage

blib/lib/Linux/SocketFilter.pm
Criterion Covered Total %
statement 33 33 100.0
branch 1 2 50.0
condition n/a
subroutine 11 11 100.0
pod 2 2 100.0
total 47 48 97.9


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, 2010 -- leonerd@leonerd.org.uk
5              
6             package Linux::SocketFilter;
7              
8 5     5   63881 use strict;
  5         11  
  5         187  
9 5     5   38 use warnings;
  5         10  
  5         191  
10              
11 5     5   34 use Carp;
  5         11  
  5         604  
12              
13             our $VERSION = '0.04';
14              
15 5     5   40 use Exporter 'import';
  5         10  
  5         186  
16              
17 5     5   4740 use Socket qw( SOL_SOCKET );
  5         21507  
  5         1080  
18              
19 5     5   2823 BEGIN { require Linux::SocketFilter_const; }
20 5     5   25 use constant SIZEOF_SOCK_FILTER => length pack_sock_filter( 0, 0, 0, 0 );
  5         6  
  5         20  
21              
22             push our @EXPORT_OK, qw(
23             attach_filter
24             detach_filter
25             );
26              
27             our %EXPORT_TAGS = (
28 5     5   40 bpf => [ do { no strict 'refs'; grep m/^BPF_/, keys %{__PACKAGE__."::"} } ],
  5         22  
  5         363  
29 5     5   23 skf => [ do { no strict 'refs'; grep m/^SKF_/, keys %{__PACKAGE__."::"} } ],
  5         9  
  5         1563  
30             );
31              
32             =head1 NAME
33              
34             C - interface to Linux's socket packet filtering
35              
36             =head1 SYNOPSIS
37              
38             use Linux::SocketFilter qw( :bpf pack_sock_filter );
39             use IO::Socket::Packet;
40             use Socket qw( SOCK_DGRAM );
41              
42             my $sock = IO::Socket::Packet->new(
43             IfIndex => 0,
44             Type => SOCK_DGRAM,
45             ) or die "Cannot socket - $!";
46              
47             $sock->attach_filter(
48             pack_sock_filter( BPF_RET|BPF_IMM, 0, 0, 20 )
49             );
50              
51             while( my $addr = $sock->recv( my $buffer, 20 ) ) {
52             printf "Packet: %v02x\n", $buffer;
53             }
54              
55             =head1 DESCRIPTION
56              
57             This module contains the constants and structure definitions to use Linux's
58             socket packet filtering mechanism.
59              
60             =cut
61              
62             =head1 CONSTANTS
63              
64             The following constants are exported:
65              
66             =head2 Socket Options
67              
68             SO_ATTACH_FILTER SO_DETACH_FILTER
69              
70             =head2 BPF Instructions
71              
72             BPF_LD BPF_LDX BPF_ST BPF_STX BPF_ALU BPF_JMP BPF_RET BPF_MISC
73             BPF_W BPF_H BPF_B BPF_IMM BPF_ABS BPF_IND BPF_MEM PBF_LEN BPF_MSH
74             BPF_ADD BPF_SUB BPF_MUL BPF_DIV BPF_OR BPF_AND BPF_LSH BPF_RSH BPF_NEG
75             BPF_JA BPF_JEQ BPF_JGT BPF_JGE BPF_JSET
76             BPF_K BPF_X BPF_A BPF_TAX BPF_TXA
77              
78             This entire set of constants is also exported under the tag name C<:bpf>.
79              
80             =head2 Linux BPF Extension Packet Addresses
81              
82             SKF_AD_OFF SKF_AD_PROTOCOL SKF_AD_PKTTYPE SKF_AD_IFINDEX
83             SKF_NET_OFF SKF_LL_OFF
84              
85             This entire set of constants is also exported under the tag name C<:skf>.
86              
87             =head1 STRUCTURE FUNCTIONS
88              
89             =head2 $buffer = pack_sock_filter( $code, $jt, $jf, $k )
90              
91             =head2 ( $code, $jt, $jf, $k ) = unpack_sock_filter( $buffer )
92              
93             Pack or unpack a single BPF instruction.
94              
95             =cut
96              
97             =head1 SOCKET FUNCTIONS
98              
99             The following exported functions are also provided as methods on the
100             C class.
101              
102             =cut
103              
104             =head2 attach_filter( $sock, $filter )
105              
106             =head2 $sock->attach_filter( $filter )
107              
108             Attaches the given filter program to the given socket. The program should be a
109             string formed by concatenating multiple calls to C to
110             build the filter program, or by using L.
111              
112             =cut
113              
114             sub attach_filter
115             {
116 2     2 1 446 my ( $sock, $filter ) = @_;
117              
118 2         4 my $fbytes = length $filter;
119 2 50       9 ( $fbytes % SIZEOF_SOCK_FILTER ) == 0 or
120             croak "Expected filter to be a multiple of ".SIZEOF_SOCK_FILTER." bytes";
121              
122 2         6 my $flen = $fbytes / SIZEOF_SOCK_FILTER;
123              
124             # TODO: ExtUtils::H2PM can't make this sort of function
125 2         11 my $struct_sock_fprog = pack( "S x![P] P", $flen, $filter );
126              
127 2         11 $sock->setsockopt( SOL_SOCKET, SO_ATTACH_FILTER, $struct_sock_fprog );
128             }
129              
130             *IO::Socket::attach_filter = \&attach_filter;
131              
132             =head2 detach_filter( $sock )
133              
134             =head2 $sock->detach_filter()
135              
136             Detaches the current filter from the socket, returning it to accepting all
137             packets.
138              
139             =cut
140              
141             sub detach_filter
142             {
143 2     2 1 1339 my ( $sock ) = @_;
144              
145             # We don't care about an option value, but kernel requires optlen to be at
146             # least sizeof(int).
147 2         9 $sock->setsockopt( SOL_SOCKET, SO_DETACH_FILTER, pack( "I", 0 ) );
148             }
149              
150             *IO::Socket::detach_filter = \&detach_filter;
151              
152             # Keep perl happy; keep Britain tidy
153             1;
154              
155             =head1 AUTHOR
156              
157             Paul Evans