From a204e3cd89e849e97db25879b4ddf62b770bd227 Mon Sep 17 00:00:00 2001 From: minima Date: Sun, 19 Jan 2003 00:43:30 +0000 Subject: [PATCH] make the major mod to make PC16 the master record for triggering the update of the routing table. --- Changes | 11 +++ cmd/set/routepc19.pl | 28 ++++++ cmd/stat/pc19list.pl | 23 +++++ cmd/unset/routepc19.pl | 28 ++++++ perl/DXProt.pm | 209 ++++++++++++++++++++++++++++------------- perl/DXUser.pm | 8 +- perl/Filter.pm | 4 +- perl/Messages | 4 + perl/Msg.pm | 1 - 9 files changed, 248 insertions(+), 68 deletions(-) create mode 100644 cmd/set/routepc19.pl create mode 100644 cmd/stat/pc19list.pl create mode 100644 cmd/unset/routepc19.pl diff --git a/Changes b/Changes index 93c294ff..cdf50df9 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,14 @@ +19Jan03======================================================================= +1. I have made a fundemental change to the way PC19s are dealt with as a +result of the discussions on the mailing list. From now on, only nodes that +issue PC16s will have PC19s propagated. If they *ever* issue a PC16 then from +then on they are considered as being 'connected' and thus routable. No PC16 +and you have no route. This should stop all passive links being routed. For +the few cases where you know that that is a very small node and it rarely has +users, then you can do a set/routepc19 to enable PC19 propagation. In +the even more rare case of you wanting to prevent PC19s being routed thru +your node, you can use unset/routepc19. THIS IS NOT A SUBSTITUTE FOR ROUTE +FILTERING!!!!! [translators: I have added wpc16s, wpc16u, wpc19s, wpc19u] 17Jan03======================================================================= 1. Fix problem with lines being left in the main input queue for a disconnected/ing node. diff --git a/cmd/set/routepc19.pl b/cmd/set/routepc19.pl new file mode 100644 index 00000000..6b5364bd --- /dev/null +++ b/cmd/set/routepc19.pl @@ -0,0 +1,28 @@ +# +# set the want to send PC19 route flag +# +# Copyright (c) 2002 - Dirk Koopman +# +# $Id$ +# + +my ($self, $line) = @_; +my @args = split /\s+/, uc $line; +my $call; +my @out; + +return (1, $self->msg('e5')) if $self->priv < 9; + +foreach $call (@args) { + return (1, $self->msg('e12')) unless is_callsign($call); + + my $user = DXUser->get_current($call); + if ($user) { + $user->wantroutepc19(1); + $user->put; + push @out, $self->msg('wpc19s', $call); + } else { + push @out, $self->msg('e3', "set/wantroutepc19", $call); + } +} +return (1, @out); diff --git a/cmd/stat/pc19list.pl b/cmd/stat/pc19list.pl new file mode 100644 index 00000000..58623cdb --- /dev/null +++ b/cmd/stat/pc19list.pl @@ -0,0 +1,23 @@ +# +# list out the PC19s that are outstanding (for which PC16s have not been seen) +# +# Copyright (c) 2003 Dirk Koopman G1TLH +# +# $Id$ +# + +my $self = shift; +return (1, $self->msg('e5')) unless $self->priv >= 9; + +my @patt = map {"^\Q$_"} split /\s+/, uc shift; +my @out; + +foreach my $k (sort keys %DXProt::pc19list) { + if (!@patt || grep $k =~ /$_/, @patt) { + my $nl = $DXProt::pc19list{$k}; + push @out, "$k: " . join (', ', map {"via $_->[0]($_->[1] $_->[2])"} @$nl); + } +} + +return (1, @out); + diff --git a/cmd/unset/routepc19.pl b/cmd/unset/routepc19.pl new file mode 100644 index 00000000..3b6ca355 --- /dev/null +++ b/cmd/unset/routepc19.pl @@ -0,0 +1,28 @@ +# +# set the don't want to send PC19 route flag +# +# Copyright (c) 2002 - Dirk Koopman +# +# $Id$ +# + +my ($self, $line) = @_; +my @args = split /\s+/, uc $line; +my $call; +my @out; + +return (1, $self->msg('e5')) if $self->priv < 9; + +foreach $call (@args) { + return (1, $self->msg('e12')) unless is_callsign($call); + + my $user = DXUser->get_current($call); + if ($user) { + $user->wantroutepc19(0); + $user->put; + push @out, $self->msg('wpc19u', $call); + } else { + push @out, $self->msg('e3', "unset/wantroutepc19", $call); + } +} +return (1, @out); diff --git a/perl/DXProt.pm b/perl/DXProt.pm index 53bd418b..66434a0e 100644 --- a/perl/DXProt.pm +++ b/perl/DXProt.pm @@ -44,7 +44,7 @@ $main::branch += $BRANCH; use vars qw($pc11_max_age $pc23_max_age $last_pc50 $eph_restime $eph_info_restime $eph_pc34_restime $last_hour $last10 %eph %pings %rcmds $ann_to_talk - $pingint $obscount + $pingint $obscount %pc19list %nodehops $baddx $badspotter $badnode $censorpc $rspfcheck $allowzero $decode_dk0wcy $send_opernam @checklist); @@ -55,6 +55,8 @@ $last_hour = time; # last time I did an hourly periodic update %pings = (); # outstanding ping requests outbound %rcmds = (); # outstanding rcmd requests outbound %nodehops = (); # node specific hop control +%pc19list = (); # list of outstanding PC19s that haven't had PC16s on them + $censorpc = 1; # Do a BadWords::check on text fields and reject things # loads of 'bad things' $baddx = new DXHash "baddx"; @@ -639,19 +641,70 @@ sub normal return; } my $parent = Route::Node::get($ncall); + + # if there is a parent, proceed, otherwise if there is a latent PC19 in the PC19list, + # fix it up in the routing tables and issue it forth before the PC16 unless ($parent) { - dbg("PCPROT: Node $ncall not in config") if isdbg('chanerr'); - return; - } - $dxchan = $parent->dxchan; - if ($dxchan && $dxchan ne $self) { - dbg("PCPROT: PC16 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chanerr'); - return; + if (my $nl = $pc19list{$ncall}) { + + # this is a new (remembered) node, now attach it to me if it isn't in filtered + # and we haven't disallowed it + my $user = DXUser->get_current($ncall); + if (!$user) { + $user = DXUser->new($ncall); + $user->sort('A'); + $user->priv(1); # I have relented and defaulted nodes + $user->lockout(1); + $user->homenode($ncall); + $user->node($ncall); + } + + delete $pc19list{$ncall}; # whatever happens - it goes + + my $wantpc19 = $user->wantroutepc19; + if ($wantpc19 || !defined $wantpc19) { + my $new = Route->new($ncall); # throw away + if ($self->in_filter_route($new)) { + my @nrout; + for (@$nl) { + $parent = Route::Node::get($_->[0]); + $dxchan = $parent->dxchan if $parent; + if ($dxchan && $dxchan ne $self) { + dbg("PCPROT: PC16 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chanerr'); + $parent = undef; + } + if ($parent) { + my $r = $parent->add($ncall, $_->[1], $_->[2]); + push @nrout, $r unless @nrout; + } + } + $user->wantroutepc19(1) unless defined $wantpc19; # for now we work on the basis that pc16 = real route + $user->lastin($main::systime) unless DXChannel->get($ncall); + $user->put; + + # route the pc19 - this will cause 'stuttering PC19s' for a while + $self->route_pc19(@nrout) if @nrout ; + $parent = Route::Node::get($ncall); + } else { + return; + } + } + } else { + dbg("PCPROT: Node $ncall not in config") if isdbg('chanerr'); + return; + } + } else { + + $dxchan = $parent->dxchan; + if ($dxchan && $dxchan ne $self) { + dbg("PCPROT: PC16 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chanerr'); + return; + } + + # input filter if required + return unless $self->in_filter_route($parent); } - # input filter if required - return unless $self->in_filter_route($parent); - my $i; my @rout; for ($i = 2; $i < $#field; $i++) { @@ -683,6 +736,7 @@ sub normal } else { push @rout, $parent->add_user($call, $flags); } + # add this station to the user database, if required $call =~ s/-\d+$//o; # remove ssid for users @@ -819,9 +873,21 @@ sub normal next; } - # update it if required + # add this station to the user database, if required (don't remove SSID from nodes) + my $user = DXUser->get_current($call); + if (!$user) { + $user = DXUser->new($call); + $user->sort('A'); + $user->priv(1); # I have relented and defaulted nodes + $user->lockout(1); + $user->homenode($call); + $user->node($call); + } + my $r = Route::Node::get($call); my $flags = Route::here($here)|Route::conf($conf); + + # modify the routing table if it is in it, otherwise store it in the pc19list for now if ($r) { my $ar; if ($call ne $parent->call) { @@ -838,17 +904,19 @@ sub normal push @rout, $r unless $ar; } } else { - if ($call eq $self->{call}) { - dbg("DXPROT: my channel route for $call has disappeared"); - next; - }; - - my $new = Route->new($call); # throw away - if ($self->in_filter_route($new)) { - my $r = $parent->add($call, $ver, $flags); - push @rout, $r; + + # if he is directly connected or allowed then add him, otherwise store him up for later + if ($call eq $self->{call} || $user->wantroutepc19) { + my $new = Route->new($call); # throw away + if ($self->in_filter_route($new)) { + my $ar = $parent->add($call, $ver, $flags); + push @rout, $ar if $ar; + } else { + next; + } } else { - next; + $pc19list{$call} = [] unless exists $pc19list{$call}; + push @{$pc19list{$call}}, [$self->{call}, $ver, $flags]; } } @@ -856,16 +924,6 @@ sub normal my $mref = DXMsg::get_busy($call); $mref->stop_msg($call) if $mref; - # add this station to the user database, if required (don't remove SSID from nodes) - my $user = DXUser->get_current($call); - if (!$user) { - $user = DXUser->new($call); - $user->sort('A'); - $user->priv(1); # I have relented and defaulted nodes - $user->lockout(1); - $user->homenode($call); - $user->node($call); - } $user->lastin($main::systime) unless DXChannel->get($call); $user->put; } @@ -886,7 +944,7 @@ sub normal if ($pcno == 21) { # delete a cluster from the list my $call = uc $field[1]; - eph_del_regex("^PC1[79].*$call"); + eph_del_regex("^PC1[679].*$call"); # if I get a PC21 from the same callsign as self then treat it # as a PC39: I have gone away @@ -895,39 +953,42 @@ sub normal return; } + # check to see if we are in the pc19list, if we are then don't bother with any of + # this routing table manipulation, just remove it from the list and dump it my @rout; - my $parent = Route::Node::get($self->{call}); - unless ($parent) { - dbg("DXPROT: my parent $self->{call} has disappeared"); - $self->disconnect; - return; - } - if ($call ne $main::mycall) { # don't allow malicious buggers to disconnect me! - my $node = Route::Node::get($call); - if ($node) { - - my $dxchan = DXChannel->get($call); - if ($dxchan && $dxchan != $self) { - dbg("PCPROT: PC21 from $self->{call} trying to alter locally connected $call, ignored!") if isdbg('chanerr'); - return; + if (my $nl = $pc19list{$call}) { + $pc19list{$call} = [ grep {$_->[0] ne $self->{call}} @$nl ]; + delete $pc19list{$call} unless @{$pc19list{$call}}; + } else { + + my $parent = Route::Node::get($self->{call}); + unless ($parent) { + dbg("DXPROT: my parent $self->{call} has disappeared"); + $self->disconnect; + return; + } + if ($call ne $main::mycall) { # don't allow malicious buggers to disconnect me! + my $node = Route::Node::get($call); + if ($node) { + + my $dxchan = DXChannel->get($call); + if ($dxchan && $dxchan != $self) { + dbg("PCPROT: PC21 from $self->{call} trying to alter locally connected $call, ignored!") if isdbg('chanerr'); + return; + } + + # input filter it + return unless $self->in_filter_route($node); + + # routing objects + push @rout, $node->del($parent); } - - # input filter it - return unless $self->in_filter_route($node); - - # routing objects - push @rout, $node->del($parent); + } else { + dbg("PCPROT: I WILL _NOT_ be disconnected!") if isdbg('chanerr'); + return; } - } else { - dbg("PCPROT: I WILL _NOT_ be disconnected!") if isdbg('chanerr'); - return; } -# if (eph_dup($line)) { -# dbg("PCPROT: dup PC21 detected") if isdbg('chanerr'); -# return; -# } - $self->route_pc21(@rout) if @rout; return; } @@ -1829,17 +1890,35 @@ sub disconnect $self->send_now("D", DXProt::pc39($main::mycall, $self->msg('disc1', "System Op"))); } - # get rid of any PC16 and 19s - eph_del_regex("^PC16\\^$call"); - eph_del_regex("^PC19\\^.*$call"); + # get rid of any PC16/17/19/21s + eph_del_regex("^PC(?:1[679]|21).*$call"); - # do routing stuff + # do routing stuff, remove me from routing table my $node = Route::Node::get($call); my @rout; if ($node) { @rout = $node->del($main::routeroot); + + # and all my ephemera as well + for (@rout) { + my $c = $_->call; + eph_del_regex("^PC(?:1[679]|21).*$c"); + } } + # remove them from the pc19list as well + while (my ($k,$v) = each %pc19list) { + my @l = grep {$_->[0] ne $call} @{$pc19list{$k}}; + if (@l) { + $pc19list{$k} = \@l; + } else { + delete $pc19list{$k}; + } + + # and the ephemera + eph_del_regex("^PC(?:1[679]|21).*$k"); + } + # unbusy and stop and outgoing mail my $mref = DXMsg::get_busy($call); $mref->stop_msg($call) if $mref; diff --git a/perl/DXUser.pm b/perl/DXUser.pm index dec317a1..e5a6a3b2 100644 --- a/perl/DXUser.pm +++ b/perl/DXUser.pm @@ -79,7 +79,8 @@ $lrusize = 2000; wantpc90 => '1,Req PC90,yesno', wantnp => '1,Req New Protocol,yesno', wantpc16 => '9,Want Users from node,yesno', - wantsendpc16 => '9,Send users to node,yesno', + wantsendpc16 => '9,Send PC16,yesno', + wantroutepc19 => '9,Route PC19,yesno', lastoper => '9,Last for/oper,cldatetime', nothere => '0,Not Here Text', registered => '9,Registered?,yesno', @@ -589,6 +590,11 @@ sub wantsendpc16 return _want('sendpc16', @_); } +sub wantroutepc16 +{ + return _want('routepc16', @_); +} + sub wantlogininfo { my $self = shift; diff --git a/perl/Filter.pm b/perl/Filter.pm index 0ca71917..4443fc55 100644 --- a/perl/Filter.pm +++ b/perl/Filter.pm @@ -92,7 +92,9 @@ sub compile my $rr; if ($ref->{$ar} && exists $ref->{$ar}->{asc}) { - $ref->{$ar}->{code} = eval "sub { my \$r=shift; return $ref->{$ar}->{asc}; }" ; + my $s = $ref->{$ar}->{asc}; # an optimisation? + $s =~ s/\$r/\$_[0]/g; + $ref->{$ar}->{code} = eval "sub { $s }" ; if ($@) { my $sort = $ref->{sort}; my $name = $ref->{name}; diff --git a/perl/Messages b/perl/Messages index f88481b3..e8abfae4 100644 --- a/perl/Messages +++ b/perl/Messages @@ -290,6 +290,10 @@ package DXM; wcy2 => 'Duplicate WCY', wcys => 'WCY enabled for $_[0]', wcyu => 'WCY disabled for $_[0]', + wpc16s => 'Allow PC16 from $_[0] enabled', + wpc16u => 'Allow PC16 from $_[0] disabled', + wpc19s => 'Route PC19 for $_[0] enabled', + wpc19u => 'Route PC19 for $_[0] disabled', wwv1 => '$_[0] is missing or out of range', wwv2 => 'Duplicate WWV', wwvs => 'WWV enabled for $_[0]', diff --git a/perl/Msg.pm b/perl/Msg.pm index c3637fb0..00569928 100644 --- a/perl/Msg.pm +++ b/perl/Msg.pm @@ -217,7 +217,6 @@ sub connect { my $ip = gethostbyname($to_host); return undef unless $ip; -# my $r = $sock->connect($to_port, $ip); my $r = connect($sock, pack_sockaddr_in($to_port, $ip)); return undef unless $r || _err_will_block($!); -- 2.34.1