Repository
Munin (contrib)
Last change
2020-10-24
Graph Categories
Family
auto
Capabilities
Keywords
Language
Perl

pf_tables_

Name

pf_tables : Munin plugin to monitor pf tables. Inout: bandwidth usage for table Addresses: number of entries in table

Applicable Systems

Should work on any BSD that has pf(4).

Examples:

  • pf_tables_inout_tablename
  • pf_tables_addresses_authenticated
  • pf_tables_addresses_badboys

Configuration

[pf_tables_*]
user root

Interpretation

The plugin simply runs the pfctl -sTables -vvv command and counts the number of Addresses and InBytes/OutBytes in each table.

Bugs

Only tested extensively on FreeBSD.

Magic Markers

#%# family=auto
#%# capabilities=autoconf suggest

Version

$Id$

Author

Copyright (C) 2015.

Original version by Luc Duchosal (at) arcantel (dot) ch. Created by Luc Duchosal, 2015

License

BSD

Pod Errors

Hey! The above document had some coding errors, which are explained below:

  • Around line 28:

    You forgot a ‘=back’ before ‘=head1’

#!/usr/bin/perl -w
# -*- perl -*-

=head1 NAME

pf_tables : Munin plugin to monitor pf tables.
Inout: bandwidth usage for table
Addresses: number of entries in table


=head1 APPLICABLE SYSTEMS

Should work on any BSD that has pf(4).

Examples:

=over

=item pf_tables_inout_tablename

=item pf_tables_addresses_authenticated

=item pf_tables_addresses_badboys


=head1 CONFIGURATION

  [pf_tables_*]
  user root

=head1 INTERPRETATION

The plugin simply runs the pfctl -sTables -vvv command and counts the number of
Addresses and InBytes/OutBytes in each table.

=head1 BUGS

Only tested extensively on FreeBSD.

=head1 MAGIC MARKERS

  #%# family=auto
  #%# capabilities=autoconf suggest

=head1 VERSION

  $Id$

=head1 AUTHOR

Copyright (C) 2015.

Original version by Luc Duchosal (at) arcantel (dot) ch.
Created by Luc Duchosal, 2015

=head1 LICENSE

BSD

=cut


use strict;
use Munin::Plugin;

$0 =~ /pf_tables_(addresses|inout)_(.+)$/;
my $name = $2;
my $operation = $1;

if ( defined($ARGV[0])) {
    if ($ARGV[0] eq 'autoconf') {
        print "yes\n";
        exit 0;
    }

    if ($ARGV[0] eq "config") {

        if (!defined($name)) {
            print "Unknown table\n";
            exit 0;
        }

        if (!defined($operation)) {
            print "Unknown operation\n";
            exit 0;
        }

        if ($operation =~ m/addresses/) {

            print "graph_title Connected users ($name)\n";
            print "graph_args --base 1000 -l 0\n";
            print "graph_vlabel Users\n";
            print "graph_scale no\n";
            print "graph_category network\n";
            print "graph_printf %3.0lf\n";

            print "users.label users\n";
            print "users.draw AREASTACK\n";
            print "users.colour 00C000\n";
            foreach my $field (qw(users)) {
                print_thresholds($field);
            }
        }

        if ($operation =~ m/inout/) {

            print "graph_title Network bandwidth ($name)\n";
            print "graph_args --base 1024 -l 0\n";
            print "graph_vlabel Bandwidth\n";
            print "graph_scale yes\n";
            print "graph_category network\n";
#            print "graph_printf %3.0lf\n";

            print "in.label in\n";
            print "in.type DERIVE\n";
            print "in.draw AREA\n";
            print "in.colour C00000\n";
            print "in.cdef in,8,*\n";
            print "in.min 0\n";
            print "in.graph no\n";
            print "out.label bps\n";
            print "out.type DERIVE\n";
            print "out.negative in\n";
            print "out.draw AREA\n";
            print "out.colour COLOUR18\n";
            print "out.cdef out,8,*\n";
            print "out.min 0\n";

            foreach my $field (qw(in out)) {
                print_thresholds($field);
            }

        }
        exit 0;
    }

    if ($ARGV[0] eq "suggest") {
        my %tables = &tables();
        foreach my $key (keys(%tables)) {
            print "addresses_$key\n";
            print "inout_$key\n";
        }
        exit 0;
    }

}

if (!defined($name)) {
    print "Usage: pf_tables_addresses_tablename or pf_tables_inout_tablename\n";
    exit 1;
}

my %tables = &tables();
if (!exists $tables{$name}) {
   print "Unknown table name $name\n";
   exit 2;
}

if ($operation =~ m/addresses/) {
    my $users = $tables{$name}->{"addresses"};
    print "users.value $users\n";
}

if ($operation =~ m/inout/) {
    my $in = $tables{$name}->{"inpassbytes"};
    my $out = $tables{$name}->{"outpassbytes"};
    print "in.value $in\n";
    print "out.value $out\n";
}


sub tables {

    # # pfctl -s Tables -vv
    # -pa-r-- auth
    #         Addresses:   0
    #         Cleared:     Fri Sep 18 17:34:42 2015
    #         References:  [ Anchors: 0                  Rules: 14                 ]
    #         Evaluations: [ NoMatch: 43624              Match: 788                ]
    #         In/Block:    [ Packets: 0                  Bytes: 0                  ]
    #         In/Pass:     [ Packets: 30908              Bytes: 2704516            ]
    #         In/XPass:    [ Packets: 124                Bytes: 7897               ]
    #         Out/Block:   [ Packets: 0                  Bytes: 0                  ]
    #         Out/Pass:    [ Packets: 30288              Bytes: 26313114           ]
    #         Out/XPass:   [ Packets: 89                 Bytes: 21166              ]

    my $output = `/sbin/pfctl -s Tables -vv 2> /dev/null`;
    my %tables;
    my $name;

    foreach (split(/\n/, $output)) {

       if (m|^[cpairhC\-]{7}\s+(\S+)$|) {
          $name = $1;
		  $name =~ s/\-/_/;
          $tables{$name}->{"name"} = $name;
          next;
       }

       if (m|Addresses:\s+([0-9]+)$|) {
          $tables{$name}->{"addresses"} = $1;
          next;
       }

       if (m|Cleared:\s+(.+)$|) {
          $tables{$name}->{"cleared"} = $1;
          next;
       }

       if (m|In/Block:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
          $tables{$name}->{"inblockpackets"} = $1;
          $tables{$name}->{"inblockbytes"} = $2;
          next;
       }

       if (m|In/Pass:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
          $tables{$name}->{"inpasspackets"} = $1;
          $tables{$name}->{"inpassbytes"} = $2;
          next;
       }

       if (m|In/XPass:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
          $tables{$name}->{"inxpasspackets"} = $1;
          $tables{$name}->{"inxpassbytes"} = $2;
          next;
       }

       if (m|Out/Block:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
          $tables{$name}->{"outblockpackets"} = $1;
          $tables{$name}->{"outblockbytes"} = $2;
          next;
       }

       if (m|Out/Pass:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
          $tables{$name}->{"outpasspackets"} = $1;
          $tables{$name}->{"outpassbytes"} = $2;
          next;
       }

       if (m|Out/XPass:\s+\[\s+Packets:\s+([0-9]+)\s+Bytes:\s+([0-9]+)\s+\]$|) {
          $tables{$name}->{"outxpasspackets"} = $1;
          $tables{$name}->{"outxpassbytes"} = $2;
          next;
       }

    }

    return %tables;

}

# vim:syntax=perl