summaryrefslogtreecommitdiffstats
path: root/net_if
blob: 4b392b9245cd56d6d520d1080c9ef9b8e815840e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/perl -T

use warnings;
use strict;

$ENV{'PATH'} = '/bin:/usr/bin:/sbin:/usr/sbin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

# define nagios status codes
my %nagios = (
    'ok' => ["OK", 0],
    'warn' => ["WARNING", 1],
    'crit' => ["CRITICAL", 2],
    'unknown' => ["UNKNOWN", 3]
);

# Print nagios compatible status message and terminat script
# with apropiate return code.
#
# parameter: type of message
sub msg ($@) {
    my $type = shift;
    my ($msg, $exit) = @{$nagios{$type}};

    print $msg, " - ", @_, "\n";
    exit $exit;
}

# Check the status of the given network interface and return
# three lists the interfaces sorted by status (up, down, error).
# This resolves interfaces groups, but only return the interfaces
# that are up.
#
# parameter: list of interfaces
sub get_if_status (@) {
    my (@up, @down, @error);

    while (@_) {
        my $if = shift @_;
        next unless ($if =~ m/^([-\w]+)$/);
        $if = $1;

        my $pid = open(IFCONFIG, "-|");
        msg('crit', "fork: $!") unless defined $pid;

        if ($pid == 0) {
            # child
            open(STDERR, ">", "/dev/null");
            exec("ifconfig", $if)
        }

        while (<IFCONFIG>) {
            if ($_ =~ m/^([-a-v0-9]+): flags=([0-9]+)</) {
                if ($2 & 1) {
                    push(@up, $1);
                }
                else {
                    push (@down, $if) if $1 eq $if;
                }
            }
        }

        close(IFCONFIG) or push(@error, $if);
    }

    return (\@up, \@down, \@error);
}

# Get the byte conters for incomming and outgoing packages.
#
# parameter: interface name
sub get_if_stats ($) {
    my $if = shift;
    my $stats = {};

    open(PFCTL, "-|", "pfctl", "-vvsI", "-i", $if);
    while (<PFCTL>) {
        if ($_ =~ m{In4/Pass.*Bytes: ([0-9]+)}) {
            $stats->{'in4'} = $1;
        }
        elsif ($_ =~ m{Out4/Pass.*Bytes: ([0-9]+)}) {
            $stats->{'out4'} = $1;
        }
        elsif ($_ =~ m{In6/Pass.*Bytes: ([0-9]+)}) {
            $stats->{'in6'} = $1;
        }
        elsif ($_ =~ m{Out6/Pass.*Bytes: ([0-9]+)}) {
            $stats->{'out6'} = $1;
        }
    }
    close(PFCTL);

    return $stats;
}

# Print nagios compatible message containing the number of interfaces
# and performance data containing the byte counter for the interfaces.
sub print_stats ($) {
    my $stats = shift;
    my ($count, $perfdata);

    $count = keys %$stats;
    $perfdata = "";
    for my $if (keys %$stats) {
        for (qw( in4 out4 in6 out6 )) {
            $perfdata = "$perfdata $if-$_=$stats->{$if}->{$_};";
        }
    }

    msg('ok', "$count interfaces |$perfdata");
}


my ($up, $down, $error) = get_if_status(@ARGV);

if (@$error) {
    $error = join ", ", @$error;
    msg('crit', "Some interfaces does not exists: $error");
}

if (@$down) {
    $down = join ", ", @$down;
    msg('warn', "Some interfaces are down: $down");
}

my $stats = {};
for my $if (@$up) {
    $stats->{$if} = get_if_stats($if);
}

print_stats($stats);