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:
parent
05e6a27704
commit
22d2645e28
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user