1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-09 06:01:28 +00:00
Files
nmap/scripts/fingerfix.pl

799 lines
19 KiB
Perl
Executable File

#!/usr/bin/perl
sub max($$) {
my ($a, $b) = @_;
if ($a >= $b) { return $a;}
return $b;
}
sub min($$) {
my ($a, $b) = @_;
if ($a <= $b) { return $a;}
return $b;
}
sub fpunwrap($) {
my $fp = shift();
$fp =~ s/^\s*OS://mg;
$fp =~ s/\n//g;
$fp =~ s/\s+$//g;
$fp =~ s/\)/\)\n/g;
return $fp;
}
# first read in the fingerprint
my $printbuf = "";
my $wrapped = 0;
while(<>) {
chomp;
$line = $_;
if (($line eq "." || $line eq "")) {
if ($printbuf) { last; }
} else { $printbuf .= "$line\n"; }
if ($line =~ /^\s*OS:/) { $wrapped = 1; }
}
if ($wrapped) {
$printbuf = fpunwrap($printbuf);
print "UNWRAPPED FINGERPRINT:\n$printbuf\n";
}
# At this point I have an unwrapped FP in $printbuf
foreach $line (split /\n/, $printbuf) {
chomp($line);
# Itemize the lines we know how to deal with
if (!$line =~ /(Fingerprint\s+\S)|(Class\s+\S)|(^SEQ)|(^OPS)|(^WIN)|(^ECN)|(^T[1-7])|(^U1)|(^IE)|(^Contributed by)/i) { next; }
# If this is coming from the submission form, there may already be a Contributor attached
if ($line =~ /Contributed by (.*)/) {
if (!$fp{contrib}) {
$fp{contrib} = $1;
} else { $fp{contrib} .= ", $1"; }
}
# We also get a Fingerprint line describing what this system (supposedly) is if it is coming from
# the submission CGI.
elsif ($line =~ /Fingerprint\s+(.*)/i) {
$fp{os} = $1;
}
# If the submitter gave a classification, we have a Class line
elsif ($line =~ /Class\s+(.*)/i) {
if (!$fp{class} or !($fp{class} =~ /\Q$line\E/)) {
$fp{class} .= $line . "\n";
}
}
# OK, time for the first real fingerprint line! The SEQ line
elsif ($line =~ /SEQ\(SP=([^%]+)%GCD=([^%\)]+)%ISR=([^%\)]+)(%TI=([^%\)]+))?(%II=([^%\)]+))?(%SS=([^%\)]+))?(%TS=([^%\)]+))?\)/) {
# SEQ
$sp = $1;
$gcd = hex($2);
$isr = $3;
$ti = $5;
$ii = $7;
$ss = $9;
$ts = $11;
if ($fp{seq}{gcd} =~ /<([0-9A-F]+)/) {
$oldgcd = hex($1);
} else { $oldgcd = 3; }
$newgcd = max($oldgcd, $gcd * 2 + 3);
$fp{seq}{gcd} = sprintf ("<%X", $newgcd);
$newhighlim = $newlowlim = -1;
if ($sp =~ /([0-9A-F]+)-([0-9A-F]+)/) {
$newlowlim = hex($1);
$newhighlim = hex($2);
} elsif ($sp =~ /<([0-9A-F]+)/) {
$newhighlim = hex($1);
}
# print "newhighlim: $newhighlim newlowlim: $newlowlim\n";
$oldhighlim = $oldlowlim = 0;
if ($fp{seq}{sp} =~ /([0-9A-F]+)-([0-9A-F]+)/) {
$oldlowlim = hex($1);
$oldhighlim = hex($2);
} elsif ($fp{seq}{sp} =~ /<([0-9A-F]+)/) {
$oldhighlim = hex($1);
} elsif ($fp{seq}{sp} =~ /^([0-9A-F]+)/) {
$oldhighlim = $oldlowlim = hex($1);
}
# print "oldhighlim: $oldhighlim oldlowlim: $oldlowlim\n";
if ($oldlowlim) {
if ($newlowlim != -1) { $newlowlim = max(0, min($oldlowlim, $newlowlim)); }
else { $newlowlim = max(0, min($oldlowlim, hex($sp))); }
} else {
if ($newlowlim == -1) { $newlowlim = max(0, hex($sp)); }
}
if ($newhighlim == -1) {
$newhighlim = max($oldhighlim, hex($sp));
} else {
$newhighlim = max($oldhighlim, $newhighlim);
}
# print "oldhighlim: $oldhighlim oldlowlim: $oldlowlim newhighlim: $newhighlim newlowlim: $newlowlim oldsp: $fp{seq}{sp}";
if ($newlowlim eq $newhighlim) {
$fp{seq}{sp} = sprintf("%X", $newhighlim);
} elsif ($newlowlim > 0) {
$fp{seq}{sp} = sprintf("%X-%X", $newlowlim, $newhighlim);
} else {
$fp{seq}{sp} = sprintf("<%X", $newhighlim);
}
# print " newsp: $fp{seq}{sp}\n";
# Treat ISR the same way as sp
$newhighlim = $newlowlim = -1;
if ($isr =~ /([0-9A-F]+)-([0-9A-F]+)/) {
$newlowlim = hex($1);
$newhighlim = hex($2);
} elsif ($isr =~ /<([0-9A-F]+)/) {
$newhighlim = hex($1);
}
# print "newhighlim: $newhighlim newlowlim: $newlowlim\n";
$oldhighlim = $oldlowlim = 0;
if ($fp{seq}{isr} =~ /([0-9A-F]+)-([0-9A-F]+)/) {
$oldlowlim = hex($1);
$oldhighlim = hex($2);
} elsif ($fp{seq}{isr} =~ /<([0-9A-F]+)/) {
$oldhighlim = hex($1);
} elsif ($fp{seq}{isr} =~ /^([0-9A-F]+)/) {
$oldhighlim = $oldlowlim = hex($1);
}
# print "oldhighlim: $oldhighlim oldlowlim: $oldlowlim\n";
if ($oldlowlim) {
if ($newlowlim != -1) { $newlowlim = max(0, min($oldlowlim, $newlowlim)); }
else { $newlowlim = max(0, min($oldlowlim, hex($isr))); }
} else {
if ($newlowlim == -1) { $newlowlim = max(0, hex($isr)); }
}
if ($newhighlim == -1) {
$newhighlim = max($oldhighlim, hex($isr));
} else {
$newhighlim = max($oldhighlim, $newhighlim);
}
# print "oldhighlim: $oldhighlim oldlowlim: $oldlowlim newhighlim: $newhighlim newlowlim: $newlowlim oldisr: $fp{seq}{isr}";
if ($newlowlim eq $newhighlim) {
$fp{seq}{isr} = sprintf("%X", $newhighlim);
} elsif ($newlowlim > 0) {
$fp{seq}{isr} = sprintf("%X-%X", $newlowlim, $newhighlim);
} else {
$fp{seq}{isr} = sprintf("<%X", $newhighlim);
}
# print " newisr: $fp{seq}{isr}\n";
if (!($fp{seq}{ti} =~ /(^|\|)$ti($|\|)/)) {
if ($fp{seq}{ti}) {
$fp{seq}{ti} = $fp{seq}{ti} . qq^|$ti^;
} else {
$fp{seq}{ti} = $ti;
}
}
if (!($fp{seq}{ii} =~ /(^|\|)$ii($|\|)/)) {
if ($fp{seq}{ii}) {
$fp{seq}{ii} = $fp{seq}{ii} . qq^|$ii^;
} else {
$fp{seq}{ii} = $ii;
}
}
if (!($fp{seq}{ss} =~ /(^|\|)$ss($|\|)/)) {
if ($fp{seq}{ss}) {
$fp{seq}{ss} = $fp{seq}{ss} . qq^|$ss^;
} else {
$fp{seq}{ss} = $ss;
}
}
if (!($fp{seq}{ts} =~ /(^|\|)$ts($|\|)/)) {
if ($fp{seq}{ts}) {
$fp{seq}{ts} = $fp{seq}{ts} . qq^|$ts^;
} else {
$fp{seq}{ts} = $ts;
}
}
} elsif ($line =~ /^OPS/) {
# Time for the second test line -- Ops (Options)
foreach $num (1 .. 6) {
$o = "";
$oi = "o$num";
if ($line =~ /[\(%]O$num=([0-9A-Z|]*)/) {
$o = $1;
if (!$o) { $o = "NULL"; }
}
if (!($fp{ops}{$oi} =~ /(^|\|)$o($|\|)/)) {
if ($fp{ops}{$oi}) {
$fp{ops}{$oi} = $fp{ops}{$oi} . qq^|$o^;
} else {
$fp{ops}{$oi} = $o;
}
}
}
} elsif ($line =~ /^WIN/) {
# WIN - Window values
foreach $num (1 .. 6) {
$w = "";
$wi = "w$num";
if ($line =~ /[\(%]W$num=([0-9A-F|]*)/) {
$w = $1;
if (!$w) { $w = "NULL"; }
}
if (!($fp{win}{$wi} =~ /(^|\|)$w($|\|)/)) {
if ($fp{win}{$wi}) {
$fp{win}{$wi} = $fp{win}{$wi} . qq^|$w^;
} else {
$fp{win}{$wi} = $w;
}
}
}
} elsif ($line =~ /^ECN/) {
# ECN - Explicit Congestion Notification probe response
$resp = $df = $ttl = $win = $ops = $cc = $quirk = "";
if ($line =~ /R=([NY])/) {
$resp = $1;
}
if ($line =~ /[\(%]DF=([NY])/) {
$df = $1;
}
if ($line =~ /[\(%]TG?=([0-9A-F]+)/) {
$ttl = $1;
if (!$ttl) { $ttl = "NULL"; }
}
if ($line =~ /[\(%]W=([0-9A-F|]*)/) {
$win = $1;
if (!$win) { $win = "NULL"; }
}
if ($line =~ /[\(%]O=([0-9A-Z|]*)/) {
$ops = $1;
if (!$ops) { $ops = "NULL"; }
}
if ($line =~ /[\(%]CC=([NY])/) {
$cc = $1;
}
if ($line =~ /[\(%]Q=(R?U?)/) {
$quirk = $1;
if (!$quirk) { $quirk = "NULL"; }
}
if ($resp eq "Y" or !$resp) {
$fp{ecn}{resp} = "Y";
if ($df and !($fp{ecn}{df} =~ /(^|\|)$df($|\|)/)) {
if ($fp{ecn}{df}) {
$fp{ecn}{df} .= qq^|$df^;
} else {
$fp{ecn}{df} = $df;
}
}
if (!($fp{ecn}{ttl} =~ /(^|\|)$ttl($|\|)/)) {
if ($fp{ecn}{ttl}) {
$fp{ecn}{ttl} = $fp{ecn}{ttl} . qq^|$ttl^;
} else {
$fp{ecn}{ttl} = $ttl;
}
}
if (!($fp{ecn}{win} =~ /(^|\|)$win($|\|)/)) {
if ($fp{ecn}{win}) {
$fp{ecn}{win} = $fp{ecn}{win} . qq^|$win^;
} else {
$fp{ecn}{win} = $win;
}
}
if (!($fp{ecn}{ops} =~ /(^|\|)$ops($|\|)/)) {
if ($fp{ecn}{ops}) {
$fp{ecn}{ops} = $fp{ecn}{ops} . qq^|$ops^;
} else {
$fp{ecn}{ops} = $ops;
}
}
if ($cc and !($fp{ecn}{cc} =~ /(^|\|)$cc($|\|)/)) {
if ($fp{ecn}{cc}) {
$fp{ecn}{cc} .= qq^|$cc^;
} else {
$fp{ecn}{cc} = $cc;
}
}
if (!($fp{ecn}{quirk} =~ /(^|\|)$quirk($|\|)/)) {
if ($fp{ecn}{quirk}) {
$fp{ecn}{quirk} .= qq^|$quirk^;
} else {
$fp{ecn}{quirk} = $quirk;
}
}
} elsif ($fp{ecn}{resp} ne "Y") {
$fp{ecn}{resp} = "N";
}
} elsif ($line =~ /^T([1-7])/) {
$num = $1;
$test = "T$num";
$resp = $df = $ttl = $win = $seq = $ack = $flags = $ops = $rd = $quirk = "";
if ($line =~ /R=([NY])/) {
$resp = $1;
}
if ($line =~ /[\(%]DF=([NY])/) {
$df = $1;
}
if ($line =~ /[\(%]TG?=([0-9A-F]+)/) {
$ttl = $1;
if (!$ttl) { $ttl = "NULL"; }
}
if ($num != 1 and $line =~ /[\(%]W=([0-9A-F|]*)/) {
$win = $1;
if (!$win) { $win = "NULL"; }
}
if ($line =~ /[\(%]S=([^%]+)/) {
$seq = $1;
}
if ($line =~ /[\(%]A=([^%]+)/) {
$ack = $1;
}
if ($line =~ /[\(%]F=([^%]*)/) {
$flags = $1;
if (!$flags) { $flags = "NULL"; }
}
if ($num != 1 and $line =~ /[\(%]O=([0-9A-Z|]*)/) {
$ops = $1;
if (!$ops) { $ops = "NULL"; }
}
if ($line =~ /[\(%]RD=([0-9A-F]*)/) {
$rd = $1;
if (!$rd) { $rd = "NULL"; }
}
if ($line =~ /[\(%]Q=(R?U?)/) {
$quirk = $1;
if (!$quirk) { $quirk = "NULL"; }
}
if ($resp eq "Y" or !$resp) {
$fp{$test}{resp} = "Y";
if ($df and !($fp{$test}{df} =~ /(^|\|)$df($|\|)/)) {
if ($fp{$test}{df}) {
$fp{$test}{df} .= qq^|$df^;
} else {
$fp{$test}{df} = $df;
}
}
if (!($fp{$test}{ttl} =~ /(^|\|)$ttl($|\|)/)) {
if ($fp{$test}{ttl}) {
$fp{$test}{ttl} = $fp{$test}{ttl} . qq^|$ttl^;
} else {
$fp{$test}{ttl} = $ttl;
}
}
if ($num != 1 and !($fp{$test}{win} =~ /(^|\|)$win($|\|)/)) {
if ($fp{$test}{win}) {
$fp{$test}{win} = $fp{$test}{win} . qq^|$win^;
} else {
$fp{$test}{win} = $win;
}
}
if ($seq and !($fp{$test}{seq} =~ /(^|\|)$seq($|\|)/)) {
if ($fp{$test}{seq}) {
$fp{$test}{seq} .= qq^|$seq^;
} else {
$fp{$test}{seq} = $seq;
}
}
# Quick hack to stop S+ from repeating endlessly ...
$acktmp = $ack;
$acktmp =~ s/\+/\\+/g;
if ($acktmp and !($fp{$test}{ack} =~ /(^|\|)$acktmp($|\|)/)) {
if ($fp{$test}{ack}) {
$fp{$test}{ack} .= qq^|$ack^;
} else {
$fp{$test}{ack} = $ack;
}
}
if (!($fp{$test}{flags} =~ /(^|\|)$flags($|\|)/)) {
if ($fp{$test}{flags}) {
$fp{$test}{flags} = $fp{$test}{flags} . qq^|$flags^;
} else {
$fp{$test}{flags} = $flags;
}
}
if ($num != 1 and !($fp{$test}{ops} =~ /(^|\|)$ops($|\|)/)) {
if ($fp{$test}{ops}) {
$fp{$test}{ops} = $fp{$test}{ops} . qq^|$ops^;
} else {
$fp{$test}{ops} = $ops;
}
}
if (!($fp{$test}{rd} =~ /(^|\|)$rd($|\|)/)) {
if ($fp{$test}{rd}) {
$fp{$test}{rd} = $fp{$test}{rd} . qq^|$rd^;
} else {
$fp{$test}{rd} = $rd;
}
}
if (!($fp{$test}{quirk} =~ /(^|\|)$quirk($|\|)/)) {
if ($fp{$test}{quirk}) {
$fp{$test}{quirk} .= qq^|$quirk^;
} else {
$fp{$test}{quirk} = $quirk;
}
}
} elsif ($fp{$test}{resp} ne "Y") {
$fp{$test}{resp} = "N";
}
} elsif ($line =~ /^U1/) {
$resp = $df = $ttl = $tos = $ipl = $un = $ripl = $rid = $ripck = $ruck = $rul = $rud = "";
if ($line =~ /R=([NY])/) {
$resp = $1;
}
if ($line =~ /[\(%]DF=([NY])/) {
$df = $1;
}
if ($line =~ /[\(%]TG?=([0-9A-F]+)/) {
$ttl = $1;
if (!$ttl) { $ttl = "NULL"; }
}
if ($line =~ /[\(%]TOS=([^%]+)/) {
$tos = $1;
if (!$tos) { $tos = "NULL"; }
}
if ($line =~ /[\(%]IPL=([^%]+)/) {
$ipl = $1;
}
if ($line =~ /[\(%]UN=([0-9A-F]*)/) {
$un = $1;
if (!$un) { $un = "NULL"; }
}
if ($line =~ /[\(%]RIPL=([^%]+)/) {
$ripl = $1;
}
if ($line =~ /[\(%]RID=([^%]+)/) {
$rid = $1;
}
if ($line =~ /[\(%]RIPCK=([^%]+)/) {
$ripck = $1;
if (!$ripck) { $ripck = "NULL"; }
}
if ($line =~ /[\(%]RUCK=([^%]+)/) {
$ruck = $1;
if (!$ruck) { $ruck = "NULL"; }
}
if ($line =~ /[\(%]RUL=([^%]+)/) {
$rul = $1;
}
if ($line =~ /[\(%]RUD=([A-Z|]+)/) {
$rud = $1;
}
if ($resp eq "Y" or !$resp) {
$fp{u1}{resp} = "Y";
if ($df and index($fp{u1}{df}, $df) == -1) {
if ($fp{u1}{df}) {
$fp{u1}{df} = $fp{u1}{df} . qq^|$df^;
} else {
$fp{u1}{df} = $df;
}
}
if (!($fp{u1}{ttl} =~ /(^|\|)$ttl($|\|)/)) {
if ($fp{u1}{ttl}) {
$fp{u1}{ttl} = $fp{u1}{ttl} . qq^|$ttl^;
} else {
$fp{u1}{ttl} = $ttl;
}
}
if ($tos and index($fp{u1}{tos}, $tos) == -1) {
if ($fp{u1}{tos}) {
$fp{u1}{tos} = $fp{u1}{tos} . qq^|$tos^;
} else {
$fp{u1}{tos} = $tos;
}
}
if ($ipl and index($fp{u1}{ipl}, $ipl) == -1) {
if ($fp{u1}{ipl}) {
$fp{u1}{ipl} = $fp{u1}{ipl} . qq^|$ipl^;
} else {
$fp{u1}{ipl} = $ipl;
}
}
if ($un and index($fp{u1}{un}, $un) == -1) {
if ($fp{u1}{un}) {
$fp{u1}{un} = $fp{u1}{un} . qq^|$un^;
} else {
$fp{u1}{un} = $un;
}
}
if ($ripl and index($fp{u1}{ripl}, $ripl) == -1) {
if ($fp{u1}{ripl}) {
$fp{u1}{ripl} = $fp{u1}{ripl} . qq^|$ripl^;
} else {
$fp{u1}{ripl} = $ripl;
}
}
if ($rid and index($fp{u1}{rid}, $rid) == -1) {
if ($fp{u1}{rid}) {
$fp{u1}{rid} = $fp{u1}{rid} . qq^|$rid^;
} else {
$fp{u1}{rid} = $rid;
}
}
if ($ripck and index($fp{u1}{ripck}, $ripck) == -1) {
if ($fp{u1}{ripck}) {
$fp{u1}{ripck} = $fp{u1}{ripck} . qq^|$ripck^;
} else {
$fp{u1}{ripck} = $ripck;
}
}
if ($ruck and index($fp{u1}{ruck}, $ruck) == -1) {
if ($fp{u1}{ruck}) {
$fp{u1}{ruck} = $fp{u1}{ruck} . qq^|$ruck^;
} else {
$fp{u1}{ruck} = $ruck;
}
}
if ($rul and index($fp{u1}{rul}, $rul) == -1) {
if ($fp{u1}{rul}) {
$fp{u1}{rul} = $fp{u1}{rul} . qq^|$rul^;
} else {
$fp{u1}{rul} = $rul;
}
}
if ($rud and index($fp{u1}{rud}, $rud) == -1) {
if ($fp{u1}{rud}) {
$fp{u1}{rud} = $fp{u1}{rud} . qq^|$rud^;
} else {
$fp{u1}{rud} = $rud;
}
}
} elsif ($fp{u1}{resp} ne "Y") {
$fp{u1}{resp} = "N";
}
} elsif ($line =~ /^IE/) {
$resp = $dfi = $ttl = $tosi = $cd = $si = $dli = "";
if ($line =~ /R=([NY])/) {
$resp = $1;
}
if ($line =~ /[\(%]DFI=([^%]+)/) {
$dfi = $1;
}
if ($line =~ /[\(%]TG?=([0-9A-F]+)/) {
$ttl = $1;
if (!$ttl) { $ttl = "NULL"; }
}
if ($line =~ /[\(%]TOSI=([^%]+)/) {
$tosi = $1;
if (!$tosi) { $tosi = "NULL"; }
}
if ($line =~ /[\(%]CD=([^%]+)/) {
$cd = $1;
}
if ($line =~ /[\(%]SI=([^%]+)/) {
$si = $1;
}
if ($line =~ /[\(%]DLI=([A-Z|]+)/) {
$dli = $1;
}
if ($resp eq "Y" or !$resp) {
$fp{ie}{resp} = "Y";
if ($dfi and index($fp{ie}{dfi}, $dfi) == -1) {
if ($fp{ie}{dfi}) {
$fp{ie}{dfi} = $fp{ie}{dfi} . qq^|$dfi^;
} else {
$fp{ie}{dfi} = $dfi;
}
}
if (!($fp{ie}{ttl} =~ /(^|\|)$ttl($|\|)/)) {
if ($fp{ie}{ttl}) {
$fp{ie}{ttl} = $fp{ie}{ttl} . qq^|$ttl^;
} else {
$fp{ie}{ttl} = $ttl;
}
}
if ($tosi and index($fp{ie}{tosi}, $tosi) == -1) {
if ($fp{ie}{tosi}) {
$fp{ie}{tosi} = $fp{ie}{tosi} . qq^|$tosi^;
} else {
$fp{ie}{tosi} = $tosi;
}
}
if ($cd and index($fp{ie}{cd}, $cd) == -1) {
if ($fp{ie}{cd}) {
$fp{ie}{cd} = $fp{ie}{cd} . qq^|$cd^;
} else {
$fp{ie}{cd} = $cd;
}
}
if ($si and index($fp{ie}{si}, $si) == -1) {
if ($fp{ie}{si}) {
$fp{ie}{si} = $fp{ie}{si} . qq^|$si^;
} else {
$fp{ie}{si} = $si;
}
}
if ($dli and index($fp{ie}{dli}, $dli) == -1) {
if ($fp{ie}{dli}) {
$fp{ie}{dli} = $fp{ie}{dli} . qq^|$dli^;
} else {
$fp{ie}{dli} = $dli;
}
}
} elsif ($fp{ie}{resp} ne "Y") {
$fp{ie}{resp} = "N";
}
}
}
# OK, now it is time to print out the merged Fprint ...
# Printing contributed by line was like a magnet for spammers and took
# up a substantial amount of space in the file.
# if ($fp{contrib}) { print "# Contributed by $fp{contrib}\n"; }
print "ADJUSTED FINGERPRINT:\n";
print "Fingerprint $fp{os}\n";
if ($fp{class}) { print $fp{class}; }
else { print "Class \n"; }
# SEQ
if ($fp{seq}{sp}) {
print("SEQ(SP=$fp{seq}{sp}");
if ($fp{seq}{gcd}) {
print "%GCD=$fp{seq}{gcd}";
}
if ($fp{seq}{isr}) { print "%ISR=$fp{seq}{isr}"; }
if ($fp{seq}{ti}) { print "%TI=$fp{seq}{ti}"; }
if ($fp{seq}{ii}) { print "%II=$fp{seq}{ii}"; }
if ($fp{seq}{ss}) { print "%SS=$fp{seq}{ss}"; }
if ($fp{seq}{ts}) { print "%TS=$fp{seq}{ts}"; }
print ")\n";
}
# OPS
if ($fp{ops}{o1}) {
$fp{ops}{o1} =~ s/NULL//;
print "OPS(O1=$fp{ops}{o1}";
foreach $num (2 .. 6) {
$oi = "o$num";
$fp{ops}{$oi} =~ s/NULL//;
print "%O$num=$fp{ops}{$oi}";
}
print ")\n";
}
# WIN
if ($fp{win}{w1}) {
$fp{win}{w1} =~ s/NULL/0/;
print "WIN(W1=$fp{win}{w1}";
foreach $num (2 .. 6) {
$wi = "w$num";
$fp{win}{$wi} =~ s/NULL/0/;
print "%W$num=$fp{win}{$wi}";
}
print ")\n";
}
# ECN
if ($fp{ecn}{resp} eq "Y") {
print "ECN(R=Y%";
$fp{ecn}{ttl} =~ s/NULL/0/;
$fp{ecn}{win} =~ s/NULL/0/;
$fp{ops}{win} =~ s/NULL//;
$fp{ecn}{quirk} =~ s/NULL//;
print "DF=$fp{ecn}{df}%T=$fp{ecn}{ttl}%TG=$fp{ecn}{ttl}%W=$fp{ecn}{win}%O=$fp{ecn}{ops}%CC=$fp{ecn}{cc}%Q=$fp{ecn}{quirk})\n";
} else {
print "ECN(R=N)\n";
}
# T1-T7
foreach $t (1 .. 7) {
$test = "T$t";
if ($fp{$test}{resp} eq "Y") {
print "$test(R=Y%";
$fp{$test}{ttl} =~ s/NULL/0/;
$fp{$test}{win} =~ s/NULL/0/;
$fp{$test}{flags} =~ s/NULL//;
$fp{$test}{ops} =~ s/NULL//;
$fp{$test}{rd} =~ s/NULL/0/;
$fp{$test}{quirk} =~ s/NULL//;
if ($t == 1) {
print "DF=$fp{$test}{df}%T=$fp{$test}{ttl}%TG=$fp{$test}{ttl}%S=$fp{$test}{seq}%A=$fp{$test}{ack}%F=$fp{$test}{flags}%RD=$fp{$test}{rd}%Q=$fp{$test}{quirk})\n";
} else {
print "DF=$fp{$test}{df}%T=$fp{$test}{ttl}%TG=$fp{$test}{ttl}%W=$fp{$test}{win}%S=$fp{$test}{seq}%A=$fp{$test}{ack}%F=$fp{$test}{flags}%O=$fp{$test}{ops}%RD=$fp{$test}{rd}%Q=$fp{$test}{quirk})\n";
}
} else {
print "$test(R=N)\n";
}
}
# U1
if ($fp{u1}{resp} eq "Y") {
print "U1(";
$fp{u1}{ttl} =~ s/NULL/0/;
$fp{u1}{tos} =~ s/NULL/0/;
$fp{u1}{uck} =~ s/NULL/0/;
$fp{u1}{un} =~ s/NULL/0/;
$fp{u1}{ripck} =~ s/NULL/0/;
$fp{u1}{ruck} =~ s/NULL/0/;
if ($fp{u1}{rid}) {
$rid = "RID=$fp{u1}{rid}\%";
} else { $ridwarning = 1; $rid = "RID=G\%"; }
print "DF=$fp{u1}{df}%T=$fp{u1}{ttl}%TG=$fp{u1}{ttl}%TOS=$fp{u1}{tos}%IPL=$fp{u1}{ipl}%UN=$fp{u1}{un}%RIPL=$fp{u1}{ripl}%${rid}RIPCK=$fp{u1}{ripck}%RUCK=$fp{u1}{ruck}%RUL=$fp{u1}{rul}%RUD=$fp{u1}{rud})\n";
} else {
print "U1(R=N)\n";
}
# IE
if ($fp{ie}{resp} eq "Y") {
print "IE(";
$fp{ie}{ttl} =~ s/NULL/0/;
$fp{ie}{tosi} =~ s/NULL/0/;
print "DFI=$fp{ie}{dfi}%T=$fp{ie}{ttl}%TG=$fp{ie}{ttl}%TOSI=$fp{ie}{tosi}%CD=$fp{ie}{cd}%SI=$fp{ie}{si}%DLI=$fp{ie}{dli})\n";
} else {
print "IE(R=N)\n";
}
if ($ridwarning == 1) {
$ridwarning = 0;
print "*******************************************************\n" .
"* WARNING: Missing U1 RID value -- this is normal for *\n" .
"* hosts submitted by Solaris or Windows boxes. You *\n" .
"* may want to get RID from similar fingerprints *\n" .
"*******************************************************\n";
}