index 803a95614b59ab74404383046d85e4c1207a67eb..cb7c976f95d75ca3a8d34a9fe36ce37c891d6f4d 100644 (file)
use Exporter;
@ISA = ("Exporter");
-# Each module has to have a function 'process_incoming_msg'. This function works as a interface to gosa-sd and recieves the msg hash from gosa-sd. 'process_incoming_function checks, wether it has a function to process the incoming msg and forward the msg to it.
+# Each module has to have a function 'process_incoming_msg'. This function works as a interface to gosa-sd and receives the msg hash from gosa-sd. 'process_incoming_function checks, wether it has a function to process the incoming msg and forward the msg to it.
use strict;
use XML::Simple;
use Data::Dumper;
use Net::LDAP;
+use Socket qw/PF_INET SOCK_DGRAM inet_ntoa sockaddr_in/;
BEGIN{}
END {}
my ($known_clients_file_name);
-my ($server_activ, $server_port, $server_passwd, $max_clients, $ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password);
+my ($server_activ, $server_ip, $server_mac_address, $server_port, $server_passwd, $max_clients, $ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password);
my ($bus_activ, $bus_passwd, $bus_ip, $bus_port);
my $server;
+my $network_interface;
my $no_bus;
my (@ldap_cfg, @pam_cfg, @nss_cfg, $goto_admin, $goto_secret);
(
"server" =>
{"server_activ" => [\$server_activ, "on"],
+ "server_ip" => [\$server_ip, "0.0.0.0"],
+ "server_mac_address" => [\$server_mac_address, ""],
"server_port" => [\$server_port, "20081"],
"server_passwd" => [\$server_passwd, ""],
"max_clients" => [\$max_clients, 100],
### START #####################################################################
-
# read configfile and import variables
&read_configfile();
-# detect own ip and mac address
-my ($server_ip, $server_mac_address) = &get_ip_and_mac();
-if (not defined $server_ip) {
- die "EXIT: ip address of $0 could not be detected";
-}
-&main::daemon_log("server ip address detected: $server_ip", 1);
-&main::daemon_log("server mac address detected: $server_mac_address", 1);
+# detect interfaces and mac address
+$network_interface= &get_interface_for_ip($server_ip);
+$server_mac_address= &get_mac($network_interface);
# complete addresses
my $server_address = "$server_ip:$server_port";
# create general settings for this module
my $xml = new XML::Simple();
-# open server socket
-if($server_activ eq "on"){
- &main::daemon_log(" ", 1);
- $server = IO::Socket::INET->new(LocalPort => $server_port,
- Type => SOCK_STREAM,
- Reuse => 1,
- Listen => 20,
- );
- if(not defined $server){
- &main::daemon_log("cannot be a tcp server at $server_port : $@");
- } else {
- &main::daemon_log("start server: $server_address", 1);
- }
-}
-
-# TODO
-# füge den server selbst zu known_server hinzu, msgs können nämlich auch von sich selbst kommen (gosa!!!)
-
-
# register at bus
if ($main::no_bus > 0) {
$bus_activ = "off"
}
if($bus_activ eq "on") {
- &main::daemon_log(" ", 1);
®ister_at_bus();
}
### functions #################################################################
-#sub get_module_tags {
-#
-# # lese config file aus dort gibt es eine section Basic
-# # dort stehen drei packettypen, für die sich das modul anmelden kann, gosa-admin-packages,
-# # server-packages, client-packages
-# my %tag_hash = (gosa_admin_packages => "yes",
-# server_packages => "yes",
-# client_packages => "yes",
-# );
-# return \%tag_hash;
-#}
-
sub get_module_info {
my @info = ($server_address,
}
+#=== FUNCTION ================================================================
+# NAME: get_interface_for_ip
+# PARAMETERS: ip address (i.e. 192.168.0.1)
+# RETURNS: array: list of interfaces if ip=0.0.0.0, matching interface if found, undef else
+# DESCRIPTION: Uses proc fs (/proc/net/dev) to get list of interfaces.
+#===============================================================================
+sub get_interface_for_ip {
+ my $result;
+ my $ip= shift;
+ if ($ip && length($ip) > 0) {
+ my @ifs= &get_interfaces();
+ if($ip eq "0.0.0.0") {
+ $result = "all";
+ } else {
+ foreach (@ifs) {
+ my $if=$_;
+ if(get_ip($if) eq $ip) {
+ $result = $if;
+ }
+ }
+ }
+ }
+ return $result;
+}
#=== FUNCTION ================================================================
-# NAME: get_ip_and_mac
-# PARAMETERS: nothing
-# RETURNS: (ip, mac)
-# DESCRIPTION: executes /sbin/ifconfig and parses the output, the first occurence
-# of a inet address is returned as well as the mac address in the line
-# above the inet address
+# NAME: get_interfaces
+# PARAMETERS: none
+# RETURNS: (list of interfaces)
+# DESCRIPTION: Uses proc fs (/proc/net/dev) to get list of interfaces.
#===============================================================================
-sub get_ip_and_mac {
- my $ip = "0.0.0.0.0"; # Defualt-IP
- my $mac = "00:00:00:00:00:00"; # Default-MAC
- my @ifconfig = qx(/sbin/ifconfig);
- foreach(@ifconfig) {
- if (/Hardware Adresse (\S{2}):(\S{2}):(\S{2}):(\S{2}):(\S{2}):(\S{2})/) {
- $mac = "$1:$2:$3:$4:$5:$6";
- next;
- }
- if (/inet Adresse:(\d+).(\d+).(\d+).(\d+)/) {
- $ip = "$1.$2.$3.$4";
- last;
- }
- }
- return ($ip, $mac);
+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
+
+ # A configured MAC Address should always override a guessed value
+ if ($server_mac_address and length($server_mac_address) > 0) {
+ $result= $server_mac_address;
+ }
+
+ 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: get_ip
+# PARAMETERS: interface name (i.e. eth0)
+# RETURNS: (ip address)
+# DESCRIPTION: Uses ioctl to get ip address directly from system.
+#===============================================================================
+sub get_ip {
+ my $ifreq= shift;
+ my $result= "";
+ my $SIOCGIFADDR= 0x8915; # man 2 ioctl_list
+ my $proto= getprotobyname('ip');
+
+ socket SOCKET, PF_INET, SOCK_DGRAM, $proto
+ or die "socket: $!";
+
+ if(ioctl SOCKET, $SIOCGIFADDR, $ifreq) {
+ my ($if, $sin) = unpack 'a16 a16', $ifreq;
+ my ($port, $addr) = sockaddr_in $sin;
+ my $ip = inet_ntoa $addr;
+
+ if ($ip && length($ip) > 0) {
+ $result = $ip;
+ }
+ }
+
+ return $result;
+}
#=== FUNCTION ================================================================
# NAME: open_socket
# RETURNS: socket IO::Socket::INET
# DESCRIPTION: open a socket to PeerAddr
#===============================================================================
-sub open_socket {
- my ($PeerAddr, $PeerPort) = @_ ;
- if(defined($PeerPort)){
- $PeerAddr = $PeerAddr.":".$PeerPort;
- }
- my $socket;
- $socket = new IO::Socket::INET(PeerAddr => $PeerAddr ,
- Porto => "tcp" ,
- Type => SOCK_STREAM,
- Timeout => 5,
- );
- if(not defined $socket) {
- return;
- }
- &main::daemon_log("open_socket to: $PeerAddr", 7);
- return $socket;
-}
+#sub open_socket {
+# my ($PeerAddr, $PeerPort) = @_ ;
+# if(defined($PeerPort)){
+# $PeerAddr = $PeerAddr.":".$PeerPort;
+# }
+# my $socket;
+# $socket = new IO::Socket::INET(PeerAddr => $PeerAddr ,
+# Porto => "tcp" ,
+# Type => SOCK_STREAM,
+# Timeout => 5,
+# );
+# if(not defined $socket) {
+# return;
+# }
+# &main::daemon_log("open_socket to: $PeerAddr", 7);
+# return $socket;
+#}
#=== FUNCTION ================================================================
# NAME: register_at_bus
hostkey=>$bus_passwd,
timestamp=>&get_time,
} );
-# if ($res == 3) {
-# my $update_hash = { table=>'known_server' };
-# $update_hash->{where} = [ { hostname=>[$bus_address] } ];
-# $update_hash->{update} = [ {
-# hostkey=>[$bus_passwd],
-# timestamp=>[&get_time],
-# } ];
-# $res = $main::known_server_db->update_dbentry( $update_hash );
-# }
-
my $msg_hash = &create_xml_hash("here_i_am", $server_address, $bus_address);
my $answer = "";
$answer = &send_msg_hash2address($msg_hash, $bus_address, $bus_passwd);
&main::daemon_log("function 'process_incoming_msg': got no msg", 7);
}
- &main::daemon_log("ServerPackages: incoming msg: \n$crypted_msg", 7);
+ &main::daemon_log("ServerPackages: incoming msg: \n$crypted_msg", 8);
$crypted_msg =~ /^([\s\S]*?)\.(\d{1,3}?)\.(\d{1,3}?)\.(\d{1,3}?)\.(\d{1,3}?)$/;
$crypted_msg = $1;
- my $host = sprintf("%s.%s.%s.%s", $2, $3, $4, $5);
+ my $host="0.0.0.0";
+ if($1 && $2 && $3 && $4) {
+ $host = sprintf("%s.%s.%s.%s", $2, $3, $4, $5);
+ }
my $msg;
my $msg_hash;
&main::daemon_log("ServerPackage: host_key: $host_key", 7);
eval{
my $key_cipher = &create_ciphering($host_key);
- $msg = &decrypt_msg($crypted_msg, $key_cipher);
+ $msg = &decrypt_msg($crypted_msg, $key_cipher);
$msg_hash = &transform_msg2hash($msg);
};
if($@) {
if( not defined $msg ) {
&main::daemon_log("WARNING: ServerPackage do not understand the message:", 5);
- &main::daemon_log("$@", 7);
+ &main::daemon_log("$@", 8);
return;
}
my $header = @{$msg_hash->{header}}[0];
my $source = @{$msg_hash->{source}}[0];
- &main::daemon_log("recieve '$header' at ServerPackages from $host", 1);
+ &main::daemon_log("receive '$header' at ServerPackages from $host", 1);
&main::daemon_log("ServerPackages: msg to process: \n$msg", 5);
my @targets = @{$msg_hash->{target}};
my $target = $targets[0];
&main::daemon_log("SeverPackages: msg is for: $target", 7);
- if ($target eq $server_address) {
- # msg is for server
- if ($header eq 'new_passwd'){ &new_passwd($msg_hash)}
- elsif ($header eq 'here_i_am') { &here_i_am($msg_hash)}
- elsif ($header eq 'who_has') { &who_has($msg_hash) }
- elsif ($header eq 'who_has_i_do') { &who_has_i_do($msg_hash)}
- elsif ($header eq 'update_status') { &update_status($msg_hash) }
- elsif ($header eq 'got_ping') { &got_ping($msg_hash)}
- elsif ($header eq 'get_load') { &execute_actions($msg_hash)}
- else { &main::daemon_log("ERROR: ServerPackages: no function assigned to this msg", 5) }
-
- } elsif ($target eq "*") {
- # msg is for all clients
- my $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients'} );
- while( my ($hit_num, $hit) = each %{ $query_res } ) {
- $host_name = $hit->{hostname};
- $host_key = $hit->{hostkey};
- $msg_hash->{target} = [$host_name];
- &send_msg_hash2address($msg_hash, $host_name, $host_key);
- }
- return;
-
- } else {
- # msg is for one host
- my $query_res;
- $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients', hostname=>$target} );
- if( 1 == keys %{$query_res} ) {
- $host_key = $query_res->{1}->{host_key};
- &send_msg_hash2address($msg_hash, $target, $host_key);
- return;
- }
+ # msg is for server
+ if ($header eq 'new_passwd'){ &new_passwd($msg_hash)}
+ elsif ($header eq 'here_i_am') { &here_i_am($msg_hash)}
+ elsif ($header eq 'who_has') { &who_has($msg_hash) }
+ elsif ($header eq 'who_has_i_do') { &who_has_i_do($msg_hash)}
+ elsif ($header eq 'update_status') { &update_status($msg_hash) }
+ elsif ($header eq 'got_ping') { &got_ping($msg_hash)}
+ elsif ($header eq 'get_load') { &execute_actions($msg_hash)}
+ else {
+ if ($target eq "*") {
+ # msg is for all clients
+ my $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients'} );
+ while( my ($hit_num, $hit) = each %{ $query_res } ) {
+ $host_name = $hit->{hostname};
+ $host_key = $hit->{hostkey};
+ $msg_hash->{target} = [$host_name];
+ &send_msg_hash2address($msg_hash, $host_name, $host_key);
+ }
- $query_res = $main::known_server_db->select_dbentry( {table=>'known_server', hostname=>$target} );
- if( 1 == keys %{$query_res} ) {
- $host_key = $query_res->{1}->{host_key};
- &send_msg_hash2address($msg_hash, $target, $host_key);
- return;
+ } else {
+ # msg is for one host
+ my $host_key;
+
+
+ if( not defined $host_key ) {
+ my $query_res = $main::known_clients_db->select_dbentry( {table=>'known_clients', hostname=>$target} );
+ if( 1 == keys %{$query_res} ) {
+ $host_key = $query_res->{1}->{host_key};
+ }
+ }
+
+ if( not defined $host_key ) {
+ my $query_res = $main::known_server_db->select_dbentry( {table=>'known_server', hostname=>$target} );
+ if( 1 == keys %{$query_res} ) {
+ $host_key = $query_res->{1}->{host_key};
+ }
+ }
+
+ if( not defined $host_key ) {
+ &main::daemon_log("ERROR: ServerPackages: target '".$target.
+ "' is not known neither in known_clients nor in known_server",1);
+ } else {
+ &send_msg_hash2address($msg_hash, $target, $host_key);
+ }
}
-
- &main::daemon_log("ERROR: ServerPackages: target '$target' is not known neither in known_clients nor in known_server",1);
- return;
}
} elsif ($len_targets > 1 ) {
# we have more than one target
- return;
+ # TODO to be implemented
}
return ;
my $out_hash;
# number of known clients
- my $nu_clients = keys %{$main::known_clients_db->select_dbentry( {table=>'known_clients'} )};
+ my $nu_clients = keys %{ $main::known_clients_db->select_dbentry( {table=>'known_clients'} ) };
# check wether client address or mac address is already known
if (exists $main::known_clients->{$source}) {