diff --git a/mxrouter/mxrouterctl b/mxrouter/mxrouterctl index ecc6a44..9713586 100755 --- a/mxrouter/mxrouterctl +++ b/mxrouter/mxrouterctl @@ -316,6 +316,56 @@ sub configure_vlans { } } +my $want_ipsets; # { name => [type,filename,create-options]) , ... } + +sub ipset { + my ($name,$type,$filename,@options)=@_; + $want_ipsets->{$name}=[$type,$filename,@options]; +} + +sub read_active_ipsets { + my $active_ipsets; # { $name => 1 , ... ) + open my $p,'-|','ipset','--list','-n' or die "$!"; + while (<$p>) { + chomp; + $active_ipsets->{$_}=1; + } + return $active_ipsets; +} + +sub unconfigure_ipsets { + my ($have_ipsets)=@_; + for my $name (sort keys %$have_ipsets) { + sys('ipset','destroy',$name); + } +} + +sub configure_ipsets { + my ($want_ipsets)=@_; + for my $name (sort keys %$want_ipsets) { + my ($type,$filename,@options)=@{$want_ipsets->{$name}}; + sys('ipset','create',$name,$type,@options); + } +} +sub reload_ipsets { + my ($want_ipsets)=@_; + for my $name (sort keys %$want_ipsets) { + my ($type,$filename,@options)=@{$want_ipsets->{$name}}; + my $tmp="$name-TMP"; + warn "read ipset $name from $filename\n"; + system('ipset','create',$tmp,$type,@options) and exit 1; + $type eq 'hash:ip' or die "read ipset type $type from file not implemented\n"; + open my $in,'<',$filename or die "$filename: $!\n"; + while (<$in>) { + s/#.*//; + /^\s*(\d+\.\d+\.\d+\.\d+)\s*$/ or next; + system('ipset','add',$tmp,$1) and exit 1; + } + system('ipset','swap',$name,$tmp) and exit 1; + system('ipset','destroy',$tmp) and exit 1; + } +} + our %radvd; # ( 'net03' => 'AdvSendAdvert on;prefix 2a02:d480:e08:20::/64;' , ...) sub radvd { @@ -358,17 +408,8 @@ sub disable_ipv4_rp_filter { $disable_ipv4_rp_filter{$if}=1; } -sub reload_ip_blacklist { - sys('ipset','flush','ip-blacklist'); - if (-e '/etc/local/mxrouter/ip-blacklist') { - open my $in,'<','/etc/local/mxrouter/ip-blacklist' or die "/etc/local/mxrouter/ip-blacklist: $!\n"; - while (<$in>) { - s/#.*//; - /^\s*(\d+\.\d+\.\d+\.\d+)\s*$/ or next; - system('ipset','add','ip-blacklist',$1); - } - } -} + + sub start { @@ -494,6 +535,17 @@ sub start { set_ipv4_routing(1); } + my $have_ipsets=read_active_ipsets(); + my ($new_ipsets,$del_ipsets)=({},{}); + for (keys %$want_ipsets) { + $new_ipsets->{$_}=$want_ipsets->{$_} + unless exists $have_ipsets->{$_}; + } + for (keys %$have_ipsets) { + $del_ipsets->{$_} = $have_ipsets->{$_} + unless exists $want_ipsets->{$_}; + } + stop_process_if($process_ulogd); stop_process_if($process_dhcrelay); stop_process_if($process_radvd); @@ -530,14 +582,15 @@ sub start { start_process_if($process_dhcrelay); start_process_if($process_radvd); + configure_ipsets($new_ipsets); unless ($opt_noop) { - sys('ipset','create','-exist','ip-blacklist','hash:ip','counters'); - reload_ip_blacklist(); open my $pipe,'|-','iptables-restore' or die "$!\n"; print $pipe rules_in_restore_format(); close $pipe or die "$!\n"; $? and exit 1; } + unconfigure_ipsets($del_ipsets); + reload_ipsets($want_ipsets); } sub move_dev_into_ns {