#!/usr/bin/perl -p # save-combine - filter and combine output from ipset(1) save # Copyright (C)2026 Corwin Brust # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # ################# # # Use a flat-file "DB" of ipset per row in the form NAME MAX # Take DB file-name from first program arg, otherwise "ipset-counts.txt" # Drop create/add lines for any set not mentioned in the DB # Input is expected on stdin in the same format as output by ipset save # ################# sub usage { my $message = shift; $message .= "\n" if $message; die <fil && \\ $0 [max-count-file] $val; return $rv; } BEGIN # program is a filter so we must wrap start-up processing { # avoid extra "BEGIN faile--" messages local $SIG{__DIE__} = sub {warn @_; exit 1}; # display usage if requested usage() if grep /^-+[?h]/, @ARGV; # and unless we have input die usage( qq(ERROR: STDIN is non a pipe or redirection) ) if -t STDIN; # take max-count-file from args, if any my $SET_COUNTS = @ARGV ? shift : q(max-counts.txt); open my$FH,q(<),$SET_COUNTS or usage( q(ERROR: cannot open max-count-file) . qq( "$SET_COUNTS": $!) . ' ('.(0+$!).')' ); # load hash of set => max while(<$FH>) { chomp; my( $k, $v ) = split; $m{ $k } = max2( $v ) if $k and $v } } if( /^create (\S+)/ ) { if( exists $h{$1} ) { # check if create issued $_ = ''; # don't print again } elsif( exists $m{ $1 } ) { $h{$1} = 1; # ensure this is the only printing $n = $1; # grab the name $v = $m{$n}; # lookup max # mangle the create to inject maxelem from DB s/^create $n (.*?maxelem) \d+ (.*)$/create $n $1 $v $2/ #and warn qq[set $n=$v] } else { $_ = ''; # skip create when no max defined } } elsif( /^add (\S+)/ ) { # $_ = '' unless exists $m{$1}; if (exists $m{$1}) { s/$/ -exist/; # make dup-safe } else { $_ = ''; # skip add for set we cannot create } }