put back the set/isolate logic into routing which is now overridable with
filters whcih means a default filter is no longer generated.
1. changed debug api to (potentially) use less cpu time
2. changed the spider.cgi in Arnold's borrowed java client to Ian's perl
script
1. changed debug api to (potentially) use less cpu time
2. changed the spider.cgi in Arnold's borrowed java client to Ian's perl
script
+3. Added input route filtering
+4. put back the set/isolate logic into routing which is now overridable with
+filters whcih means a default filter is no longer generated.
13Jun01=======================================================================
1. fix init cnd rinit cmds
2. add missing clear/route cmd
13Jun01=======================================================================
1. fix init cnd rinit cmds
2. add missing clear/route cmd
# check for and dump bad protocol messages
my $n = check($pcno, @field);
if ($n) {
# check for and dump bad protocol messages
my $n = check($pcno, @field);
if ($n) {
- dbg("PCPROT: bad field $n, dumped (" . parray($checklist[$pcno-10]) . ")") if isdbg('chan');
+ dbg("PCPROT: bad field $n, dumped (" . parray($checklist[$pcno-10]) . ")") if isdbg('chanerr');
if ($censorpc) {
my @bad;
if (@bad = BadWords::check($field[3])) {
if ($censorpc) {
my @bad;
if (@bad = BadWords::check($field[3])) {
- dbg("PCPROT: Bad words: @bad, dropped") if isdbg('chan');
+ dbg("PCPROT: Bad words: @bad, dropped") if isdbg('chanerr');
# if this is a 'nodx' node then ignore it
if ($badnode->in($field[7])) {
# if this is a 'nodx' node then ignore it
if ($badnode->in($field[7])) {
- dbg("PCPROT: Bad Node, dropped") if isdbg('chan');
+ dbg("PCPROT: Bad Node, dropped") if isdbg('chanerr');
return;
}
# if this is a 'bad spotter' user then ignore it
if ($badspotter->in($field[6])) {
return;
}
# if this is a 'bad spotter' user then ignore it
if ($badspotter->in($field[6])) {
- dbg("PCPROT: Bad Spotter, dropped") if isdbg('chan');
+ dbg("PCPROT: Bad Spotter, dropped") if isdbg('chanerr');
my $d = cltounix($field[3], $field[4]);
# bang out (and don't pass on) if date is invalid or the spot is too old (or too young)
if (!$d || ($pcno == 11 && ($d < $main::systime - $pc11_max_age || $d > $main::systime + 900))) {
my $d = cltounix($field[3], $field[4]);
# bang out (and don't pass on) if date is invalid or the spot is too old (or too young)
if (!$d || ($pcno == 11 && ($d < $main::systime - $pc11_max_age || $d > $main::systime + 900))) {
- dbg("PCPROT: Spot ignored, invalid date or out of range ($field[3] $field[4])\n") if isdbg('chan');
+ dbg("PCPROT: Spot ignored, invalid date or out of range ($field[3] $field[4])\n") if isdbg('chanerr');
return;
}
# is it 'baddx'
if ($baddx->in($field[2])) {
return;
}
# is it 'baddx'
if ($baddx->in($field[2])) {
- dbg("PCPROT: Bad DX spot, ignored") if isdbg('chan');
+ dbg("PCPROT: Bad DX spot, ignored") if isdbg('chanerr');
$field[5] =~ s/^\s+//; # take any leading blanks off
$field[2] = unpad($field[2]); # take off leading and trailing blanks from spotted callsign
if ($field[2] =~ /BUST\w*$/) {
$field[5] =~ s/^\s+//; # take any leading blanks off
$field[2] = unpad($field[2]); # take off leading and trailing blanks from spotted callsign
if ($field[2] =~ /BUST\w*$/) {
- dbg("PCPROT: useless 'BUSTED' spot") if isdbg('chan');
+ dbg("PCPROT: useless 'BUSTED' spot") if isdbg('chanerr');
return;
}
if (Spot::dup($field[1], $field[2], $d, $field[5])) {
return;
}
if (Spot::dup($field[1], $field[2], $d, $field[5])) {
- dbg("PCPROT: Duplicate Spot ignored\n") if isdbg('chan');
+ dbg("PCPROT: Duplicate Spot ignored\n") if isdbg('chanerr');
return;
}
if ($censorpc) {
my @bad;
if (@bad = BadWords::check($field[5])) {
return;
}
if ($censorpc) {
my @bad;
if (@bad = BadWords::check($field[5])) {
- dbg("PCPROT: Bad words: @bad, dropped") if isdbg('chan');
+ dbg("PCPROT: Bad words: @bad, dropped") if isdbg('chanerr');
if ($self->{inspotsfilter}) {
my ($filter, $hops) = $self->{inspotsfilter}->it(@spot);
unless ($filter) {
if ($self->{inspotsfilter}) {
my ($filter, $hops) = $self->{inspotsfilter}->it(@spot);
unless ($filter) {
- dbg("PCPROT: Rejected by filter") if isdbg('chan');
+ dbg("PCPROT: Rejected by filter") if isdbg('chanerr');
# announce duplicate checking
$field[3] =~ s/^\s+//; # remove leading blanks
if (AnnTalk::dup($field[1], $field[2], $field[3])) {
# announce duplicate checking
$field[3] =~ s/^\s+//; # remove leading blanks
if (AnnTalk::dup($field[1], $field[2], $field[3])) {
- dbg("PCPROT: Duplicate Announce ignored") if isdbg('chan');
+ dbg("PCPROT: Duplicate Announce ignored") if isdbg('chanerr');
return;
}
if ($censorpc) {
my @bad;
if (@bad = BadWords::check($field[3])) {
return;
}
if ($censorpc) {
my @bad;
if (@bad = BadWords::check($field[3])) {
- dbg("PCPROT: Bad words: @bad, dropped") if isdbg('chan');
+ dbg("PCPROT: Bad words: @bad, dropped") if isdbg('chanerr');
my ($filter, $hops) = $self->{inannfilter}->it(@field[1..6], $self->{call},
$ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq);
unless ($filter) {
my ($filter, $hops) = $self->{inannfilter}->it(@field[1..6], $self->{call},
$ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq);
unless ($filter) {
- dbg("PCPROT: Rejected by filter") if isdbg('chan');
+ dbg("PCPROT: Rejected by filter") if isdbg('chanerr');
my $newline = "PC16^";
if ($ncall eq $main::mycall) {
my $newline = "PC16^";
if ($ncall eq $main::mycall) {
- dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chan');
+ dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chanerr');
return;
}
$dxchan = DXChannel->get($ncall);
if ($dxchan && $dxchan ne $self) {
return;
}
$dxchan = DXChannel->get($ncall);
if ($dxchan && $dxchan ne $self) {
- dbg("PCPROT: PC16 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chan');
+ dbg("PCPROT: PC16 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chanerr');
return;
}
my $parent = Route::Node::get($ncall);
unless ($parent) {
return;
}
my $parent = Route::Node::get($ncall);
unless ($parent) {
- dbg("PCPROT: Node $ncall not in config") if isdbg('chan');
+ dbg("PCPROT: Node $ncall not in config") if isdbg('chanerr');
+
+ # input filter if required
+ return unless $self->in_filter_route($parent);
+
my $i;
my @rout;
for ($i = 2; $i < $#field; $i++) {
my $i;
my @rout;
for ($i = 2; $i < $#field; $i++) {
my $ncall = $field[2];
my $ucall = $field[1];
if ($ncall eq $main::mycall) {
my $ncall = $field[2];
my $ucall = $field[1];
if ($ncall eq $main::mycall) {
- dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chan');
+ dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chanerr');
return;
}
$dxchan = DXChannel->get($ncall);
if ($dxchan && $dxchan ne $self) {
return;
}
$dxchan = DXChannel->get($ncall);
if ($dxchan && $dxchan ne $self) {
- dbg("PCPROT: PC17 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chan');
+ dbg("PCPROT: PC17 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chanerr');
return;
}
my $parent = Route::Node::get($ncall);
unless ($parent) {
return;
}
my $parent = Route::Node::get($ncall);
unless ($parent) {
- dbg("PCPROT: Route::Node $ncall not in config") if isdbg('chan');
+ dbg("PCPROT: Route::Node $ncall not in config") if isdbg('chanerr');
+
+ # input filter if required
+ return unless $self->in_filter_route($parent);
+
my @rout = $parent->del_user($ucall);
$self->route_pc17($parent, @rout) if @rout;
return;
my @rout = $parent->del_user($ucall);
$self->route_pc17($parent, @rout) if @rout;
return;
next if length $call < 3; # min 3 letter callsigns
# update it if required
next if length $call < 3; # min 3 letter callsigns
# update it if required
+ my $r = Route::Node::get($call);
my $flags = Route::here($here)|Route::conf($conf);
if ($parent->call eq $call && ($parent->version ne $ver || $parent->flags != $flags)) {
$parent->version($ver);
$parent->flags($flags);
push @rout, $parent;
my $flags = Route::here($here)|Route::conf($conf);
if ($parent->call eq $call && ($parent->version ne $ver || $parent->flags != $flags)) {
$parent->version($ver);
$parent->flags($flags);
push @rout, $parent;
- } elsif ($parent->call ne $call) {
- next if $call eq $main::mycall || $call eq $self->{call};
-
- my $r = $parent->add($call, $ver, Route::here($here)|Route::conf($conf));
- push @rout, $r if $r;
- } else {
- $r = Route::Node::get($call);
- if ($r && ($r->version ne $ver || $r->flags != $flags)) {
+ } elsif ($r) {
+ my $ar = $parent->add($r);
+ push @rout, $ar if $ar;
+ if ($r->version ne $ver || $r->flags != $flags) {
$r->version($ver);
$r->flags(Route::here($here)|Route::conf($conf));
$r->version($ver);
$r->flags(Route::here($here)|Route::conf($conf));
+ push @rout, $r unless $ar;
+ }
+ } elsif ($parent->call ne $call) {
+ next if $call eq $main::mycall || $call eq $self->{call};
+
+ my $new = Route::Node->new($call, $ver, Route::here($here)|Route::conf($conf));
+ if ($self->in_filter_route($new)) {
+ $parent->add($new);
+ push @rout, $new;
+ } else {
+ $new->del($parent);
my @rout;
my $parent = Route::Node::get($self->{call});
unless ($parent) {
my @rout;
my $parent = Route::Node::get($self->{call});
unless ($parent) {
- dbg("PCPROT: Route::Node $call not in config") if isdbg('chan');
+ dbg("PCPROT: Route::Node $call not in config") if isdbg('chanerr');
return;
}
my $node = Route::Node::get($call);
return;
}
my $node = Route::Node::get($call);
if ($call ne $main::mycall) { # don't allow malicious buggers to disconnect me!
if ($call eq $self->{call}) {
if ($call ne $main::mycall) { # don't allow malicious buggers to disconnect me!
if ($call eq $self->{call}) {
- dbg("PCPROT: Trying to disconnect myself with PC21") if isdbg('chan');
+ dbg("PCPROT: Trying to disconnect myself with PC21") if isdbg('chanerr');
- # routing objects
- push @rout, $node->del($parent) if $node;
+ if ($node) {
+ # input filter it
+ return unless $self->in_filter_route($node);
+
+ # routing objects
+ push @rout, $node->del($parent);
+ }
- dbg("PCPROT: I WILL _NOT_ be disconnected!") if isdbg('chan');
+ dbg("PCPROT: I WILL _NOT_ be disconnected!") if isdbg('chanerr');
return;
}
$self->route_pc21(@rout) if @rout;
return;
}
$self->route_pc21(@rout) if @rout;
my ($r) = $field[6] =~ /R=(\d+)/;
$r = 0 unless $r;
if (($pcno == 23 && $d < $main::systime - $pc23_max_age) || $d > $main::systime + 1500 || $field[2] < 0 || $field[2] > 23) {
my ($r) = $field[6] =~ /R=(\d+)/;
$r = 0 unless $r;
if (($pcno == 23 && $d < $main::systime - $pc23_max_age) || $d > $main::systime + 1500 || $field[2] < 0 || $field[2] > 23) {
- dbg("PCPROT: WWV Date ($field[1] $field[2]) out of range") if isdbg('chan');
+ dbg("PCPROT: WWV Date ($field[1] $field[2]) out of range") if isdbg('chanerr');
return;
}
if (Geomag::dup($d,$sfi,$k,$i,$field[6])) {
return;
}
if (Geomag::dup($d,$sfi,$k,$i,$field[6])) {
- dbg("PCPROT: Dup WWV Spot ignored\n") if isdbg('chan');
+ dbg("PCPROT: Dup WWV Spot ignored\n") if isdbg('chanerr');
return;
}
$field[7] =~ s/-\d+$//o; # remove spotter's ssid
return;
}
$field[7] =~ s/-\d+$//o; # remove spotter's ssid
$ref = Route::User::get($call);
$ref->here($field[2]) if $ref;
$ref = Route::User::get($call);
$ref->here($field[2]) if $ref;
+ # input filter if required
+ return unless $self->in_filter_route($ref);
+
$self->route_pc24($ref, $field[3]) if $ref && !eph_dup($line);
return;
}
$self->route_pc24($ref, $field[3]) if $ref && !eph_dup($line);
return;
}
return;
}
if ($field[2] eq $main::mycall) {
return;
}
if ($field[2] eq $main::mycall) {
- dbg("PCPROT: Trying to merge to myself, ignored") if isdbg('chan');
+ dbg("PCPROT: Trying to merge to myself, ignored") if isdbg('chanerr');
if ($field[1] eq $self->{call}) {
$self->disconnect(1);
} else {
if ($field[1] eq $self->{call}) {
$self->disconnect(1);
} else {
- dbg("PCPROT: came in on wrong channel") if isdbg('chan');
+ dbg("PCPROT: came in on wrong channel") if isdbg('chanerr');
$user->lastoper($main::systime); # to cut down on excessive for/opers being generated
$user->put;
my $ref = Route::get($call);
$user->lastoper($main::systime); # to cut down on excessive for/opers being generated
$user->put;
my $ref = Route::get($call);
+
+ # input filter if required
+ return unless $self->in_filter_route($ref);
+
$self->route_pc41($ref, $call, $field[2], $field[3], $field[4]) if $ref && !eph_dup($line);
return;
}
$self->route_pc41($ref, $call, $field[2], $field[3], $field[4]) if $ref && !eph_dup($line);
return;
}
if ($node) {
return unless $node->call eq $self->{call};
$node->usercount($field[2]);
if ($node) {
return unless $node->call eq $self->{call};
$node->usercount($field[2]);
+
+ # input filter if required
+ return unless $self->in_filter_route($node);
+
$self->route_pc50($node, $field[2], $field[3]) unless eph_dup($line);
}
return;
$self->route_pc50($node, $field[2], $field[3]) unless eph_dup($line);
}
return;
# do some de-duping
my $d = cltounix($call, sprintf("%02d18Z", $field[2]));
if (($pcno == 23 && $d < $main::systime - $pc23_max_age) || $d > $main::systime + 1500 || $field[2] < 0 || $field[2] > 23) {
# do some de-duping
my $d = cltounix($call, sprintf("%02d18Z", $field[2]));
if (($pcno == 23 && $d < $main::systime - $pc23_max_age) || $d > $main::systime + 1500 || $field[2] < 0 || $field[2] > 23) {
- dbg("PCPROT: WCY Date ($call $field[2]) out of range") if isdbg('chan');
+ dbg("PCPROT: WCY Date ($call $field[2]) out of range") if isdbg('chanerr');
return;
}
@field = map { unpad($_) } @field;
if (WCY::dup($d,@field[3..7])) {
return;
}
@field = map { unpad($_) } @field;
if (WCY::dup($d,@field[3..7])) {
- dbg("PCPROT: Dup WCY Spot ignored\n") if isdbg('chan');
+ dbg("PCPROT: Dup WCY Spot ignored\n") if isdbg('chanerr');
- dbg("PCPROT: Ephemeral dup, dropped") if isdbg('chan');
+ dbg("PCPROT: Ephemeral dup, dropped") if isdbg('chanerr');
} else {
unless ($self->{isolate}) {
broadcast_ak1a($line, $self); # send it to everyone but me
} else {
unless ($self->{isolate}) {
broadcast_ak1a($line, $self); # send it to everyone but me
if ($n) {
send_route($self, \&pc16, 1, $n, map {my $r = Route::User::get($_); $r ? ($r) : ()} $n->users);
} else {
if ($n) {
send_route($self, \&pc16, 1, $n, map {my $r = Route::User::get($_); $r ? ($r) : ()} $n->users);
} else {
- dbg("sent a null value") if isdbg('chan');
+ dbg("sent a null value") if isdbg('chanerr');
my ($self, $call, $line) = @_;
if (ref $self && $call eq $self->{call}) {
my ($self, $call, $line) = @_;
if (ref $self && $call eq $self->{call}) {
- dbg("PCPROT: Trying to route back to source, dropped") if isdbg('chan');
+ dbg("PCPROT: Trying to route back to source, dropped") if isdbg('chanerr');
$dxchan = $cl->dxchan if $cl;
if (ref $dxchan) {
if (ref $self && $dxchan eq $self) {
$dxchan = $cl->dxchan if $cl;
if (ref $dxchan) {
if (ref $self && $dxchan eq $self) {
- dbg("PCPROT: Trying to route back to source, dropped") if isdbg('chan');
+ dbg("PCPROT: Trying to route back to source, dropped") if isdbg('chanerr');
$dxchan->send($routeit);
}
} else {
$dxchan->send($routeit);
}
} else {
- dbg("PCPROT: No route available, dropped") if isdbg('chan');
+ dbg("PCPROT: No route available, dropped") if isdbg('chanerr');
my ($filter, $hops);
my @rin;
my ($filter, $hops);
my @rin;
- if ($self->{routefilter}) {
- for (; @_ && $no; $no--) {
- my $r = shift;
+ for (; @_ && $no; $no--) {
+ my $r = shift;
+
+ if ($self->{routefilter}) {
+ $filter = undef;
if ($r) {
($filter, $hops) = $self->{routefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq);
if ($r) {
($filter, $hops) = $self->{routefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq);
- push @rin, $r if $filter;
+ if ($filter) {
+ push @rin, $r;
+ } else {
+ dbg('DXPROT: Rejected by filter') if isdbg('chanerr');
+ }
- dbg("was sent a null value") if isdbg('chan');
+ dbg("was sent a null value") if isdbg('chanerr');
+ } else {
+ push @rin, $r;
$routeit = adjust_hops($self, $line); # adjust its hop count by node name
next unless $routeit;
}
$routeit = adjust_hops($self, $line); # adjust its hop count by node name
next unless $routeit;
}
+ $self->send($routeit) if $self->{routefilter} || !$self->{isolate};
foreach $dxchan (@dxchan) {
next if $dxchan == $self;
next if $dxchan == $me;
foreach $dxchan (@dxchan) {
next if $dxchan == $self;
next if $dxchan == $me;
- $dxchan->send_route($generate, @_);
+ if ($self->{routefilter} || !$self->{isolate}) {
+ $dxchan->send_route($generate, @_)
+ } else {
+ dbg('DXPROT: isolated') if isdbg('chanerr');
+ }
broadcast_route($self, \&pc50, 1, @_);
}
broadcast_route($self, \&pc50, 1, @_);
}
+sub in_filter_route
+{
+ my $self = shift;
+ my $r = shift;
+ my ($filter, $hops) = (1, 1);
+
+ if ($self->{inroutefilter}) {
+ ($filter, $hops) = $self->{inroutefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq);
+ dbg('PCPROT: rejected by filter') if !$filter && isdbg('chanerr');
+ }
+ return $filter;
+}
sub add
{
my $parent = shift;
sub add
{
my $parent = shift;
- my $call = uc shift;
- confess "Route::add trying to add $call to myself" if $call eq $parent->{call};
- my $self = get($call);
+ my $call = shift;
+ my $self;
+
+ if (ref $call) {
+ $self = $call;
+ $call = $self->{call};
+ } else {
+ $self = get($call);
+ }
+
+ confess "Trying to add NULL Node call to routing tables" unless $call;
+
if ($self) {
$self->_addparent($parent->{call});
$parent->_addnode($call);
return undef;
}
if ($self) {
$self->_addparent($parent->{call});
$parent->_addnode($call);
return undef;
}
+ confess "Route::Node::add trying to add $call to myself" if $call eq $parent->{call};
$parent->_addnode($call);
$self = $parent->new($call, @_);
return $self;
$parent->_addnode($call);
$self = $parent->new($call, @_);
return $self;
{
my $self = shift;
my $ucall = shift;
{
my $self = shift;
my $ucall = shift;
+
+ confess "Trying to add NULL User call to routing tables" unless $ucall;
+
$self->_adduser($ucall);
$self->{usercount} = scalar @{$self->{users}};
$self->_adduser($ucall);
$self->{usercount} = scalar @{$self->{users}};
$routeroot = Route::Node->new($mycall, $version*100+5300, Route::here($DXProt::me->here)|Route::conf($DXProt::me->conf));
# make sure that there is a routing OUTPUT node default file
$routeroot = Route::Node->new($mycall, $version*100+5300, Route::here($DXProt::me->here)|Route::conf($DXProt::me->conf));
# make sure that there is a routing OUTPUT node default file
-unless (Filter::read_in('route', 'node_default', 0)) {
- my $dxcc = $DXProt::me->dxcc;
- $Route::filterdef->cmd($DXProt::me, 'route', 'accept', "node_default call $mycall" );
-}
+#unless (Filter::read_in('route', 'node_default', 0)) {
+# my $dxcc = $DXProt::me->dxcc;
+# $Route::filterdef->cmd($DXProt::me, 'route', 'accept', "node_default call $mycall" );
+#}
# read in any existing message headers and clean out old crap
dbg("reading existing message headers ...");
# read in any existing message headers and clean out old crap
dbg("reading existing message headers ...");