Add IPv4 support.

After adding IPv4 support, noted that IMM and AMM behaved far less nicely,
restore the service-request prelude to attribute request as a result

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@11900 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
jbjohnso 2012-03-19 21:06:17 +00:00
parent 05e6a27704
commit 22d2645e28

View File

@ -14,6 +14,7 @@ unless ($ip6support) {
#TODO: somehow get at system headers to get the value, put in linux's for now
use constant IPV6_MULTICAST_IF => 17;
use constant IP_MULTICAST_IF => 32;
my %xid_to_srvtype_map;
my $xid;
@ -50,7 +51,7 @@ sub dodiscover {
}
my $interfaces = get_interfaces(%args);
foreach my $srvtype (@srvtypes) {
send_attribute_request_single(%args,ifacemap=>$interfaces,SrvType=>$srvtype);
send_service_request_single(%args,ifacemap=>$interfaces,SrvType=>$srvtype);
}
unless ($args{NoWait}) { #in nowait, caller owns the responsibility..
#by default, report all respondants within 3 seconds:
@ -69,10 +70,17 @@ sub dodiscover {
}
my $result = process_slp_packet(packet=>$slppacket,sockaddr=>$peer,'socket'=>$args{'socket'});
if ($result) {
if ($peername =~ /\./) { #ipv4
$peername =~ s/::ffff://;
}
$result->{peername} = $peername;
$result->{scopeid} = $scope;
$result->{sockaddr} = $peer;
$rethash{$peername.'%'.$scope} = $result;
my $hashkey;
if ($peername =~ /fe80/) {
$peername .= '%'.$scope;
}
$rethash{$peername} = $result;
if ($args{Callback}) {
$args{Callback}->($result);
}
@ -89,15 +97,17 @@ sub process_slp_packet {
my $socket = $args{'socket'};
my $packet = $args{packet};
my $parsedpacket = removeslpheader($packet);
# if ($parsedpacket->{FunctionId} == 2) {#Service Reply
# $parsedpacket->{service_urls} = parse_service_reply($parsedpacket->{payload});
# unless (scalar @{$parsedpacket->{service_urls}}) { return undef; }
# send_attribute_request('socket'=>$socket,url=>$parsedpacket->{service_urls}->[0],sockaddr=>$sockaddy);
# return undef;
# } elsif ($parsedpacket->{FunctionId} == 7) { #attribute reply
if ($parsedpacket->{FunctionId} == 7) { #attribute reply
$parsedpacket->{attributes} = parse_attribute_reply($parsedpacket->{payload});
if ($parsedpacket->{FunctionId} == 2) {#Service Reply
$parsedpacket->{service_urls} = parse_service_reply($parsedpacket->{payload});
unless (scalar @{$parsedpacket->{service_urls}}) { return undef; }
#send_attribute_request('socket'=>$socket,url=>$parsedpacket->{service_urls}->[0],sockaddr=>$sockaddy);
my $srvtype = $xid_to_srvtype_map{$parsedpacket->{Xid}};
my $packet = generate_attribute_request(%args,SrvType=>$srvtype);
$socket->send($packet,0,$sockaddy);
return undef;
} elsif ($parsedpacket->{FunctionId} == 7) { #attribute reply
$parsedpacket->{SrvType} = $xid_to_srvtype_map{$parsedpacket->{Xid}};
$parsedpacket->{attributes} = parse_attribute_reply($parsedpacket->{payload});
delete $parsedpacket->{payload};
return $parsedpacket;
} else {
@ -109,7 +119,7 @@ sub parse_attribute_reply {
my $contents = shift;
my @payload = unpack("C*",$contents);
if ($payload[0] != 0 or $payload[1] != 0) {
return [];
return {};
}
my $attrlength = ($payload[2]<<8)+$payload[3];
splice(@payload,0,4);
@ -164,36 +174,36 @@ sub generate_attribute_request {
}
#sub parse_service_reply {
# my $packet = shift;
# my @reply = unpack("C*",$packet);
# if ($reply[0] != 0 or $reply[1] != 0) {
# return ();
# }
# my @urls;
# my $numurls = ($reply[2]<<8)+$reply[3];
# splice (@reply,0,4);
# while ($numurls--) {
# push @urls,extract_next_url(\@reply);
# }
# return \@urls;
#}
sub parse_service_reply {
my $packet = shift;
my @reply = unpack("C*",$packet);
if ($reply[0] != 0 or $reply[1] != 0) {
return ();
}
my @urls;
my $numurls = ($reply[2]<<8)+$reply[3];
splice (@reply,0,4);
while ($numurls--) {
push @urls,extract_next_url(\@reply);
}
return \@urls;
}
#sub extract_next_url { #section 4.3 url entries
# my $payload = shift;
# splice (@$payload,0,3); # discard reserved and lifetime which we will not bother using
# my $urllength = ((shift @$payload)<<8)+(shift @$payload);
# my @url = splice(@$payload,0,$urllength);
# my $authblocks = shift @$payload;
# unless ($authblocks == 0) {
# $payload = []; #TODO: skip/use auth blocks if needed to get at more URLs
# }
# return pack("C*",@url);
#}
sub extract_next_url { #section 4.3 url entries
my $payload = shift;
splice (@$payload,0,3); # discard reserved and lifetime which we will not bother using
my $urllength = ((shift @$payload)<<8)+(shift @$payload);
my @url = splice(@$payload,0,$urllength);
my $authblocks = shift @$payload;
unless ($authblocks == 0) {
$payload = []; #TODO: skip/use auth blocks if needed to get at more URLs
}
return pack("C*",@url);
}
sub send_attribute_request_single {
sub send_service_request_single {
my %args = @_;
my $packet = generate_attribute_request(%args);
my $packet = generate_service_request(%args);
my $interfaces = $args{ifacemap}; #get_interfaces(%args);
my $socket = $args{'socket'};
my $v6addr;
@ -204,14 +214,19 @@ sub send_attribute_request_single {
($fam, $type, $proto, $v6addr, $name) =
Socket6::getaddrinfo($target,"svrloc",Socket6::AF_INET6(),SOCK_DGRAM,0);
}
my $ipv4mcastaddr = inet_aton("239.255.255.253"); #per rfc 2608
my $ipv4sockaddr = sockaddr_in(427,$ipv4mcastaddr);
foreach my $iface (keys %{$interfaces}) {
if ($ip6support) {
setsockopt($socket,Socket6::IPPROTO_IPV6(),IPV6_MULTICAST_IF,pack("I",$interfaces->{$iface}->{scopeidx}));
$socket->send($packet,0,$v6addr);
}
#setsockopt($socket,IPPROTO_IP,IP_MULTICAST_IF,
#TODO: IPv4 support
# setsockopt($socket,IPPROTO_IP,IP_MULTICAST_IF,
foreach my $ip (@{$interfaces->{$iface}->{ipv4addrs}}) {
$ip =~ s/\/.*//;
my $ipn = inet_aton($ip); #we are ipv4 only, this is ok
setsockopt($socket,0,IP_MULTICAST_IF,pack("NNI",$ipv4mcastaddr,$ipn,$interfaces->{$iface}->{scopeidx}));
$socket->send($packet,0,$ipv4sockaddr);
}
}
}
@ -255,24 +270,25 @@ sub get_interfaces {
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | length of <SLP SPI> string | <SLP SPI> String \
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#sub gendiscover {
# my %args = @_;
# my $srvtype = $args{SrvType};
# my $scope = "DEFAULT";
# if ($args{Scopes}) { $scope = $args{Scopes}; }
# my $packet = pack("C*",0,0); #start with PRList, we have no prlist so zero
# #TODO: actually accumulate PRList, particularly between IPv4 and IPv6 runs
# my $length = length($srvtype);
# $packet .= pack("C*",($length>>8),($length&0xff));
# $packet .= $srvtype;
# $length = length($scope);
# $packet .= pack("C*",($length>>8),($length&0xff));
# $packet .= $scope;
sub generate_service_request {
my %args = @_;
my $srvtype = $args{SrvType};
my $scope = "DEFAULT";
if ($args{Scopes}) { $scope = $args{Scopes}; }
my $packet = pack("C*",0,0); #start with PRList, we have no prlist so zero
#TODO: actually accumulate PRList, particularly between IPv4 and IPv6 runs
my $length = length($srvtype);
$packet .= pack("C*",($length>>8),($length&0xff));
$packet .= $srvtype;
$length = length($scope);
$packet .= pack("C*",($length>>8),($length&0xff));
$packet .= $scope;
#no ldap predicates, and no auth, so zeroes..
# $packet .= pack("C*",0,0,0,0);
# my $header = genslpheader($packet,Multicast=>1,FunctionId=>1);
# return $packet = $header.$packet;
#}
$packet .= pack("C*",0,0,0,0);
my $header = genslpheader($packet,Multicast=>1,FunctionId=>1);
$xid_to_srvtype_map{$xid++}=$srvtype;
return $packet = $header.$packet;
}
# SLP header from RFC 2608
# 0 1 2 3
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -320,7 +336,7 @@ unless (caller) {
#results on-the-fly
require Data::Dumper;
Data::Dumper->import();
my $srvtypes = ["service:management-hardware.IBM:chassis-management-module","service:management-hardware.IBM:integrated-management-module2"];
my $srvtypes = ["service:management-hardware.IBM:chassis-management-module","service:management-hardware.IBM:integrated-management-module2","service:management-hardware.IBM:management-module"];
xCAT::SLP::dodiscover(SrvTypes=>$srvtypes,Callback=>sub { print Dumper(@_) });
#example 2: simple invocation of a single service type
$srvtypes = "service:management-hardware.IBM:chassis-management-module";