index 16c8c1695c990dd561b8d04d5ea32fa99f46d2b3..be47d61400b9fdf05cb67725313445a27df369ed 100644 (file)
use strict;
use warnings;
use GOSA::GosaSupportDaemon;
use strict;
use warnings;
use GOSA::GosaSupportDaemon;
-use Getopt::Long;
-use Config::IniFiles;
use POSIX;
use Fcntl;
use Net::LDAP;
use POSIX;
use Fcntl;
use Net::LDAP;
use Net::DNS;
use Switch;
use Data::Dumper;
use Net::DNS;
use Switch;
use Data::Dumper;
-use POE qw(Component::Pcap Component::ArpWatch);
-BEGIN{}
+# Don't start if some of the modules are missing
+my $start_service=1;
+BEGIN{
+ unless(eval('use Socket qw(PF_INET SOCK_DGRAM inet_ntoa sockaddr_in)')) {
+ $start_service=0;
+ }
+ unless(eval('use POE qw(Component::Pcap Component::ArpWatch)')) {
+ $start_service=0;
+ }
+}
+
END{}
END{}
-my ($verbose, $cfg_file, $log_file, $pid_file, $foreground);
my ($timeout, $mailto, $mailfrom, $user, $group);
my ($timeout, $mailto, $mailfrom, $user, $group);
-my ($procid, $pid, $loglevel);
-my ($fifo_path, $max_process_timeout, $max_process );
my %daemon_children;
my %daemon_children;
-my ($ldap, $bind_phrase, $password, $ldap_base) ;
+my ($ldap, $bind_phrase, $password, $ldap_base, $interface) ;
my $hosts_database={};
my $resolver=Net::DNS::Resolver->new;
my $hosts_database={};
my $resolver=Net::DNS::Resolver->new;
-$procid = -1 ;
-$foreground = 0 ;
-$verbose = 0 ;
-$max_process = 2 ;
-$max_process_timeout = 1 ;
$ldap_base = "dc=gonicus,dc=de" ;
$ldap_base = "dc=gonicus,dc=de" ;
-#$ldap_path = "/var/run/gosa-support-daemon.socket";
-#$log_path = "/var/log/gosa-support-daemon.log";
-#$pid_path = "/var/run/gosa-support-daemon/gosa-support-daemon.pid";
-
-#---------------------------------------------------------------------------
-# parse commandline options
-#---------------------------------------------------------------------------
-#Getopt::Long::Configure( "bundling" );
-#GetOptions( "v|verbose+" => \$verbose,
-# "c|config=s" => \$cfg_file,
-# "h|help" => \&usage,
-# "l|logfile=s" => \$log_file,
-# "p|pid=s" => \$pid_file,
-# "f|foreground" => \$foreground);
-#
-#---------------------------------------------------------------------------
-# read and set config parameters
-#---------------------------------------------------------------------------
-#my %cfg_defaults =
-#("Allgemein" =>
-# {"timeout" => [ \$timeout, 1000 ],
-# "mailto" => [ \$mailto, 'root@localhost' ],
-# "mailfrom" => [ \$mailfrom, 'sps-daemon@localhost' ],
-# "user" => [ \$user, "nobody" ],
-# "group" => [ \$group, "nogroup" ],
-# "fifo_path" => [ \$fifo_path, "/home/rettenbe/gonicus/gosa-support/tmp/fifo" ],
-# "log_file" => [ \$log_file, "/home/rettenbe/gonicus/gosa-support/tmp/gosa-support.log" ],
-# "pid_file" => [ \$pid_file, "/home/rettenbe/gonicus/gosa-support/tmp/gosa-support.pid" ],
-# "loglevel" => [ \$loglevel, 1]
-# },
-#"LDAP" =>
-# {"bind" => [ \$bind_phrase, "cn=ldapadmin,dc=gonicus,dc=de" ],
-# "password" => [ \$password, "tester" ],
-# }
-# );
-#&read_configfile;
+$interface = "all";
sub get_module_info {
my @info = (undef,
sub get_module_info {
my @info = (undef,
"socket",
);
"socket",
);
- my $device = 'eth0';
- $ldap = Net::LDAP->new("ldap.intranet.gonicus.de") or die "$@";
-
- POE::Session->create(
- inline_states => {
- _start => \&start,
- _stop => sub {
- $_[KERNEL]->post( arp_watch => 'shutdown' )
- },
- got_packet => \&got_packet,
- },
- );
+ # Don't start if some of the modules are missing
+ if($start_service) {
+ eval {
+ $ldap = Net::LDAP->new("ldap.intranet.gonicus.de");
+ };
+ if ($@) {
+ &main::daemon_log("Could not connect to LDAP Server!\n$@", 1);
+ } else {
+ &main::daemon_log("Could not connect to LDAP Server!\n$@", 1);
+
+ }
+
+ # When interface is not configured (or 'all'), start arpwatch on all possible interfaces
+ if ((!defined($interface)) || $interface eq 'all') {
+ foreach my $device(&get_interfaces) {
+ # TODO: Need a better workaround for IPv4-to-IPv6 bridges
+ if($device =~ m/^sit\d+$/) {
+ next;
+ }
- return \@info;
+ # If device has a valid mac address
+ if(not(&get_mac($device) eq "00:00:00:00:00:00")) {
+ &main::daemon_log("Starting ArpWatch on $device", 1);
+ POE::Session->create(
+ inline_states => {
+ _start => sub {
+ &start(@_,$device);
+ },
+ _stop => sub {
+ $_[KERNEL]->post( sprintf("arp_watch_$device") => 'shutdown' )
+ },
+ got_packet => \&got_packet,
+ },
+ );
+ }
+ }
+ } else {
+ foreach my $device(split(/[\s,]+/, $interface)) {
+ &main::daemon_log("Starting ArpWatch on $device", 1);
+ POE::Session->create(
+ inline_states => {
+ _start => sub {
+ &start(@_,$device);
+ },
+ _stop => sub {
+ $_[KERNEL]->post( sprintf("arp_watch_$device") => 'shutdown' )
+ },
+ got_packet => \&got_packet,
+ },
+ );
+ }
+ }
+ }
+ return \@info;
}
sub process_incoming_msg {
}
sub process_incoming_msg {
- return 0;
+ return 1;
}
sub start {
}
sub start {
+ my $device = (exists($_[ARG0])?$_[ARG0]:'eth0');
POE::Component::ArpWatch->spawn(
POE::Component::ArpWatch->spawn(
- Alias => 'arp_watch',
- Device => 'eth0',
+ Alias => sprintf("arp_watch_$device"),
+ Device => $device,
Dispatch => 'got_packet',
Session => $_[SESSION],
);
Dispatch => 'got_packet',
Session => $_[SESSION],
);
- $_[KERNEL]->post( arp_watch => 'run' );
+ $_[KERNEL]->post( sprintf("arp_watch_$device") => 'run' );
}
sub got_packet {
my $packet = $_[ARG0];
}
sub got_packet {
my $packet = $_[ARG0];
- if($packet->{source_haddr} eq "00:00:00:00:00:00" ||
+ if( $packet->{source_haddr} eq "00:00:00:00:00:00" ||
$packet->{source_haddr} eq "ff:ff:ff:ff:ff:ff" ||
$packet->{source_ipaddr} eq "0.0.0.0") {
return;
}
if(!exists($hosts_database->{$packet->{source_haddr}})) {
$packet->{source_haddr} eq "ff:ff:ff:ff:ff:ff" ||
$packet->{source_ipaddr} eq "0.0.0.0") {
return;
}
if(!exists($hosts_database->{$packet->{source_haddr}})) {
+ my $dnsresult= $resolver->search($packet->{source_ipaddr});
+ my $dnsname= (defined($dnsresult))?$dnsresult->{answer}[0]->{ptrdname}:$packet->{source_ipaddr};
my $ldap_result=&get_host_from_ldap($packet->{source_haddr});
if(exists($ldap_result->{dn})) {
$hosts_database->{$packet->{source_haddr}}=$ldap_result;
my $ldap_result=&get_host_from_ldap($packet->{source_haddr});
if(exists($ldap_result->{dn})) {
$hosts_database->{$packet->{source_haddr}}=$ldap_result;
- $hosts_database->{$packet->{source_haddr}}->{dnsname}=($resolver->search($packet->{source_ipaddr}))->{answer}[0]->{ptrdname};
- print STDERR "Host was found in LDAP as ".$ldap_result->{dn}."\n";
+ if(!exists($ldap_result->{ipHostNumber})) {
+ $hosts_database->{$packet->{source_haddr}}->{ipHostNumber}=$packet->{source_ipaddr};
+ } else {
+ if(!($ldap_result->{ipHostNumber} eq $packet->{source_ipaddr})) {
+ &main::daemon_log(
+ "Current IP Address ".$packet->{source_ipaddr}.
+ " of host ".$ldap_result->{dnsname}.
+ " differs from LDAP (".$ldap_result->{ipHostNumber}.")", 4);
+ }
+ }
+ $hosts_database->{$packet->{source_haddr}}->{dnsname}=$dnsname;
+ &main::daemon_log("Host was found in LDAP as ".$ldap_result->{dn}, 6);
} else {
$hosts_database->{$packet->{source_haddr}}={
macAddress => $packet->{source_haddr},
ipHostNumber => $packet->{source_ipaddr},
} else {
$hosts_database->{$packet->{source_haddr}}={
macAddress => $packet->{source_haddr},
ipHostNumber => $packet->{source_ipaddr},
- dnsname => ($resolver->search($packet->{source_ipaddr}))->{answer}[0]->{ptrdname},
+ dnsname => $dnsname,
};
};
- print STDERR "Host was not found in LDAP (".($hosts_database->{$packet->{source_haddr}}->{dnsname}).")\n";
+ &main::daemon_log("Host was not found in LDAP (".($hosts_database->{$packet->{source_haddr}}->{dnsname}).")",6);
+ &main::daemon_log(
+ "New Host ".($hosts_database->{$packet->{source_haddr}}->{dnsname}).
+ ": ".$hosts_database->{$packet->{source_haddr}}->{ipHostNumber}.
+ "/".$hosts_database->{$packet->{source_haddr}}->{macAddress},4);
}
} else {
}
} else {
- print STDERR "Host already in cache (".($hosts_database->{$packet->{source_haddr}}->{dnsname}).")\n";
+ if(!($hosts_database->{$packet->{source_haddr}}->{ipHostNumber} eq $packet->{source_ipaddr})) {
+ &main::daemon_log(
+ "IP Address change of MAC ".$packet->{source_haddr}.
+ ": ".$hosts_database->{$packet->{source_haddr}}->{ipHostNumber}.
+ "->".$packet->{source_ipaddr}, 4);
+ $hosts_database->{$packet->{source_haddr}}->{ipHostNumber}= $packet->{source_ipaddr};
+ }
+ &main::daemon_log("Host already in cache (".($hosts_database->{$packet->{source_haddr}}->{dnsname}).")",6);
}
}
}
}
return $result;
}
return $result;
}
+#=== FUNCTION ================================================================
+# NAME: get_interfaces
+# PARAMETERS: none
+# RETURNS: (list of interfaces)
+# DESCRIPTION: Uses proc fs (/proc/net/dev) to get list of interfaces.
+#===============================================================================
+sub get_interfaces {
+ my @result;
+ my $PROC_NET_DEV= ('/proc/net/dev');
+
+ open(PROC_NET_DEV, "<$PROC_NET_DEV")
+ or die "Could not open $PROC_NET_DEV";
+
+ my @ifs = <PROC_NET_DEV>;
+
+ close(PROC_NET_DEV);
+
+ # Eat first two line
+ shift @ifs;
+ shift @ifs;
+
+ chomp @ifs;
+ foreach my $line(@ifs) {
+ my $if= (split /:/, $line)[0];
+ $if =~ s/^\s+//;
+ push @result, $if;
+ }
+
+ return @result;
+}
+
+#=== FUNCTION ================================================================
+# NAME: get_mac
+# PARAMETERS: interface name (i.e. eth0)
+# RETURNS: (mac address)
+# DESCRIPTION: Uses ioctl to get mac address directly from system.
+#===============================================================================
+sub get_mac {
+ my $ifreq= shift;
+ my $result;
+ if ($ifreq && length($ifreq) > 0) {
+ if($ifreq eq "all") {
+ $result = "00:00:00:00:00:00";
+ } else {
+ my $SIOCGIFHWADDR= 0x8927; # man 2 ioctl_list
+
+ socket SOCKET, PF_INET, SOCK_DGRAM, getprotobyname('ip')
+ or die "socket: $!";
+
+ if(ioctl SOCKET, $SIOCGIFHWADDR, $ifreq) {
+ my ($if, $mac)= unpack 'h36 H12', $ifreq;
+
+ if (length($mac) > 0) {
+ $mac=~ m/^([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$/;
+ $mac= sprintf("%s:%s:%s:%s:%s:%s", $1, $2, $3, $4, $5, $6);
+ $result = $mac;
+ }
+ }
+ }
+ }
+ return $result;
+}
#=== FUNCTION ================================================================
# NAME: add_ldap_entry
#=== FUNCTION ================================================================
# NAME: add_ldap_entry