File Coverage

blib/lib/Parse/Netstat/linux.pm
Criterion Covered Total %
statement 35 35 100.0
branch 10 14 71.4
condition 12 15 80.0
subroutine 6 6 100.0
pod 1 1 100.0
total 64 71 90.1


line stmt bran cond sub pod time code
1             package Parse::Netstat::linux;
2              
3 1     1   19 use 5.010001;
  1         4  
4 1     1   5 use strict;
  1         2  
  1         21  
5 1     1   4 use warnings;
  1         2  
  1         26  
6              
7 1     1   8 use Exporter 'import';
  1         3  
  1         365  
8              
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2022-12-04'; # DATE
11             our $DIST = 'Parse-Netstat'; # DIST
12             our $VERSION = '0.150'; # VERSION
13              
14             our @EXPORT_OK = qw(parse_netstat);
15              
16             our %SPEC;
17              
18             $SPEC{parse_netstat} = {
19             v => 1.1,
20             summary => 'Parse the output of Linux "netstat" command',
21             description => <<'_',
22              
23             Netstat can be called with `-n` (show raw IP addresses and port numbers instead
24             of hostnames or port names) or without. It can be called with `-a` (show all
25             listening and non-listening socket) option or without. And can be called with
26             `-p` (show PID/program names) or without.
27              
28             _
29             args => {
30             output => {
31             summary => 'Output of netstat command',
32             schema => 'str*',
33             req => 1,
34             },
35             tcp => {
36             summary => 'Whether to parse TCP (and TCP6) connections',
37             schema => [bool => default => 1],
38             },
39             udp => {
40             summary => 'Whether to parse UDP (and UDP6) connections',
41             schema => [bool => default => 1],
42             },
43             unix => {
44             summary => 'Whether to parse Unix socket connections',
45             schema => [bool => default => 1],
46             },
47             },
48             };
49             sub parse_netstat {
50 4     4 1 12 my %args = @_;
51 4 50       10 my $output = $args{output} or return [400, "Please specify output"];
52 4   50     11 my $tcp = $args{tcp} // 1;
53 4   50     9 my $udp = $args{udp} // 1;
54 4   50     8 my $unix = $args{unix} // 1;
55              
56 4         8 my $in_unix;
57             my $in_unix_header;
58 4         0 my @conns;
59 4         6 my $i = 0;
60 4         74 for my $line (split /^/, $output) {
61 84         105 $i++;
62 84         109 my %k;
63 84 100 100     374 if ($line =~ /^tcp/ && $tcp) {
    100 100        
    100 100        
64             #Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
65             #tcp 0 0 0.0.0.0:8898 0.0.0.0:* LISTEN 5566/daemon2.pl [pa
66 30 50       212 $line =~ m!^(?Ptcp[46]?) \s+ (?P\d+) \s+ (?P\d+)\s+
67             (?P\S+?):(?P\w+)\s+
68             (?P\S+?):(?P\w+|\*)\s+
69             (?P\S+) (?: \s+ (?:
70             (?P\d+)/(?P.+?) |
71             -
72             ))? \s*$!x
73             or return [400, "Can't parse tcp line (#$i): $line"];
74 1     1   430 %k = %+;
  1         351  
  1         320  
  30         541  
75             } elsif ($line =~ /^udp/ && $udp) {
76             #udp 0 0 0.0.0.0:631 0.0.0.0:* 2769/cupsd
77 12 50       86 $line =~ m!^(?Pudp[46]?) \s+ (?P\d+) \s+ (?P\d+) \s+
78             (?P\S+?):(?P\w+|\*)\s+
79             (?P\S+?):(?P\w+|\*)
80             (?: \s+
81             (?P\S+)?
82             (?: \s+ (?:
83             (?P\d+)/(?P.+?) |
84             -
85             ))?
86             )? \s*$!x
87             or return [400, "Can't parse udp line (#$i): $line"];
88 12         264 %k = %+;
89             } elsif ($line =~ /^unix/ && $unix) {
90             #Proto RefCnt Flags Type State I-Node PID/Program name Path
91             # unix 2 [ ACC ] STREAM LISTENING 650654 30463/gconfd-2 /tmp/orbit-t1/linc-76ff-0-3fc1dd3f2f2
92 9 50       91 $line =~ m!^(?Punix) \s+ (?P\d+) \s+
93             \[\s*(?P\S*)\s*\] \s+ (?P\S+) \s+
94             (?P\S+|\s+) \s+ (?P\d+) \s+
95             (?: (?: (?P\d+)/(?P.+?) | - ) \s+)?
96             (?P.*?)\s*$!x
97             or return [400, "Can't parse unix line (#$i): $line"];
98 9         159 %k = %+;
99             } else {
100 33         54 next;
101             }
102 51         241 push @conns, \%k;
103             }
104              
105 4         32 [200, "OK", {active_conns => \@conns}];
106             }
107              
108             1;
109             # ABSTRACT: Parse the output of Linux "netstat" command
110              
111             __END__