Code

finished jobs are set to 'done' and deleted from job queue
[gosa.git] / gosa-si / modules / ArpWatch.pm
1 #!/usr/bin/perl
2 package POE::Component::ArpWatch;
4 use strict;
5 use warnings;
6 use utf8;
8 BEGIN{
9         eval('use POE');
10         eval('use POE::Component::Pcap');
11         eval('use NetPacket::Ethernet qw( :types )');
12         eval('use NetPacket::ARP qw( :opcodes )');
13 }
15 END{
16 }
18 ## Map arp opcode #'s to strings
19 my %arp_opcodes = (
20                    NetPacket::ARP::ARP_OPCODE_REQUEST, 'ARP Request',
21                    NetPacket::ARP::ARP_OPCODE_REPLY, 'ARP Reply',
22                    NetPacket::ARP::RARP_OPCODE_REQUEST, 'RARP Request',
23                    NetPacket::ARP::RARP_OPCODE_REPLY, 'RARP Reply',
24                   );
26 ##
27 ## POE::Component::ArpWatch->spawn(
28 ##                                 [ Alias => 'arp_watch' ],
29 ##                                 [ Device => 'eth0' ],
30 ##                                 [ Dispatch => dispatch_state ],
31 ##                                 [ Session => dispatch_session ],
32 ##                                )
33 ##
34 sub spawn {
35   my $class = shift;
36   my %args = @_;
38   $args{ Alias } ||= 'arp_watch';
40   POE::Session->create( 
41                        inline_states => {
42                                          _start => \&_start,
43 #                                        _signal => \&_signal,
44                                          _stop => \&_stop,,
45                                          _dispatch => \&_dispatch,
46                                          set_dispatch => \&set_dispatch,
47                                          run => \&run,
48                                          pause => \&pause,
49                                          shutdown => \&shutdown,
50                                         },
51                        args => [
52                                 $args{ Alias },   # ARG0
53                                 $args{ Device },  # ARG1
54                                 $args{ Dispatch },# ARG2
55                                 $args{ Session }, # ARG3
56                                ],
57                       );
59   return $args{ Alias };
60 }
62 sub _start {
63   my ($kernel, $heap, $session, 
64       $alias, $device, $target_state, $target_session ) 
65     = @_[ KERNEL, HEAP, SESSION, ARG0..ARG3 ];
67   POE::Component::Pcap->spawn( 
68                               Alias => $alias . '_pcap',
69                               Device => $device, 
70                               Filter => 'arp',
71                               Dispatch => '_dispatch',
72                               Session => $session,
73                              );
75   $heap->{'pcap_session'} = $kernel->alias_resolve( $alias . '_pcap' );
77   ## Set alias for ourselves and remember it
78   $kernel->alias_set( $alias );
79   $heap->{Alias} = $alias;
81   ## Set dispatch target session and state if it was given
82   if( defined( $target_session ) ) {
83     $heap->{'target_session'} = $target_session;
84     $heap->{'target_state'} = $target_state;
85   }
86 }
88 sub set_dispatch {
89   my( $heap, $sender, $target ) = @_[ HEAP, SENDER, ARG0 ];
91   if( defined $target ) {
92     ## Remember whome to forward results to
93     $heap->{'target_session'} = $sender;
94     $heap->{'target_state'} = $target;
95   } else {
96     ## Clear target
97     delete $heap->{'target_session'};
98     delete $heap->{'target_state'};
99   }
102 sub run {
103   $_[KERNEL]->post( $_[HEAP]->{'pcap_session'} => 'run' );
106 sub pause {
107   $_[KERNEL]->post( $_[HEAP]->{'pcap_session'} => 'pause' );
110 sub _dispatch {
111   my( $kernel, $heap, $packets ) =
112     @_[ KERNEL, HEAP, ARG0 ];
114   if( exists $heap->{'target_session'} ) {
115     $kernel->post( $heap->{'target_session'}, 
116                    $heap->{'target_state'}, 
117                    _process_packet( @{ $_ } ) ) foreach( @{$packets} );
118   }
121 sub _signal {
122   # print "Got signal ", $_[ARG0], "\n";
124   $_[KERNEL]->post( pcap => 'shutdown' );
126   return 1
129 sub shutdown {
130   my ( $kernel, $heap, $session, $sender ) 
131     = @_[ KERNEL, HEAP, SESSION, SENDER ];
132   my $alias = $heap->{Alias};
134 #  print "In shutdown for sid ", $session->ID, ", alias $alias\n"; 
135 #  print "shutdown by ", $sender->ID, "\n";
137   $kernel->post( $heap->{'pcap_session'} => 'shutdown' );
139   $kernel->alias_remove( $alias );
141 #  print "Out shutdown for sid ", $session->ID, ", alias $alias\n"; 
144 sub _stop {
145   my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ];
146   my $alias = $heap->{Alias};
148 #  print "In state_stop for sid ", $session->ID, ", alias $alias\n"; 
150 #  print "Out state_stop for sid ", $session->ID, ", alias $alias\n"; 
153 sub _process_packet {
154   my( $hdr, $pkt ) = @_;
156   my $arp = 
157     NetPacket::ARP->decode( NetPacket::Ethernet->decode($pkt)->{data} );
159   ## Return hashref with apropriate fields
160   return { 
161           type => $arp_opcodes{ $arp->{opcode} },
162           tv_sec => $hdr->{tv_sec},
163           tv_usec => $hdr->{tv_usec},
164           source_haddr => _phys( $arp->{sha} ), 
165           source_ipaddr => _ipaddr( $arp->{spa} ),
166           target_haddr => _phys( $arp->{tha} ),
167           target_ipaddr => _ipaddr( $arp->{tpa} ),
168          }
171 ## Pretty printing subs for addresses
172 sub _ipaddr { join( ".", unpack( "C4", pack( "N", oct( "0x". shift ) ) ) ) }
173 sub _phys { join( ":", grep {length} split( /(..)/, shift ) ) }
175 1;
177 __END__