File Coverage

blib/lib/IO/Socket/Netlink/Generic.pm
Criterion Covered Total %
statement 52 65 80.0
branch 5 14 35.7
condition n/a
subroutine 17 19 89.4
pod 6 8 75.0
total 80 106 75.4


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-2016 -- leonerd@leonerd.org.uk
5              
6             package IO::Socket::Netlink::Generic;
7              
8 2     2   1598 use strict;
  2         23  
  2         54  
9 2     2   8 use warnings;
  2         2  
  2         52  
10 2     2   6 use base qw( IO::Socket::Netlink );
  2         2  
  2         577  
11              
12             our $VERSION = '0.05';
13              
14 2     2   10 use Carp;
  2         2  
  2         116  
15              
16 2         1058 use Socket::Netlink::Generic qw(
17             NETLINK_GENERIC
18             CTRL_CMD_GETFAMILY
19 2     2   19 );
  2         3  
20              
21             __PACKAGE__->register_protocol( NETLINK_GENERIC );
22              
23             =head1 NAME
24              
25             C - Object interface to C
26             netlink protocol sockets
27              
28             =head1 SYNOPSIS
29              
30             use IO::Socket::Netlink::Generic;
31              
32             my $genlsock = IO::Socket::Netlink::Generic->new or die "socket: $!";
33              
34             printf "TASKSTATS family ID is %d\n",
35             $genlsock->get_family_by_name( "TASKSTATS" )->{id};
36              
37             =head1 DESCRIPTION
38              
39             This subclass of L implements the C
40             protocol. It is itself intended to serve as a base class for particular
41             generic families to extend.
42              
43             =cut
44              
45             =head1 CLASS METHODS
46              
47             =head2 register_family_name
48              
49             $class->register_family_name( $name )
50              
51             Must be called by a subclass implementing a particular protocol family, to
52             declare its family name. The first time a socket in that class is constructed,
53             this name will be looked up into an ID number.
54              
55             =cut
56              
57             my %pkg2familyname;
58             my %familyname2pkg;
59              
60             sub register_family_name
61             {
62 0     0 1 0 my ( $pkg, $family_name ) = @_;
63              
64 0         0 $pkg2familyname{$pkg} = $family_name;
65 0         0 $familyname2pkg{$family_name} = $pkg;
66             }
67              
68             sub new
69             {
70 1     1 1 14 my $class = shift;
71 1         11 $class->SUPER::new( Protocol => NETLINK_GENERIC, @_ );
72             }
73              
74             sub configure
75             {
76 1     1 0 100 my $self = shift;
77 1         2 my ( $arg ) = @_;
78              
79 1         7 my $ret = $self->SUPER::configure( $arg );
80              
81 1         1 my $class = ref $self;
82 1 50       4 if( $class ne __PACKAGE__ ) {
83 0 0       0 defined( my $family_name = $pkg2familyname{$class} ) or
84             croak "No family name defined for $class";
85              
86 0         0 my $family_id = $self->get_family_by_name( $family_name )->{id};
87 0         0 $class->message_class->register_nlmsg_type( $family_id );
88              
89 0         0 ${*$self}{default_nlmsg_type} = $family_id;
  0         0  
90             }
91              
92 1         5 return $ret;
93             }
94              
95             sub new_message
96             {
97 3     3 1 1271 my $self = shift;
98              
99             $self->SUPER::new_message(
100 3 50       10 ( defined ${*$self}{default_nlmsg_type} ? ( nlmsg_type => ${*$self}{default_nlmsg_type} ) : () ),
  3         22  
  0         0  
101             @_,
102             );
103             }
104              
105             sub new_command
106             {
107 0     0 1 0 my $self = shift;
108              
109             $self->SUPER::new_command(
110 0 0       0 ( defined ${*$self}{default_nlmsg_type} ? ( nlmsg_type => ${*$self}{default_nlmsg_type} ) : () ),
  0         0  
  0         0  
111             @_,
112             );
113             }
114              
115             sub message_class
116             {
117 5     5 0 36 return "IO::Socket::Netlink::Generic::_Message";
118             }
119              
120             =head1 METHODS
121              
122             =cut
123              
124             =head2 get_family_by_name
125              
126             $family = $sock->get_family_by_name( $name )
127              
128             =cut
129              
130             sub get_family_by_name
131             {
132 1     1 1 1594 my $self = shift;
133 1         3 my ( $name ) = @_;
134              
135 1         2 return $self->_get_family( name => $name );
136             }
137              
138             =head2 get_family_by_id
139              
140             $family = $sock->get_family_by_id( $id )
141              
142             =cut
143              
144             sub get_family_by_id
145             {
146 1     1 1 1523 my $self = shift;
147 1         2 my ( $id ) = @_;
148              
149 1         4 return $self->_get_family( id => $id );
150             }
151              
152             =pod
153              
154             Query the kernel for information on the C family specifed by
155             name or ID number, and return information about it. Returns a HASH reference
156             containing the following fields:
157              
158             =over 8
159              
160             =item id => NUMBER
161              
162             =item name => STRING
163              
164             =item version => NUMBER
165              
166             =item hdrsize => NUMBER
167              
168             =item maxattr => NUMBER
169              
170             =back
171              
172             =cut
173              
174             sub _get_family
175             {
176 2     2   4 my $self = shift;
177 2         6 my %searchattrs = @_;
178              
179 2 50       14 $self->send_nlmsg( $self->new_request(
180             nlmsg_type => NETLINK_GENERIC,
181              
182             cmd => CTRL_CMD_GETFAMILY,
183             nlattrs => \%searchattrs,
184             ) ) or croak "Cannot send - $!";
185              
186 2 50       104 $self->recv_nlmsg( my $message, 32768 ) or
187             croak "Cannot recv - $!";
188              
189 2 50       5 $message->nlmsg_type == NETLINK_GENERIC or
190             croak "Expected nlmsg_type == NETLINK_GENERIC";
191              
192 2         6 return $message->nlattrs;
193             }
194              
195             package IO::Socket::Netlink::Generic::_Message;
196              
197 2     2   10 use base qw( IO::Socket::Netlink::_Message );
  2         2  
  2         542  
198              
199 2     2   10 use Carp;
  2         2  
  2         101  
200              
201 2         839 use Socket::Netlink::Generic qw(
202             :DEFAULT
203             pack_genlmsghdr unpack_genlmsghdr
204 2     2   10 );
  2         34  
205              
206             =head1 MESSAGE OBJECTS
207              
208             Sockets in this class provide the following extra field accessors on their
209             message objects:
210              
211             =cut
212              
213             __PACKAGE__->is_subclassed_by_type;
214              
215             __PACKAGE__->register_nlmsg_type( NETLINK_GENERIC );
216              
217             =over 8
218              
219             =item * $message->cmd
220              
221             ID number of the command to give to the family
222              
223             =item * $message->version
224              
225             Version number of the interface
226              
227             =item * $message->genlmsg
228              
229             Accessor for the trailing data buffer; intended for subclasses to use
230              
231             =back
232              
233             =cut
234              
235             __PACKAGE__->is_header(
236             data => "nlmsg",
237             fields => [
238             [ cmd => 'decimal' ],
239             [ version => 'decimal' ],
240             [ genlmsg => 'bytes' ],
241             ],
242             pack => \&pack_genlmsghdr,
243             unpack => \&unpack_genlmsghdr,
244             );
245              
246             sub nlmsg_string
247             {
248 1     1   2 my $self = shift;
249 1         4 return sprintf "cmd=%d,version=%d,%s", $self->cmd, $self->version, $self->genlmsg_string;
250             }
251              
252             sub genlmsg_string
253             {
254 1     1   1 my $self = shift;
255 1         6 return sprintf "{%d bytes}", length $self->genlmsg;
256             }
257              
258             __PACKAGE__->has_nlattrs(
259             "genlmsg",
260             id => [ CTRL_ATTR_FAMILY_ID, "u16" ],
261             name => [ CTRL_ATTR_FAMILY_NAME, "asciiz" ],
262             version => [ CTRL_ATTR_VERSION, "u32" ],
263             hdrsize => [ CTRL_ATTR_HDRSIZE, "u32" ],
264             maxattr => [ CTRL_ATTR_MAXATTR, "u32" ],
265             );
266              
267             =head1 SEE ALSO
268              
269             =over 4
270              
271             =item *
272              
273             L - interface to Linux's C netlink
274             socket protocol
275              
276             =item *
277              
278             L - Object interface to C domain sockets
279              
280             =back
281              
282             =head1 AUTHOR
283              
284             Paul Evans
285              
286             =cut
287              
288             0x55AA;