|
@@ -4,15 +4,26 @@ use Mozilla::LDAP::Utils qw(normalizeDN);
|
|
|
use Mozilla::LDAP::API qw(:constant ldap_url_parse ldap_explode_dn);
|
|
use Mozilla::LDAP::API qw(:constant ldap_url_parse ldap_explode_dn);
|
|
|
use DSUtil qw(debug);
|
|
use DSUtil qw(debug);
|
|
|
use Config;
|
|
use Config;
|
|
|
|
|
+use bigint;
|
|
|
|
|
|
|
|
# # Determine the endianness of your system
|
|
# # Determine the endianness of your system
|
|
|
-my $packfmt32 = "QA6SCx3"; # must be 20 bytes
|
|
|
|
|
-my $packfmt64 = "QA6SCx7"; # must be 24 bytes
|
|
|
|
|
|
|
+my $packfmt32 = "VVA6vCx3"; # must be 20 bytes
|
|
|
|
|
+my $packfmt64 = "VVA6vCx7"; # must be 24 bytes
|
|
|
|
|
|
|
|
my $is_big_endian = unpack('xc', pack('s', 1));
|
|
my $is_big_endian = unpack('xc', pack('s', 1));
|
|
|
# see if we are on an LP64 system
|
|
# see if we are on an LP64 system
|
|
|
my $is64 = ($Config{longsize} == 8);
|
|
my $is64 = ($Config{longsize} == 8);
|
|
|
|
|
|
|
|
|
|
+sub convert_to_32bit {
|
|
|
|
|
+ my $val64 = shift;
|
|
|
|
|
+ return ($val64 >> 32, $val64 & 0xffffffff);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+sub convert_from_32bit {
|
|
|
|
|
+ my ($hi, $lo) = @_;
|
|
|
|
|
+ return ($hi << 32) + $lo;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
sub convert_uniqueid {
|
|
sub convert_uniqueid {
|
|
|
my $ent = shift;
|
|
my $ent = shift;
|
|
|
my $val = shift;
|
|
my $val = shift;
|
|
@@ -24,20 +35,28 @@ sub convert_uniqueid {
|
|
|
my $hex = unpack('H*', $val);
|
|
my $hex = unpack('H*', $val);
|
|
|
#print "hex=$hex\n";
|
|
#print "hex=$hex\n";
|
|
|
|
|
|
|
|
- my $fmt32 = "QA6SC";
|
|
|
|
|
- my $fmt64 = "QA6SC";
|
|
|
|
|
|
|
+ my $fmt32 = "VVA6vC";
|
|
|
|
|
+ my $bigfmt32 = "NNA6nC";
|
|
|
|
|
+ my $fmt64 = "VVA6vC";
|
|
|
|
|
+ my $bigfmt64 = "NNA6nC";
|
|
|
my $fmt = $fmt32;
|
|
my $fmt = $fmt32;
|
|
|
|
|
+ my $bigfmt = $bigfmt32;
|
|
|
if (length($val) > 20) {
|
|
if (length($val) > 20) {
|
|
|
$fmt = $fmt64;
|
|
$fmt = $fmt64;
|
|
|
|
|
+ $bigfmt = $bigfmt64;
|
|
|
} elsif ($is64) {
|
|
} elsif ($is64) {
|
|
|
# cannot convert 32-bit to 64-bit - just delete the entry and continue
|
|
# cannot convert 32-bit to 64-bit - just delete the entry and continue
|
|
|
debug(1, "Cannot convert 32-bit nsState value $hex to 64-bit - deleting entry " .
|
|
debug(1, "Cannot convert 32-bit nsState value $hex to 64-bit - deleting entry " .
|
|
|
$ent->getDN() . " and continuing\n");
|
|
$ent->getDN() . " and continuing\n");
|
|
|
return (-1, 0);
|
|
return (-1, 0);
|
|
|
|
|
+ } else { # 32-bit to 32-bit - just leave it alone
|
|
|
|
|
+ debug(1, "Skipping 32-bit nsState value $hex in entry " .
|
|
|
|
|
+ $ent->getDN() . " and continuing\n");
|
|
|
|
|
+ return (0, 0);
|
|
|
}
|
|
}
|
|
|
if ($is_big_endian) {
|
|
if ($is_big_endian) {
|
|
|
- $packfmt32 = "(QA6SCx3)>";
|
|
|
|
|
- $packfmt64 = "(QA6SCx7)>";
|
|
|
|
|
|
|
+ $packfmt32 = "NNA6nCx3";
|
|
|
|
|
+ $packfmt64 = "NNA6nCx7";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
my $packfmt = $packfmt32;
|
|
my $packfmt = $packfmt32;
|
|
@@ -45,16 +64,16 @@ sub convert_uniqueid {
|
|
|
$packfmt = $packfmt64;
|
|
$packfmt = $packfmt64;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- my ($ts, $node, $clockseq, $last_update) = unpack($fmt, $val);
|
|
|
|
|
- # if we think it is from bigendian, do
|
|
|
|
|
- # $bigfmt = "(" . $fmt . ")>";
|
|
|
|
|
|
|
+ my ($tslow, $tshigh, $node, $clockseq, $last_update) = unpack($fmt, $val);
|
|
|
|
|
+ my $ts = convert_from_32bit($tshigh, $tslow);
|
|
|
my $tssecs = ($ts - 0x01B21DD213814000) / 10000000;
|
|
my $tssecs = ($ts - 0x01B21DD213814000) / 10000000;
|
|
|
my $curts = time;
|
|
my $curts = time;
|
|
|
my $tsdiff = abs($curts - $tssecs);
|
|
my $tsdiff = abs($curts - $tssecs);
|
|
|
my $maxdiff = 86400*365*10; # 10 years
|
|
my $maxdiff = 86400*365*10; # 10 years
|
|
|
if (($tsdiff > $maxdiff) || (($last_update != 0) && ($last_update != 1))) {
|
|
if (($tsdiff > $maxdiff) || (($last_update != 0) && ($last_update != 1))) {
|
|
|
# try big endian
|
|
# try big endian
|
|
|
- ($ts, $node, $clockseq, $last_update) = unpack("($fmt)>", $val);
|
|
|
|
|
|
|
+ ($tslow, $tshigh, $node, $clockseq, $last_update) = unpack($bigfmt, $val);
|
|
|
|
|
+ $ts = convert_from_32bit($tshigh, $tslow);
|
|
|
$tssecs = ($ts - 0x01B21DD213814000) / 10000000;
|
|
$tssecs = ($ts - 0x01B21DD213814000) / 10000000;
|
|
|
$tsdiff = abs($curts - $tssecs);
|
|
$tsdiff = abs($curts - $tssecs);
|
|
|
if (($tsdiff > $maxdiff) || (($last_update != 0) && ($last_update != 1))) {
|
|
if (($tsdiff > $maxdiff) || (($last_update != 0) && ($last_update != 1))) {
|
|
@@ -64,9 +83,10 @@ sub convert_uniqueid {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# format for the target system
|
|
# format for the target system
|
|
|
- my $newval = pack($packfmt, $ts, $node, $clockseq, $last_update);
|
|
|
|
|
|
|
+ ($tshigh, $tslow) = convert_to_32bit($ts);
|
|
|
|
|
+ my $newval = pack($packfmt, $tslow, $tshigh, $node, $clockseq, $last_update);
|
|
|
my $rc = 0;
|
|
my $rc = 0;
|
|
|
- if ($val != $newval) { # changed
|
|
|
|
|
|
|
+ if ($val ne $newval) { # changed
|
|
|
my $hex2 = unpack('H*', $newval);
|
|
my $hex2 = unpack('H*', $newval);
|
|
|
debug(1, "Converted old nsState val in ", $ent->getDN(), " from $hex to $hex2\n");
|
|
debug(1, "Converted old nsState val in ", $ent->getDN(), " from $hex to $hex2\n");
|
|
|
$rc = 1; # changed
|
|
$rc = 1; # changed
|
|
@@ -85,22 +105,40 @@ sub convert_replica {
|
|
|
my $len = length($val);
|
|
my $len = length($val);
|
|
|
my $pad;
|
|
my $pad;
|
|
|
my $timefmt;
|
|
my $timefmt;
|
|
|
|
|
+ my ($rid, $sampled_time, $local_offset, $remote_offset, $seq_num);
|
|
|
|
|
+ my ($st_high, $st_low, $lo_high, $lo_low, $ro_high, $ro_low);
|
|
|
|
|
+ my $fmtstr;
|
|
|
|
|
+ my $bigfmtstr;
|
|
|
if ($len <= 20) {
|
|
if ($len <= 20) {
|
|
|
$pad = 2; # padding for short H values
|
|
$pad = 2; # padding for short H values
|
|
|
- $timefmt = 'I'; # timevals are unsigned 32-bit int
|
|
|
|
|
|
|
+ $timefmt = 'V'; # timevals are unsigned 32-bit int - try little-endian 'V' first
|
|
|
|
|
+ $fmtstr = "vx" . $pad . $timefmt . "3vx" . $pad;
|
|
|
|
|
+ $bigfmtstr = 'nx' . $pad . 'N' . '3nx' . $pad;
|
|
|
|
|
+ ($rid, $sampled_time, $local_offset, $remote_offset, $seq_num) = unpack($fmtstr, $val);
|
|
|
} else {
|
|
} else {
|
|
|
$pad = 6; # padding for short H values
|
|
$pad = 6; # padding for short H values
|
|
|
- $timefmt = 'Q'; # timevals are unsigned 64-bit int
|
|
|
|
|
|
|
+ $timefmt = 'V'; # timevals are unsigned 64-bit int
|
|
|
|
|
+ $fmtstr = "vx" . $pad . $timefmt . "6vx" . $pad;
|
|
|
|
|
+ $bigfmtstr = 'nx' . $pad . 'N' . '6nx' . $pad;
|
|
|
|
|
+ ($rid, $st_low, $st_high, $lo_low, $lo_high, $rt_low, $rt_high, $seq_num) = unpack($fmtstr, $val);
|
|
|
|
|
+ $sampled_time = convert_from_32bit($st_high, $st_low);
|
|
|
|
|
+ $local_offset = convert_from_32bit($lo_high, $lo_low);
|
|
|
|
|
+ $remote_offset = convert_from_32bit($ro_high, $ro_low);
|
|
|
}
|
|
}
|
|
|
# short - padbytes - 3 timevals - short - padbytes
|
|
# short - padbytes - 3 timevals - short - padbytes
|
|
|
- my $fmtstr = "Sx" . $pad . $timefmt . "3Sx" . $pad;
|
|
|
|
|
- my ($rid, $sampled_time, $local_offset, $remote_offset, $seq_num) = unpack($fmtstr, $val);
|
|
|
|
|
my $hex = unpack('H*', $val);
|
|
my $hex = unpack('H*', $val);
|
|
|
my $now = time;
|
|
my $now = time;
|
|
|
my $tdiff = abs($now - $sampled_time);
|
|
my $tdiff = abs($now - $sampled_time);
|
|
|
my $maxdiff = 86400*365*10; # 10 years
|
|
my $maxdiff = 86400*365*10; # 10 years
|
|
|
if ($tdiff > $maxdiff) { # try big endian
|
|
if ($tdiff > $maxdiff) { # try big endian
|
|
|
- ($rid, $sampled_time, $local_offset, $remote_offset, $seq_num) = unpack("($fmtstr)>", $val);
|
|
|
|
|
|
|
+ if ($len <= 20) {
|
|
|
|
|
+ ($rid, $sampled_time, $local_offset, $remote_offset, $seq_num) = unpack($bigfmtstr, $val);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ($rid, $st_low, $st_high, $lo_low, $lo_high, $rt_low, $rt_high, $seq_num) = unpack($bigfmtstr, $val);
|
|
|
|
|
+ $sampled_time = convert_from_32bit($st_high, $st_low);
|
|
|
|
|
+ $local_offset = convert_from_32bit($lo_high, $lo_low);
|
|
|
|
|
+ $remote_offset = convert_from_32bit($ro_high, $ro_low);
|
|
|
|
|
+ }
|
|
|
my $tdiff = abs($now - $sampled_time);
|
|
my $tdiff = abs($now - $sampled_time);
|
|
|
if ($tdiff > $maxdiff) { # error
|
|
if ($tdiff > $maxdiff) { # error
|
|
|
debug(0, "Error: could not parse nsstate $hex - tdiff is $tdiff seconds or", ($tdiff/86400), " days\n");
|
|
debug(0, "Error: could not parse nsstate $hex - tdiff is $tdiff seconds or", ($tdiff/86400), " days\n");
|
|
@@ -108,12 +146,28 @@ sub convert_replica {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
# format for the target system
|
|
# format for the target system
|
|
|
- if ($is_big_endian) {
|
|
|
|
|
- $fmtstr = "($fmtstr)>";
|
|
|
|
|
|
|
+ my $packfmt;
|
|
|
|
|
+ my @packargs;
|
|
|
|
|
+ if ($is64) {
|
|
|
|
|
+ my $packfmt = "vx" . $pad . "V6vx" . $pad;
|
|
|
|
|
+ if ($is_big_endian) {
|
|
|
|
|
+ $packfmt = "nx" . $pad . "N6nx" . $pad;
|
|
|
|
|
+ }
|
|
|
|
|
+ $st_high = $st >> 32;
|
|
|
|
|
+ ($st_high, $st_low) = convert_to_32bit($sampled_time);
|
|
|
|
|
+ ($lo_high, $lo_low) = convert_to_32bit($local_offset);
|
|
|
|
|
+ ($ro_high, $ro_low) = convert_to_32bit($remote_offset);
|
|
|
|
|
+ @packargs = ($rid, $st_low, $st_high, $lo_low, $lo_high, $ro_low, $ro_high, $seq_num);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ my $packfmt = "vx" . $pad . "V3vx" . $pad;
|
|
|
|
|
+ if ($is_big_endian) {
|
|
|
|
|
+ $packfmt = "nx" . $pad . "N3nx" . $pad;
|
|
|
|
|
+ }
|
|
|
|
|
+ @packargs = ($rid, $sampled_time, $local_offset, $remote_offset, $seq_num);
|
|
|
}
|
|
}
|
|
|
- my $newval = pack($fmtstr, $rid, $sampled_time, $local_offset, $remote_offset, $seq_num);
|
|
|
|
|
|
|
+ my $newval = pack($fmtstr, @packargs);
|
|
|
my $rc = 0;
|
|
my $rc = 0;
|
|
|
- if ($val != $newval) { # changed
|
|
|
|
|
|
|
+ if ($val ne $newval) { # changed
|
|
|
my $hex2 = unpack('H*', $newval);
|
|
my $hex2 = unpack('H*', $newval);
|
|
|
debug(1, "Converted old nsState val in ", $ent->getDN(), " from $hex to $hex2\n");
|
|
debug(1, "Converted old nsState val in ", $ent->getDN(), " from $hex to $hex2\n");
|
|
|
$rc = 1; # changed
|
|
$rc = 1; # changed
|
|
@@ -164,7 +218,11 @@ sub runinst {
|
|
|
sub testit {
|
|
sub testit {
|
|
|
#my $val = 'ACm2BdIdsgH+tw/8AAB+swEAAAA=';
|
|
#my $val = 'ACm2BdIdsgH+tw/8AAB+swEAAAA=';
|
|
|
#my $val = 'AOj+tyuA4AHsNZ7S9NnxZwEAAAAAAAAA';
|
|
#my $val = 'AOj+tyuA4AHsNZ7S9NnxZwEAAAAAAAAA';
|
|
|
-my $testval = "00a43cb4d11db2018b7912fd0000a42e01000000";
|
|
|
|
|
|
|
+#my $val = 'ABI3gdIdsgH3TJWpAACGIgEAAAA=';
|
|
|
|
|
+#my $testval = "00a43cb4d11db2018b7912fd0000a42e01000000";
|
|
|
|
|
+#my $testval = "0029B605D21DB201FEB70FFC00007EB301000000";
|
|
|
|
|
+#my $testval = "00E8FEB72B80E001EC359ED2F4D9F1670100000000000000";
|
|
|
|
|
+my $testval = "00123781D21DB201F74C95A90000862201000000";
|
|
|
my $testdecval = $testval;
|
|
my $testdecval = $testval;
|
|
|
# base16 decode
|
|
# base16 decode
|
|
|
$testdecval =~ s/(..)/chr(hex($1))/eg;
|
|
$testdecval =~ s/(..)/chr(hex($1))/eg;
|