| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # | 
| 2 |  |  |  |  |  |  | # (c) Jan Gehring | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | package Rex::Hardware::Network::Linux; | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 6 |  |  | 6 |  | 179524 | use v5.12.5; | 
|  | 6 |  |  |  |  | 55 |  | 
| 8 | 6 |  |  | 6 |  | 55 | use warnings; | 
|  | 6 |  |  |  |  | 24 |  | 
|  | 6 |  |  |  |  | 452 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | our $VERSION = '1.14.3'; # VERSION | 
| 11 |  |  |  |  |  |  |  | 
| 12 | 6 |  |  | 6 |  | 1267 | use Rex::Logger; | 
|  | 6 |  |  |  |  | 28 |  | 
|  | 6 |  |  |  |  | 128 |  | 
| 13 | 6 |  |  | 6 |  | 1171 | use Rex::Helper::Run; | 
|  | 6 |  |  |  |  | 24 |  | 
|  | 6 |  |  |  |  | 644 |  | 
| 14 | 6 |  |  | 6 |  | 63 | use Rex::Commands::Run; | 
|  | 6 |  |  |  |  | 20 |  | 
|  | 6 |  |  |  |  | 128 |  | 
| 15 | 6 |  |  | 6 |  | 45 | use Rex::Helper::Array; | 
|  | 6 |  |  |  |  | 24 |  | 
|  | 6 |  |  |  |  | 413 |  | 
| 16 | 6 |  |  | 6 |  | 58 | use Data::Dumper; | 
|  | 6 |  |  |  |  | 35 |  | 
|  | 6 |  |  |  |  | 15167 |  | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | sub get_bridge_devices { | 
| 19 | 9 | 50 |  | 9 | 0 | 215 | unless ( can_run("brctl") ) { | 
| 20 | 9 |  |  |  |  | 318 | Rex::Logger::debug("No brctl available"); | 
| 21 | 9 |  |  |  |  | 156 | return {}; | 
| 22 |  |  |  |  |  |  | } | 
| 23 |  |  |  |  |  |  |  | 
| 24 | 0 |  |  |  |  | 0 | local $/ = "\n"; | 
| 25 | 0 |  |  |  |  | 0 | my @lines = i_run 'brctl show', fail_ok => 1; | 
| 26 | 0 |  |  |  |  | 0 | chomp @lines; | 
| 27 | 0 |  |  |  |  | 0 | shift @lines; | 
| 28 |  |  |  |  |  |  |  | 
| 29 | 0 |  |  |  |  | 0 | my $current_bridge; | 
| 30 | 0 |  |  |  |  | 0 | my $data = {}; | 
| 31 | 0 |  |  |  |  | 0 | for my $line (@lines) { | 
| 32 | 0 | 0 |  |  |  | 0 | if ( $line =~ m/^[A-Za-z0-9_.]+/ ) { | 
| 33 | 0 |  |  |  |  | 0 | my ( $br, $br_id, $stp, $dev ) = split( /\s+/, $line ); | 
| 34 | 0 |  |  |  |  | 0 | $current_bridge = $br; | 
| 35 | 0 |  |  |  |  | 0 | $data->{$br}->{stp} = 0; | 
| 36 | 0 |  |  |  |  | 0 | push @{ $data->{$br}->{devices} }, $dev; | 
|  | 0 |  |  |  |  | 0 |  | 
| 37 | 0 |  |  |  |  | 0 | next; | 
| 38 |  |  |  |  |  |  | } | 
| 39 |  |  |  |  |  |  |  | 
| 40 | 0 |  |  |  |  | 0 | my ($dev) = ( $line =~ m/([a-zA-Z0-9_.]+)$/ ); | 
| 41 | 0 | 0 |  |  |  | 0 | if ($dev) { | 
| 42 | 0 |  |  |  |  | 0 | push @{ $data->{$current_bridge}->{devices} }, $dev; | 
|  | 0 |  |  |  |  | 0 |  | 
| 43 |  |  |  |  |  |  | } | 
| 44 |  |  |  |  |  |  | } | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 0 |  |  |  |  | 0 | return $data; | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | sub get_network_devices { | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 9 | 50 |  | 9 | 0 | 104 | my $command = can_run('ip') ? 'ip addr show' : 'ifconfig -a'; | 
| 52 | 9 |  |  |  |  | 206 | my @output  = i_run( "$command", fail_ok => 1 ); | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 9 | 50 |  |  |  | 308 | my $devices = | 
| 55 |  |  |  |  |  |  | ( $command eq 'ip addr show' ) | 
| 56 |  |  |  |  |  |  | ? _parse_ip(@output) | 
| 57 |  |  |  |  |  |  | : _parse_ifconfig(@output); | 
| 58 | 9 |  |  |  |  | 46 | my @device_list = keys %{$devices}; | 
|  | 9 |  |  |  |  | 109 |  | 
| 59 |  |  |  |  |  |  |  | 
| 60 | 9 |  |  |  |  | 517 | return \@device_list; | 
| 61 |  |  |  |  |  |  | } | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | sub get_network_configuration { | 
| 64 |  |  |  |  |  |  |  | 
| 65 | 9 |  |  | 9 | 0 | 71 | my $device_info = {}; | 
| 66 |  |  |  |  |  |  |  | 
| 67 | 9 | 50 |  |  |  | 183 | my $command = can_run('ip') ? 'ip addr show' : 'ifconfig -a'; | 
| 68 | 9 |  |  |  |  | 157 | my @output  = i_run( "$command", fail_ok => 1 ); | 
| 69 |  |  |  |  |  |  |  | 
| 70 | 9 |  |  |  |  | 176 | my $br_data = get_bridge_devices(); | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 9 | 50 |  |  |  | 238 | my $data = | 
| 73 |  |  |  |  |  |  | ( $command eq 'ip addr show' ) | 
| 74 |  |  |  |  |  |  | ? _parse_ip(@output) | 
| 75 |  |  |  |  |  |  | : _parse_ifconfig(@output); | 
| 76 |  |  |  |  |  |  |  | 
| 77 | 9 |  |  |  |  | 36 | for my $dev ( keys %{$data} ) { | 
|  | 9 |  |  |  |  | 151 |  | 
| 78 | 27 | 50 |  |  |  | 230 | if ( exists $br_data->{$dev} ) { | 
| 79 | 0 |  |  |  |  | 0 | $data->{$dev}->{is_bridge} = 1; | 
| 80 |  |  |  |  |  |  | } | 
| 81 |  |  |  |  |  |  | else { | 
| 82 | 27 |  |  |  |  | 113 | $data->{$dev}->{is_bridge} = 0; | 
| 83 |  |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  | } | 
| 85 |  |  |  |  |  |  |  | 
| 86 | 9 |  |  |  |  | 271 | return $data; | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | sub _parse_ifconfig { | 
| 90 | 4 |  |  | 4 |  | 8797 | my (@ifconfig) = @_; | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 4 |  |  |  |  | 9 | my $dev = {}; | 
| 93 |  |  |  |  |  |  |  | 
| 94 | 4 |  |  |  |  | 6 | my $cur_dev; | 
| 95 | 4 |  |  |  |  | 9 | for my $line (@ifconfig) { | 
| 96 | 49 | 100 |  |  |  | 86 | if ( $line =~ m/^([a-zA-Z0-9:\._]+)/ ) { | 
| 97 | 6 |  |  |  |  | 15 | my $new_dev = $1; | 
| 98 | 6 | 100 |  |  |  | 72 | $new_dev = substr( $new_dev, 0, -1 ) if ( $new_dev =~ m/:$/ ); | 
| 99 |  |  |  |  |  |  |  | 
| 100 | 6 | 100 | 66 |  |  | 19 | if ( $cur_dev && $cur_dev ne $new_dev ) { | 
| 101 | 2 |  |  |  |  | 3 | $cur_dev = $new_dev; | 
| 102 |  |  |  |  |  |  | } | 
| 103 |  |  |  |  |  |  |  | 
| 104 | 6 | 100 |  |  |  | 24 | if ( !$cur_dev ) { | 
| 105 | 4 |  |  |  |  | 8 | $cur_dev = $new_dev; | 
| 106 |  |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  |  | 
| 108 | 6 |  |  |  |  | 15 | $dev->{$cur_dev}->{mac}       = ""; | 
| 109 | 6 |  |  |  |  | 8 | $dev->{$cur_dev}->{ip}        = ""; | 
| 110 | 6 |  |  |  |  | 8 | $dev->{$cur_dev}->{netmask}   = ""; | 
| 111 | 6 |  |  |  |  | 11 | $dev->{$cur_dev}->{broadcast} = ""; | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 49 | 100 |  |  |  | 149 | if ( $line =~ m/(ether|HWaddr) (..:..:..:..:..:..)/ ) { | 
| 116 | 4 |  |  |  |  | 10 | $dev->{$cur_dev}->{mac} = $2; | 
| 117 |  |  |  |  |  |  | } | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 49 | 100 |  |  |  | 79 | if ( $line =~ m/inet( addr:| )?(\d+\.\d+\.\d+\.\d+)/ ) { | 
| 120 | 5 |  |  |  |  | 9 | $dev->{$cur_dev}->{ip} = $2; | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 49 | 100 |  |  |  | 93 | if ( $line =~ m/(netmask |Mask:)(\d+\.\d+\.\d+\.\d+)/ ) { | 
| 124 | 5 |  |  |  |  | 11 | $dev->{$cur_dev}->{netmask} = $2; | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  |  | 
| 127 | 49 | 100 |  |  |  | 92 | if ( $line =~ m/(broadcast |Bcast:)(\d+\.\d+\.\d+\.\d+)/ ) { | 
| 128 | 3 |  |  |  |  | 7 | $dev->{$cur_dev}->{broadcast} = $2; | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | } | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 4 |  |  |  |  | 17 | return $dev; | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | sub _parse_ip { | 
| 138 | 24 |  |  | 24 |  | 11004 | my (@ip_lines) = @_; | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 24 |  |  |  |  | 132 | my $dev = {}; | 
| 141 |  |  |  |  |  |  |  | 
| 142 | 24 |  |  |  |  | 61 | my $cur_dev; | 
| 143 | 24 |  |  |  |  | 160 | for my $line (@ip_lines) { | 
| 144 | 191 | 100 |  |  |  | 981 | if ( $line =~ m/^\d+:\s*([^\s]+):/ ) { | 
| 145 | 45 |  |  |  |  | 426 | my $new_dev = $1; | 
| 146 |  |  |  |  |  |  |  | 
| 147 | 45 | 100 | 66 |  |  | 354 | if ( $cur_dev && $cur_dev ne $new_dev ) { | 
| 148 | 21 |  |  |  |  | 91 | $cur_dev = $new_dev; | 
| 149 |  |  |  |  |  |  | } | 
| 150 |  |  |  |  |  |  |  | 
| 151 | 45 | 100 |  |  |  | 129 | if ( !$cur_dev ) { | 
| 152 | 24 |  |  |  |  | 144 | $cur_dev = $new_dev; | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 45 |  |  |  |  | 439 | $dev->{$cur_dev}->{ip}        = ""; | 
| 156 | 45 |  |  |  |  | 198 | $dev->{$cur_dev}->{mac}       = ""; | 
| 157 | 45 |  |  |  |  | 195 | $dev->{$cur_dev}->{netmask}   = ""; | 
| 158 | 45 |  |  |  |  | 167 | $dev->{$cur_dev}->{broadcast} = ""; | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 45 |  |  |  |  | 154 | next; | 
| 161 |  |  |  |  |  |  | } | 
| 162 |  |  |  |  |  |  |  | 
| 163 | 146 | 100 |  |  |  | 449 | if ( $line =~ m/^\s*link\/ether (..:..:..:..:..:..)/ ) { | 
| 164 | 23 |  |  |  |  | 101 | $dev->{$cur_dev}->{mac} = $1; | 
| 165 |  |  |  |  |  |  | } | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | # loopback | 
| 168 |  |  |  |  |  |  | #    if ( $line =~ m/^\s*inet (\d+\.\d+\.\d+\.\d+)\/(\d+) scope host lo/ ) { | 
| 169 |  |  |  |  |  |  | #      $dev->{$cur_dev}->{ip}      = $1; | 
| 170 |  |  |  |  |  |  | #      $dev->{$cur_dev}->{netmask} = _convert_cidr_prefix($2); | 
| 171 |  |  |  |  |  |  | #    } | 
| 172 |  |  |  |  |  |  |  | 
| 173 | 146 |  |  |  |  | 235 | my $sec_i = 1; | 
| 174 | 146 | 100 |  |  |  | 719 | if ( $line =~ | 
| 175 |  |  |  |  |  |  | m/^\s*inet (\d+\.\d+\.\d+\.\d+)\/(\d+) (brd (\d+\.\d+\.\d+\.\d+) )?scope ([^\s]+) (\w+\s)?(.+?)$/ | 
| 176 |  |  |  |  |  |  | ) | 
| 177 |  |  |  |  |  |  | { | 
| 178 | 45 |  |  |  |  | 148 | my $ip          = $1; | 
| 179 | 45 |  |  |  |  | 235 | my $cidr_prefix = $2; | 
| 180 | 45 |  | 100 |  |  | 570 | my $broadcast   = $4 || ''; | 
| 181 | 45 |  |  |  |  | 354 | my $scope       = $5; | 
| 182 | 45 |  | 33 |  |  | 249 | my $dev_name    = $7 || $6; | 
| 183 | 45 |  |  |  |  | 123 | chomp $dev_name; | 
| 184 |  |  |  |  |  |  |  | 
| 185 | 45 | 100 | 100 |  |  | 480 | if ( $scope eq "global" && $dev_name ne $cur_dev ) { | 
|  |  | 100 | 33 |  |  |  |  | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | # this is an alias | 
| 188 | 19 |  |  |  |  | 163 | $dev->{$dev_name}->{ip}        = $ip; | 
| 189 | 19 |  |  |  |  | 57 | $dev->{$dev_name}->{broadcast} = $broadcast; | 
| 190 | 19 |  |  |  |  | 93 | $dev->{$dev_name}->{netmask}   = _convert_cidr_prefix($cidr_prefix); | 
| 191 | 19 |  |  |  |  | 109 | $dev->{$dev_name}->{mac}       = $dev->{$cur_dev}->{mac}; | 
| 192 |  |  |  |  |  |  | } | 
| 193 |  |  |  |  |  |  | elsif ( $dev_name eq $cur_dev && $dev->{$cur_dev}->{ip} ) { | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | # there is already an ip address, so this must be a secondary | 
| 196 | 1 |  |  |  |  | 5 | $dev->{"${dev_name}_${sec_i}"}->{ip}        = $ip; | 
| 197 | 1 |  |  |  |  | 5 | $dev->{"${dev_name}_${sec_i}"}->{broadcast} = $broadcast; | 
| 198 |  |  |  |  |  |  | $dev->{"${dev_name}_${sec_i}"}->{netmask} = | 
| 199 | 1 |  |  |  |  | 2 | _convert_cidr_prefix($cidr_prefix); | 
| 200 | 1 |  |  |  |  | 3 | $dev->{"${dev_name}_${sec_i}"}->{mac} = $dev->{$cur_dev}->{mac}; | 
| 201 | 1 |  |  |  |  | 2 | $sec_i++; | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  | else { | 
| 204 | 25 |  |  |  |  | 123 | $dev->{$cur_dev}->{ip}        = $ip; | 
| 205 | 25 |  |  |  |  | 81 | $dev->{$cur_dev}->{broadcast} = $broadcast; | 
| 206 | 25 |  |  |  |  | 127 | $dev->{$cur_dev}->{netmask}   = _convert_cidr_prefix($cidr_prefix); | 
| 207 |  |  |  |  |  |  | } | 
| 208 |  |  |  |  |  |  | } | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  | # ppp | 
| 211 | 146 | 100 |  |  |  | 465 | if ( $line =~ | 
| 212 |  |  |  |  |  |  | m/^\s*inet (\d+\.\d+\.\d+\.\d+) peer (\d+\.\d+\.\d+\.\d+)\/(\d+)/ ) | 
| 213 |  |  |  |  |  |  | { | 
| 214 | 1 |  |  |  |  | 13 | $dev->{$cur_dev}->{ip}      = $1; | 
| 215 | 1 |  |  |  |  | 3 | $dev->{$cur_dev}->{netmask} = _convert_cidr_prefix($3); | 
| 216 |  |  |  |  |  |  | } | 
| 217 |  |  |  |  |  |  | } | 
| 218 |  |  |  |  |  |  |  | 
| 219 | 24 |  |  |  |  | 112 | return $dev; | 
| 220 |  |  |  |  |  |  | } | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  | sub route { | 
| 223 |  |  |  |  |  |  |  | 
| 224 | 0 |  |  | 0 | 0 | 0 | my @ret = (); | 
| 225 |  |  |  |  |  |  |  | 
| 226 | 0 |  |  |  |  | 0 | my @route = i_run "netstat -nr", fail_ok => 1; | 
| 227 | 0 | 0 |  |  |  | 0 | if ( $? != 0 ) { | 
| 228 | 0 |  |  |  |  | 0 | die("Error running netstat"); | 
| 229 |  |  |  |  |  |  | } | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 0 |  |  |  |  | 0 | shift @route; | 
| 232 | 0 |  |  |  |  | 0 | shift @route; # remove first 2 lines | 
| 233 |  |  |  |  |  |  |  | 
| 234 | 0 |  |  |  |  | 0 | for my $route_entry (@route) { | 
| 235 | 0 |  |  |  |  | 0 | my ( $dest, $gw, $genmask, $flags, $mss, $window, $irtt, $iface ) = | 
| 236 |  |  |  |  |  |  | split( /\s+/, $route_entry, 8 ); | 
| 237 | 0 |  |  |  |  | 0 | push( | 
| 238 |  |  |  |  |  |  | @ret, | 
| 239 |  |  |  |  |  |  | { | 
| 240 |  |  |  |  |  |  | destination => $dest, | 
| 241 |  |  |  |  |  |  | gateway     => $gw, | 
| 242 |  |  |  |  |  |  | genmask     => $genmask, | 
| 243 |  |  |  |  |  |  | flags       => $flags, | 
| 244 |  |  |  |  |  |  | mss         => $mss, | 
| 245 |  |  |  |  |  |  | irtt        => $irtt, | 
| 246 |  |  |  |  |  |  | iface       => $iface, | 
| 247 |  |  |  |  |  |  | } | 
| 248 |  |  |  |  |  |  | ); | 
| 249 |  |  |  |  |  |  | } | 
| 250 |  |  |  |  |  |  |  | 
| 251 | 0 |  |  |  |  | 0 | return @ret; | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | } | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | sub default_gateway { | 
| 256 |  |  |  |  |  |  |  | 
| 257 | 0 |  |  | 0 | 0 | 0 | my ( $class, $new_default_gw ) = @_; | 
| 258 |  |  |  |  |  |  |  | 
| 259 | 0 | 0 |  |  |  | 0 | if ($new_default_gw) { | 
| 260 | 0 | 0 |  |  |  | 0 | if ( default_gateway() ) { | 
| 261 | 0 |  |  |  |  | 0 | i_run "/sbin/route del default", fail_ok => 1; | 
| 262 | 0 | 0 |  |  |  | 0 | if ( $? != 0 ) { | 
| 263 | 0 |  |  |  |  | 0 | die("Error running route del default"); | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  | } | 
| 266 |  |  |  |  |  |  |  | 
| 267 | 0 |  |  |  |  | 0 | i_run "/sbin/route add default gw $new_default_gw", fail_ok => 1; | 
| 268 | 0 | 0 |  |  |  | 0 | if ( $? != 0 ) { | 
| 269 | 0 |  |  |  |  | 0 | die("Error route add default"); | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | } | 
| 273 |  |  |  |  |  |  | else { | 
| 274 | 0 |  |  |  |  | 0 | my @route = route(); | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | my ($default_route) = grep { | 
| 277 | 0 |  |  |  |  | 0 | $_->{"flags"} =~ m/UG/ | 
| 278 |  |  |  |  |  |  | && ( $_->{"destination"} eq "0.0.0.0" | 
| 279 | 0 | 0 | 0 |  |  | 0 | || $_->{"destination"} eq "default" ) | 
| 280 |  |  |  |  |  |  | } @route; | 
| 281 | 0 | 0 |  |  |  | 0 | return $default_route->{"gateway"} if $default_route; | 
| 282 |  |  |  |  |  |  | } | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  | sub netstat { | 
| 286 |  |  |  |  |  |  |  | 
| 287 | 0 |  |  | 0 | 0 | 0 | my @ret; | 
| 288 | 0 |  |  |  |  | 0 | my @netstat = i_run "netstat -nap", fail_ok => 1; | 
| 289 | 0 | 0 |  |  |  | 0 | if ( $? != 0 ) { | 
| 290 | 0 |  |  |  |  | 0 | die("Error running netstat"); | 
| 291 |  |  |  |  |  |  | } | 
| 292 | 0 |  |  |  |  | 0 | my ( $in_inet, $in_unix, $in_unknown ) = ( 0, 0, 0 ); | 
| 293 | 0 |  |  |  |  | 0 | for my $line (@netstat) { | 
| 294 | 0 | 0 |  |  |  | 0 | if ( $in_inet == 1 ) { ++$in_inet; next; } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 295 | 0 | 0 |  |  |  | 0 | if ( $in_unix == 1 ) { ++$in_unix; next; } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 296 | 0 | 0 |  |  |  | 0 | if ( $line =~ m/^Active Internet/ ) { | 
| 297 | 0 |  |  |  |  | 0 | $in_inet    = 1; | 
| 298 | 0 |  |  |  |  | 0 | $in_unix    = 0; | 
| 299 | 0 |  |  |  |  | 0 | $in_unknown = 0; | 
| 300 | 0 |  |  |  |  | 0 | next; | 
| 301 |  |  |  |  |  |  | } | 
| 302 |  |  |  |  |  |  |  | 
| 303 | 0 | 0 |  |  |  | 0 | if ( $line =~ m/^Active UNIX/ ) { | 
| 304 | 0 |  |  |  |  | 0 | $in_inet    = 0; | 
| 305 | 0 |  |  |  |  | 0 | $in_unix    = 1; | 
| 306 | 0 |  |  |  |  | 0 | $in_unknown = 0; | 
| 307 | 0 |  |  |  |  | 0 | next; | 
| 308 |  |  |  |  |  |  | } | 
| 309 |  |  |  |  |  |  |  | 
| 310 | 0 | 0 |  |  |  | 0 | if ( $line =~ m/^Active/ ) { | 
| 311 | 0 |  |  |  |  | 0 | $in_inet    = 0; | 
| 312 | 0 |  |  |  |  | 0 | $in_unix    = 0; | 
| 313 | 0 |  |  |  |  | 0 | $in_unknown = 1; | 
| 314 | 0 |  |  |  |  | 0 | next; | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 0 | 0 |  |  |  | 0 | if ($in_unknown) { | 
| 318 | 0 |  |  |  |  | 0 | next; | 
| 319 |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  |  | 
| 321 | 0 | 0 |  |  |  | 0 | if ($in_inet) { | 
| 322 | 0 |  |  |  |  | 0 | my ( $proto, $recvq, $sendq, $local_addr, $foreign_addr, $state, | 
| 323 |  |  |  |  |  |  | $pid_cmd ); | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 0 | 0 |  |  |  | 0 | unless ( $line =~ m/^udp/ ) { | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | # no state | 
| 328 | 0 |  |  |  |  | 0 | ( $proto, $recvq, $sendq, $local_addr, $foreign_addr, $state, $pid_cmd ) | 
| 329 |  |  |  |  |  |  | = split( /\s+/, $line, 7 ); | 
| 330 |  |  |  |  |  |  | } | 
| 331 |  |  |  |  |  |  | else { | 
| 332 | 0 |  |  |  |  | 0 | ( $proto, $recvq, $sendq, $local_addr, $foreign_addr, $pid_cmd ) = | 
| 333 |  |  |  |  |  |  | split( /\s+/, $line, 6 ); | 
| 334 |  |  |  |  |  |  | } | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 0 |  | 0 |  |  | 0 | $pid_cmd ||= ""; | 
| 337 |  |  |  |  |  |  |  | 
| 338 | 0 |  |  |  |  | 0 | my ( $pid, $cmd ) = split( /\//, $pid_cmd, 2 ); | 
| 339 | 0 | 0 |  |  |  | 0 | if ( $pid =~ m/^-/ ) { | 
| 340 | 0 |  |  |  |  | 0 | $pid = ""; | 
| 341 |  |  |  |  |  |  | } | 
| 342 | 0 |  | 0 |  |  | 0 | $cmd   ||= ""; | 
| 343 | 0 |  | 0 |  |  | 0 | $state ||= ""; | 
| 344 |  |  |  |  |  |  |  | 
| 345 | 0 |  |  |  |  | 0 | $cmd =~ s/\s+$//; | 
| 346 |  |  |  |  |  |  |  | 
| 347 | 0 |  |  |  |  | 0 | push( | 
| 348 |  |  |  |  |  |  | @ret, | 
| 349 |  |  |  |  |  |  | { | 
| 350 |  |  |  |  |  |  | proto        => $proto, | 
| 351 |  |  |  |  |  |  | recvq        => $recvq, | 
| 352 |  |  |  |  |  |  | sendq        => $sendq, | 
| 353 |  |  |  |  |  |  | local_addr   => $local_addr, | 
| 354 |  |  |  |  |  |  | foreign_addr => $foreign_addr, | 
| 355 |  |  |  |  |  |  | state        => $state, | 
| 356 |  |  |  |  |  |  | pid          => $pid, | 
| 357 |  |  |  |  |  |  | command      => $cmd, | 
| 358 |  |  |  |  |  |  | } | 
| 359 |  |  |  |  |  |  | ); | 
| 360 | 0 |  |  |  |  | 0 | next; | 
| 361 |  |  |  |  |  |  | } | 
| 362 |  |  |  |  |  |  |  | 
| 363 | 0 | 0 |  |  |  | 0 | if ($in_unix) { | 
| 364 |  |  |  |  |  |  |  | 
| 365 | 0 |  |  |  |  | 0 | my ( $proto, $refcnt, $flags, $type, $state, $inode, $pid, $cmd, $path ); | 
| 366 |  |  |  |  |  |  |  | 
| 367 | 0 | 0 |  |  |  | 0 | if ( $line =~ | 
| 368 |  |  |  |  |  |  | m/^([a-z]+)\s+(\d+)\s+\[([^\]]+)\]\s+([a-z]+)\s+([a-z]+)?\s+(\d+)\s+(\d+)\/([^\s]+)\s+(.*)$/i | 
| 369 |  |  |  |  |  |  | ) | 
| 370 |  |  |  |  |  |  | { | 
| 371 | 0 |  |  |  |  | 0 | ( $proto, $refcnt, $flags, $type, $state, $inode, $pid, $cmd, $path ) = | 
| 372 |  |  |  |  |  |  | ( $line =~ | 
| 373 |  |  |  |  |  |  | m/^([a-z]+)\s+(\d+)\s+\[([^\]]+)\]\s+([a-z]+)\s+([a-z]+)?\s+(\d+)\s+(\d+)\/([^\s]+)\s+(.*)$/i | 
| 374 |  |  |  |  |  |  | ); | 
| 375 |  |  |  |  |  |  | } | 
| 376 |  |  |  |  |  |  | else { | 
| 377 | 0 |  |  |  |  | 0 | ( $proto, $refcnt, $flags, $type, $state, $inode, $path ) = | 
| 378 |  |  |  |  |  |  | ( $line =~ | 
| 379 |  |  |  |  |  |  | m/^([a-z]+)\s+(\d+)\s+\[([^\]]+)\]\s+([a-z]+)\s+([a-z]+)?\s+(\d+)\s+\-\s+(.*)$/i | 
| 380 |  |  |  |  |  |  | ); | 
| 381 |  |  |  |  |  |  |  | 
| 382 | 0 |  |  |  |  | 0 | $pid = ""; | 
| 383 | 0 |  |  |  |  | 0 | $cmd = ""; | 
| 384 |  |  |  |  |  |  | } | 
| 385 |  |  |  |  |  |  |  | 
| 386 | 0 | 0 |  |  |  | 0 | $state =~ s/^\s|\s$//g if ($state); | 
| 387 | 0 | 0 |  |  |  | 0 | $flags =~ s/\s+$//     if ($flags); | 
| 388 | 0 |  |  |  |  | 0 | $cmd   =~ s/\s+$//; | 
| 389 |  |  |  |  |  |  |  | 
| 390 | 0 |  |  |  |  | 0 | my $data = { | 
| 391 |  |  |  |  |  |  | proto   => $proto, | 
| 392 |  |  |  |  |  |  | refcnt  => $refcnt, | 
| 393 |  |  |  |  |  |  | flags   => $flags, | 
| 394 |  |  |  |  |  |  | type    => $type, | 
| 395 |  |  |  |  |  |  | state   => $state, | 
| 396 |  |  |  |  |  |  | inode   => $inode, | 
| 397 |  |  |  |  |  |  | pid     => $pid, | 
| 398 |  |  |  |  |  |  | command => $cmd, | 
| 399 |  |  |  |  |  |  | path    => $path, | 
| 400 |  |  |  |  |  |  | }; | 
| 401 |  |  |  |  |  |  |  | 
| 402 | 0 |  |  |  |  | 0 | push( @ret, $data ); | 
| 403 |  |  |  |  |  |  | } | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | } | 
| 406 |  |  |  |  |  |  |  | 
| 407 | 0 |  |  |  |  | 0 | return @ret; | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | } | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  | sub _convert_cidr_prefix { | 
| 412 | 46 |  |  | 46 |  | 131 | my ($cidr_prefix) = @_; | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | # convert CIDR prefix to dotted decimal notation | 
| 415 | 46 |  |  |  |  | 268 | my $binary_mask         = '1' x $cidr_prefix . '0' x ( 32 - $cidr_prefix ); | 
| 416 | 46 |  |  |  |  | 577 | my $dotted_decimal_mask = join '.', unpack 'C4', pack 'B32', $binary_mask; | 
| 417 |  |  |  |  |  |  |  | 
| 418 | 46 |  |  |  |  | 234 | return $dotted_decimal_mask; | 
| 419 |  |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | 1; |