Code

Added missing comments
[gosa.git] / gosa-si / modules / ArpWatch.pm
1 #!/usr/bin/perl
2 package POE::Component::ArpWatch;
4 use strict;
5 use warnings;
7 BEGIN{
8         eval('use POE');
9         eval('use POE::Component::Pcap');
10         eval('use NetPacket::Ethernet qw( :types )');
11         eval('use NetPacket::ARP qw( :opcodes )');
12 }
14 END{
15 }
17 ## Map arp opcode #'s to strings
18 my %arp_opcodes = (
19                    NetPacket::ARP::ARP_OPCODE_REQUEST, 'ARP Request',
20                    NetPacket::ARP::ARP_OPCODE_REPLY, 'ARP Reply',
21                    NetPacket::ARP::RARP_OPCODE_REQUEST, 'RARP Request',
22                    NetPacket::ARP::RARP_OPCODE_REPLY, 'RARP Reply',
23                   );
25 ##
26 ## POE::Component::ArpWatch->spawn(
27 ##                                 [ Alias => 'arp_watch' ],
28 ##                                 [ Device => 'eth0' ],
29 ##                                 [ Dispatch => dispatch_state ],
30 ##                                 [ Session => dispatch_session ],
31 ##                                )
32 ##
33 sub spawn {
34   my $class = shift;
35   my %args = @_;
37   $args{ Alias } ||= 'arp_watch';
39   POE::Session->create( 
40                        inline_states => {
41                                          _start => \&_start,
42 #                                        _signal => \&_signal,
43                                          _stop => \&_stop,,
44                                          _dispatch => \&_dispatch,
45                                          set_dispatch => \&set_dispatch,
46                                          run => \&run,
47                                          pause => \&pause,
48                                          shutdown => \&shutdown,
49                                         },
50                        args => [
51                                 $args{ Alias },   # ARG0
52                                 $args{ Device },  # ARG1
53                                 $args{ Dispatch },# ARG2
54                                 $args{ Session }, # ARG3
55                                ],
56                       );
58   return $args{ Alias };
59 }
61 sub _start {
62   my ($kernel, $heap, $session, 
63       $alias, $device, $target_state, $target_session ) 
64     = @_[ KERNEL, HEAP, SESSION, ARG0..ARG3 ];
66   POE::Component::Pcap->spawn( 
67                               Alias => $alias . '_pcap',
68                               Device => $device, 
69                               Filter => 'arp',
70                               Dispatch => '_dispatch',
71                               Session => $session,
72                              );
74   $heap->{'pcap_session'} = $kernel->alias_resolve( $alias . '_pcap' );
76   ## Set alias for ourselves and remember it
77   $kernel->alias_set( $alias );
78   $heap->{Alias} = $alias;
80   ## Set dispatch target session and state if it was given
81   if( defined( $target_session ) ) {
82     $heap->{'target_session'} = $target_session;
83     $heap->{'target_state'} = $target_state;
84   }
85 }
87 sub set_dispatch {
88   my( $heap, $sender, $target ) = @_[ HEAP, SENDER, ARG0 ];
90   if( defined $target ) {
91     ## Remember whome to forward results to
92     $heap->{'target_session'} = $sender;
93     $heap->{'target_state'} = $target;
94   } else {
95     ## Clear target
96     delete $heap->{'target_session'};
97     delete $heap->{'target_state'};
98   }
99 }
101 sub run {
102   $_[KERNEL]->post( $_[HEAP]->{'pcap_session'} => 'run' );
105 sub pause {
106   $_[KERNEL]->post( $_[HEAP]->{'pcap_session'} => 'pause' );
109 sub _dispatch {
110   my( $kernel, $heap, $packets ) =
111     @_[ KERNEL, HEAP, ARG0 ];
113   if( exists $heap->{'target_session'} ) {
114     $kernel->post( $heap->{'target_session'}, 
115                    $heap->{'target_state'}, 
116                    _process_packet( @{ $_ } ) ) foreach( @{$packets} );
117   }
120 sub _signal {
121   # print "Got signal ", $_[ARG0], "\n";
123   $_[KERNEL]->post( pcap => 'shutdown' );
125   return 1
128 sub shutdown {
129   my ( $kernel, $heap, $session, $sender ) 
130     = @_[ KERNEL, HEAP, SESSION, SENDER ];
131   my $alias = $heap->{Alias};
133 #  print "In shutdown for sid ", $session->ID, ", alias $alias\n"; 
134 #  print "shutdown by ", $sender->ID, "\n";
136   $kernel->post( $heap->{'pcap_session'} => 'shutdown' );
138   $kernel->alias_remove( $alias );
140 #  print "Out shutdown for sid ", $session->ID, ", alias $alias\n"; 
143 sub _stop {
144   my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ];
145   my $alias = $heap->{Alias};
147 #  print "In state_stop for sid ", $session->ID, ", alias $alias\n"; 
149 #  print "Out state_stop for sid ", $session->ID, ", alias $alias\n"; 
152 sub _process_packet {
153   my( $hdr, $pkt ) = @_;
155   my $arp = 
156     NetPacket::ARP->decode( NetPacket::Ethernet->decode($pkt)->{data} );
158   ## Return hashref with apropriate fields
159   return { 
160           type => $arp_opcodes{ $arp->{opcode} },
161           tv_sec => $hdr->{tv_sec},
162           tv_usec => $hdr->{tv_usec},
163           source_haddr => _phys( $arp->{sha} ), 
164           source_ipaddr => _ipaddr( $arp->{spa} ),
165           target_haddr => _phys( $arp->{tha} ),
166           target_ipaddr => _ipaddr( $arp->{tpa} ),
167          }
170 ## Pretty printing subs for addresses
171 sub _ipaddr { join( ".", unpack( "C4", pack( "N", oct( "0x". shift ) ) ) ) }
172 sub _phys { join( ":", grep {length} split( /(..)/, shift ) ) }
174 # vim:ts=4:shiftwidth:expandtab
175 1;
177 __END__