| blib/lib/Net/SinFP3/Global.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 19 | 21 | 90.4 |
| branch | n/a | ||
| condition | n/a | ||
| subroutine | 7 | 7 | 100.0 |
| pod | n/a | ||
| total | 26 | 28 | 92.8 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | # | ||||||
| 2 | # $Id: Global.pm 2234 2014-04-08 13:05:14Z gomor $ | ||||||
| 3 | # | ||||||
| 4 | package Net::SinFP3::Global; | ||||||
| 5 | 1 | 1 | 654 | use strict; | |||
| 1 | 1 | ||||||
| 1 | 45 | ||||||
| 6 | 1 | 1 | 5 | use warnings; | |||
| 1 | 1 | ||||||
| 1 | 37 | ||||||
| 7 | |||||||
| 8 | 1 | 1 | 58 | use base qw(Class::Gomor::Array); | |||
| 1 | 2 | ||||||
| 1 | 197 | ||||||
| 9 | our @AS = qw( | ||||||
| 10 | log | ||||||
| 11 | job | ||||||
| 12 | next | ||||||
| 13 | input | ||||||
| 14 | db | ||||||
| 15 | mode | ||||||
| 16 | search | ||||||
| 17 | output | ||||||
| 18 | |||||||
| 19 | target | ||||||
| 20 | targetIp | ||||||
| 21 | targetIpAsInt | ||||||
| 22 | targetReverse | ||||||
| 23 | targetList | ||||||
| 24 | targetListAsInt | ||||||
| 25 | targetCount | ||||||
| 26 | targetSubnet | ||||||
| 27 | targetHostname | ||||||
| 28 | |||||||
| 29 | port | ||||||
| 30 | portList | ||||||
| 31 | portCount | ||||||
| 32 | |||||||
| 33 | ipv6 | ||||||
| 34 | jobs | ||||||
| 35 | macLookup | ||||||
| 36 | dnsReverse | ||||||
| 37 | worker | ||||||
| 38 | device | ||||||
| 39 | retry | ||||||
| 40 | timeout | ||||||
| 41 | pps | ||||||
| 42 | ip | ||||||
| 43 | ip6 | ||||||
| 44 | mac | ||||||
| 45 | srcPort | ||||||
| 46 | subnet | ||||||
| 47 | subnet6 | ||||||
| 48 | gatewayIp | ||||||
| 49 | gatewayIp6 | ||||||
| 50 | gatewayMac | ||||||
| 51 | threshold | ||||||
| 52 | bestScore | ||||||
| 53 | |||||||
| 54 | cacheArp | ||||||
| 55 | cacheDnsReverse | ||||||
| 56 | cacheDnsResolve | ||||||
| 57 | |||||||
| 58 | data | ||||||
| 59 | ); | ||||||
| 60 | our @AA = qw( | ||||||
| 61 | result | ||||||
| 62 | ); | ||||||
| 63 | __PACKAGE__->cgBuildIndices; | ||||||
| 64 | __PACKAGE__->cgBuildAccessorsScalar(\@AS); | ||||||
| 65 | __PACKAGE__->cgBuildAccessorsArray (\@AA); | ||||||
| 66 | |||||||
| 67 | 1 | 1 | 7 | use File::Glob ':globally'; | |||
| 1 | 2 | ||||||
| 1 | 76 | ||||||
| 68 | 1 | 1 | 1607 | use IO::Socket::INET; | |||
| 1 | 22216 | ||||||
| 1 | 10 | ||||||
| 69 | 1 | 1 | 1566 | use IO::Socket::INET6; | |||
| 1 | 6496 | ||||||
| 1 | 11 | ||||||
| 70 | 1 | 1 | 2903 | use Net::Frame::Device; | |||
| 0 | |||||||
| 0 | |||||||
| 71 | use Net::Frame::Dump::Offline; | ||||||
| 72 | use Net::Frame::Dump::Online2; | ||||||
| 73 | use Net::Frame::Dump::Writer; | ||||||
| 74 | use Net::Frame::Layer qw(:subs); | ||||||
| 75 | use Net::Frame::Simple; | ||||||
| 76 | use Net::Netmask; | ||||||
| 77 | use Net::Write::Layer2; | ||||||
| 78 | use Net::Write::Layer3; | ||||||
| 79 | use Socket; | ||||||
| 80 | use Socket6 qw(inet_pton NI_NUMERICHOST NI_NUMERICSERV getnameinfo getaddrinfo); | ||||||
| 81 | |||||||
| 82 | sub new { | ||||||
| 83 | my $self = shift->SUPER::new( | ||||||
| 84 | job => 0, | ||||||
| 85 | ipv6 => 0, | ||||||
| 86 | macLookup => 1, | ||||||
| 87 | dnsReverse => 0, | ||||||
| 88 | jobs => 10, | ||||||
| 89 | retry => 3, | ||||||
| 90 | timeout => 3, | ||||||
| 91 | pps => 200, | ||||||
| 92 | worker => 'Fork', | ||||||
| 93 | srcPort => 31337, | ||||||
| 94 | threshold => 0, | ||||||
| 95 | bestScore => 0, | ||||||
| 96 | port => 'top10', | ||||||
| 97 | targetReverse => 'unknown', | ||||||
| 98 | targetHostname => 'unknown', | ||||||
| 99 | result => [], | ||||||
| 100 | cacheArp => {}, | ||||||
| 101 | @_, | ||||||
| 102 | ); | ||||||
| 103 | |||||||
| 104 | if (!defined($self->log)) { | ||||||
| 105 | die("[-] ".__PACKAGE__.": You must provide a log object\n"); | ||||||
| 106 | } | ||||||
| 107 | my $log = $self->log; | ||||||
| 108 | |||||||
| 109 | my $dev; | ||||||
| 110 | if ($self->target) { | ||||||
| 111 | my $ip = $self->_parseTarget; | ||||||
| 112 | |||||||
| 113 | my %args = (); | ||||||
| 114 | $self->ipv6 ? ($args{target6} = $ip) : ($args{target} = $ip); | ||||||
| 115 | $self->device ? ($args{dev} = $self->device) : (); | ||||||
| 116 | $dev = Net::Frame::Device->new(%args); | ||||||
| 117 | if (!defined($dev)) { | ||||||
| 118 | $log->fatal("Unable to acquire device information from target [". | ||||||
| 119 | $self->target."]"); | ||||||
| 120 | } | ||||||
| 121 | } | ||||||
| 122 | elsif ($self->device) { | ||||||
| 123 | $dev = Net::Frame::Device->new(dev => $self->device); | ||||||
| 124 | if (!defined($dev)) { | ||||||
| 125 | $log->fatal("Unable to acquire device information from device [". | ||||||
| 126 | $self->device."]"); | ||||||
| 127 | } | ||||||
| 128 | } | ||||||
| 129 | else { | ||||||
| 130 | $dev = Net::Frame::Device->new; | ||||||
| 131 | if (!defined($dev)) { | ||||||
| 132 | $log->warning("Unable to get default device information"); | ||||||
| 133 | } | ||||||
| 134 | } | ||||||
| 135 | |||||||
| 136 | $self->_parsePort; | ||||||
| 137 | |||||||
| 138 | $self->device($dev->dev) if !$self->device && $dev->dev; | ||||||
| 139 | $self->ip($dev->ip) if !$self->ip && $dev->ip; | ||||||
| 140 | $self->ip6($dev->ip6) if !$self->ip6 && $dev->ip6; | ||||||
| 141 | $self->mac($dev->mac) if !$self->mac && $dev->mac; | ||||||
| 142 | $self->subnet($dev->subnet) if !$self->subnet && $dev->subnet; | ||||||
| 143 | $self->gatewayIp($dev->gatewayIp) if !$self->gatewayIp && $dev->gatewayIp; | ||||||
| 144 | $self->gatewayIp6($dev->gatewayIp6) if !$self->gatewayIp6 | ||||||
| 145 | && $dev->gatewayIp6; | ||||||
| 146 | $self->gatewayMac($dev->gatewayMac) if !$self->gatewayMac | ||||||
| 147 | && $dev->gatewayMac; | ||||||
| 148 | |||||||
| 149 | $log->verbose("dev: ".$self->device) if $self->device; | ||||||
| 150 | $log->verbose("ip: ".$self->ip) if $self->ip; | ||||||
| 151 | $log->verbose("ip6: ".$self->ip6) if $self->ip6; | ||||||
| 152 | $log->verbose("mac: ".$self->mac) if $self->mac; | ||||||
| 153 | $log->verbose("subnet: ".$self->subnet) if $self->subnet; | ||||||
| 154 | $log->verbose("gatewayIp: ".$self->gatewayIp) if $self->gatewayIp; | ||||||
| 155 | $log->verbose("gatewayIp6: ".$self->gatewayIp6) if $self->gatewayIp6; | ||||||
| 156 | $log->verbose("gatewayMac: ".$self->gatewayMac) if $self->gatewayMac; | ||||||
| 157 | |||||||
| 158 | return $self; | ||||||
| 159 | } | ||||||
| 160 | |||||||
| 161 | sub _parseTarget { | ||||||
| 162 | my $self = shift; | ||||||
| 163 | |||||||
| 164 | my $log = $self->log; | ||||||
| 165 | |||||||
| 166 | my $target = $self->target; | ||||||
| 167 | if (! $target) { | ||||||
| 168 | return 1; | ||||||
| 169 | } | ||||||
| 170 | |||||||
| 171 | # Possible formats | ||||||
| 172 | # FQDN => 0 | ||||||
| 173 | # SUBNET => 1 | ||||||
| 174 | # IP/32 => 2 | ||||||
| 175 | # IP => 2 | ||||||
| 176 | |||||||
| 177 | $target =~ s/\/32$//; | ||||||
| 178 | $self->target($target); | ||||||
| 179 | |||||||
| 180 | my $format = 0; # FQDN format by default | ||||||
| 181 | if ($target =~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/\d+$/) { | ||||||
| 182 | $format = 1; # Subnet format | ||||||
| 183 | } | ||||||
| 184 | elsif ($target =~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { | ||||||
| 185 | $format = 2; # Single IP format | ||||||
| 186 | } | ||||||
| 187 | |||||||
| 188 | my $ip; | ||||||
| 189 | if ($format == 0) { # FQDN format | ||||||
| 190 | $ip = $self->getHostAddr(host => $target) | ||||||
| 191 | or $log->fatal("Unable to resolve target hostname: [$target]"); | ||||||
| 192 | |||||||
| 193 | $self->targetHostname($target); | ||||||
| 194 | $self->targetIp($ip); | ||||||
| 195 | $self->targetCount(1); | ||||||
| 196 | $self->targetList([ $ip ]); | ||||||
| 197 | |||||||
| 198 | my $ipAsInt = $self->ipToInt(ip => $ip) or return; | ||||||
| 199 | $self->targetIpAsInt($ipAsInt); | ||||||
| 200 | $self->targetListAsInt([ $ipAsInt ]); | ||||||
| 201 | } | ||||||
| 202 | elsif ($format == 1) { # Subnet format | ||||||
| 203 | if ($self->ipv6) { | ||||||
| 204 | $log->fatal("IPv6 subnet scanning not supported (yet): [$target]"); | ||||||
| 205 | } | ||||||
| 206 | else { | ||||||
| 207 | my $list = $self->expandSubnet( | ||||||
| 208 | subnet => $target, | ||||||
| 209 | asInt => 1, | ||||||
| 210 | ) or $log->fatal("Unable to parse this subnet: [$target]"); | ||||||
| 211 | |||||||
| 212 | $self->targetSubnet($target); | ||||||
| 213 | |||||||
| 214 | my $size = scalar(@$list); | ||||||
| 215 | $self->targetCount($size); | ||||||
| 216 | if ($size > 1) { # Skip the network address | ||||||
| 217 | $self->targetIpAsInt($list->[1]); | ||||||
| 218 | $ip = $self->intToIp(int => $list->[1]) or return; | ||||||
| 219 | } | ||||||
| 220 | elsif ($size == 1) { # No network address here | ||||||
| 221 | $self->targetIpAsInt($list->[0]); | ||||||
| 222 | $ip = $self->intToIp(int => $list->[0]) or return; | ||||||
| 223 | } | ||||||
| 224 | else { | ||||||
| 225 | $log->fatal("Unable to analyze this subnet: [$target]"); | ||||||
| 226 | } | ||||||
| 227 | $self->targetIp($ip); | ||||||
| 228 | # XXX: do we convert all IPs to ASCII format here? -> targetList | ||||||
| 229 | # No, it will take too much memory. Must be a user option. | ||||||
| 230 | $self->targetListAsInt($list); | ||||||
| 231 | } | ||||||
| 232 | } | ||||||
| 233 | elsif ($format == 2) { # Single IP format | ||||||
| 234 | $self->targetIp($target); | ||||||
| 235 | my $ipAsInt = $self->ipToInt(ip => $target) or return; | ||||||
| 236 | $self->targetIpAsInt($ipAsInt); | ||||||
| 237 | $self->targetCount(1); | ||||||
| 238 | $self->targetList([ $target ]); | ||||||
| 239 | $self->targetListAsInt([ $ipAsInt ]); | ||||||
| 240 | } | ||||||
| 241 | else { | ||||||
| 242 | $log->fatal("Unknown target format"); | ||||||
| 243 | } | ||||||
| 244 | |||||||
| 245 | #$log->debug("_parseTarget: target: ".($self->target || '(null)')); | ||||||
| 246 | #$log->debug("_parseTarget: targetIp: ".($self->targetIp || '(null)')); | ||||||
| 247 | #$log->debug("_parseTarget: targetIpAsInt: ".($self->targetIpAsInt || '(null)')); | ||||||
| 248 | #$log->debug("_parseTarget: targetCount: ".($self->targetCount || '(null)')); | ||||||
| 249 | #$log->debug("_parseTarget: targetSubnet: ".($self->targetSubnet || '(null)')); | ||||||
| 250 | #$log->debug("_parseTarget: targetHostname: ".($self->targetHostname || '(null)')); | ||||||
| 251 | #my $listAsInt = $self->targetListAsInt; | ||||||
| 252 | #my $first = $listAsInt->[0] || '(null)'; | ||||||
| 253 | #$log->debug("_parseTarget: targetListAsInt first: $first"); | ||||||
| 254 | |||||||
| 255 | if ($self->dnsReverse) { | ||||||
| 256 | $self->targetReverse( | ||||||
| 257 | $self->getAddrReverse(addr => $self->targetIp) || 'unknown' | ||||||
| 258 | ); | ||||||
| 259 | } | ||||||
| 260 | |||||||
| 261 | return $self->targetIp; | ||||||
| 262 | } | ||||||
| 263 | |||||||
| 264 | sub _parsePort { | ||||||
| 265 | my $self = shift; | ||||||
| 266 | |||||||
| 267 | my $log = $self->log; | ||||||
| 268 | |||||||
| 269 | # Valid port format | ||||||
| 270 | # Single port: 80 | ||||||
| 271 | # Range port: 80-90 | ||||||
| 272 | # Comma list: 80,81,82 | ||||||
| 273 | # Mixed list: 80-90,100 | ||||||
| 274 | # Fixed: top10, top100, top1000, all|full | ||||||
| 275 | |||||||
| 276 | my $list = $self->expandPorts(ports => $self->port) | ||||||
| 277 | or $log->fatal("Unable to expand ports: [".$self->port."]"); | ||||||
| 278 | |||||||
| 279 | $self->portList($list); | ||||||
| 280 | $self->portCount(scalar(@$list)); | ||||||
| 281 | |||||||
| 282 | #$log->debug("_parsePort: portCount: ".scalar(@$list)); | ||||||
| 283 | #$log->debug("_parsePort: portList first: ".$list->[0]); | ||||||
| 284 | ##$log->debug("_parsePort: portList: ".join(',', @$list)); | ||||||
| 285 | |||||||
| 286 | return 1; | ||||||
| 287 | } | ||||||
| 288 | |||||||
| 289 | sub expandSubnet { | ||||||
| 290 | my $self = shift; | ||||||
| 291 | my %h = @_; | ||||||
| 292 | |||||||
| 293 | my $log = $self->log; | ||||||
| 294 | |||||||
| 295 | if (!defined($h{subnet})) { | ||||||
| 296 | $log->fatal("expandSubnet: You must provide subnet attribute"); | ||||||
| 297 | } | ||||||
| 298 | my $subnet = $h{subnet}; | ||||||
| 299 | |||||||
| 300 | if ($subnet !~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\/\d+$/) { | ||||||
| 301 | $log->fatal("expandSubnet: Invalid subnet format: [$subnet]"); | ||||||
| 302 | } | ||||||
| 303 | |||||||
| 304 | my $oNet = Net::Netmask->new2($subnet); | ||||||
| 305 | if (!defined($oNet)) { | ||||||
| 306 | $log->warning("expandSubnet: Net::Netmask error for subnet ". | ||||||
| 307 | "[$subnet]: $Net::Netmask::errstr"); | ||||||
| 308 | return; | ||||||
| 309 | } | ||||||
| 310 | |||||||
| 311 | $log->debug("Expanding subnet IP addresses, this may take a few seconds ..."); | ||||||
| 312 | |||||||
| 313 | my @list = (); | ||||||
| 314 | my $size = $oNet->size; | ||||||
| 315 | my $ibase = $oNet->{IBASE}; | ||||||
| 316 | if ($h{asInt}) { | ||||||
| 317 | for my $i (0..$size-1) { | ||||||
| 318 | push @list, $ibase+$i; | ||||||
| 319 | } | ||||||
| 320 | } | ||||||
| 321 | else { | ||||||
| 322 | for my $i (0..$size-1) { | ||||||
| 323 | push @list, $self->intToIp(int => ($ibase + $i)) or return; | ||||||
| 324 | } | ||||||
| 325 | } | ||||||
| 326 | |||||||
| 327 | $log->debug("Expanding subnet IP addresses: Done (count: ".scalar(@list).")"); | ||||||
| 328 | |||||||
| 329 | return \@list; | ||||||
| 330 | } | ||||||
| 331 | |||||||
| 332 | sub expandPorts { | ||||||
| 333 | my $self = shift; | ||||||
| 334 | my %h = @_; | ||||||
| 335 | |||||||
| 336 | my $log = $self->log; | ||||||
| 337 | |||||||
| 338 | if (!defined($h{ports})) { | ||||||
| 339 | $log->fatal("expandPorts: You must provide ports attribute"); | ||||||
| 340 | } | ||||||
| 341 | my $ports = $h{ports}; | ||||||
| 342 | |||||||
| 343 | #$log->debug("Expanding target ports, this may take a few seconds ..."); | ||||||
| 344 | |||||||
| 345 | if ($ports =~ /all|full/i) { | ||||||
| 346 | $ports = '0-65535'; | ||||||
| 347 | } | ||||||
| 348 | elsif ($ports =~ /top10\s*$/i) { | ||||||
| 349 | $ports = '21,22,23,25,80,135,139,443,445,3389'; | ||||||
| 350 | } | ||||||
| 351 | elsif ($ports =~ /top100\s*$/i) { | ||||||
| 352 | $ports = '7,9,13,21,22,23,25,26,37,53,79,80,81,88,106,110,111,113,119,135,139,143,144,179,199,389,427,443,444,445,465,513,514,515,543,544,548,554,587,631,646,873,990,993,995,1025,1026,1027,1028,1029,1110,1433,1720,1723,1755,1900,2000,2001,2049,2121,2717,3000,3128,3306,3389,3986,4899,5000,5009,5051,5060,5101,5190,5357,5432,5631,5666,5800,5900,6000,6001,6646,7070,8000,8008,8009,8080,8081,8443,8888,9100,9999,10000,32768,49152,49153,49154,49155,49156,49157'; | ||||||
| 353 | } | ||||||
| 354 | elsif ($ports =~ /top1000\s*$/i) { | ||||||
| 355 | $ports = '1,3,4,6,7,9,13,17,19,20,21,22,23,24,25,26,30,32,33,37,42,43,49,53,70,79,80,81,82,83,84,85,88,89,90,99,100,106,109,110,111,113,119,125,135,139,143,144,146,161,163,179,199,211,212,222,254,255,256,259,264,280,301,306,311,340,366,389,406,407,416,417,425,427,443,444,445,458,464,465,481,497,500,512,513,514,515,524,541,543,544,545,548,554,555,563,587,593,616,617,625,631,636,646,648,666,667,668,683,687,691,700,705,711,714,720,722,726,749,765,777,783,787,800,801,808,843,873,880,888,898,900,901,902,903,911,912,981,987,990,992,993,995,999,1000,1001,1002,1007,1009,1010,1011,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1102,1104,1105,1106,1107,1108,1110,1111,1112,1113,1114,1117,1119,1121,1122,1123,1124,1126,1130,1131,1132,1137,1138,1141,1145,1147,1148,1149,1151,1152,1154,1163,1164,1165,1166,1169,1174,1175,1183,1185,1186,1187,1192,1198,1199,1201,1213,1216,1217,1218,1233,1234,1236,1244,1247,1248,1259,1271,1272,1277,1287,1296,1300,1301,1309,1310,1311,1322,1328,1334,1352,1417,1433,1434,1443,1455,1461,1494,1500,1501,1503,1521,1524,1533,1556,1580,1583,1594,1600,1641,1658,1666,1687,1688,1700,1717,1718,1719,1720,1721,1723,1755,1761,1782,1783,1801,1805,1812,1839,1840,1862,1863,1864,1875,1900,1914,1935,1947,1971,1972,1974,1984,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2013,2020,2021,2022,2030,2033,2034,2035,2038,2040,2041,2042,2043,2045,2046,2047,2048,2049,2065,2068,2099,2100,2103,2105,2106,2107,2111,2119,2121,2126,2135,2144,2160,2161,2170,2179,2190,2191,2196,2200,2222,2251,2260,2288,2301,2323,2366,2381,2382,2383,2393,2394,2399,2401,2492,2500,2522,2525,2557,2601,2602,2604,2605,2607,2608,2638,2701,2702,2710,2717,2718,2725,2800,2809,2811,2869,2875,2909,2910,2920,2967,2968,2998,3000,3001,3003,3005,3006,3007,3011,3013,3017,3030,3031,3050,3052,3071,3077,3128,3168,3211,3221,3260,3261,3268,3269,3283,3300,3301,3306,3322,3323,3324,3325,3333,3351,3367,3369,3370,3371,3372,3389,3390,3404,3476,3493,3517,3527,3546,3551,3580,3659,3689,3690,3703,3737,3766,3784,3800,3801,3809,3814,3826,3827,3828,3851,3869,3871,3878,3880,3889,3905,3914,3918,3920,3945,3971,3986,3995,3998,4000,4001,4002,4003,4004,4005,4006,4045,4111,4125,4126,4129,4224,4242,4279,4321,4343,4443,4444,4445,4446,4449,4550,4567,4662,4848,4899,4900,4998,5000,5001,5002,5003,5004,5009,5030,5033,5050,5051,5054,5060,5061,5080,5087,5100,5101,5102,5120,5190,5200,5214,5221,5222,5225,5226,5269,5280,5298,5357,5405,5414,5431,5432,5440,5500,5510,5544,5550,5555,5560,5566,5631,5633,5666,5678,5679,5718,5730,5800,5801,5802,5810,5811,5815,5822,5825,5850,5859,5862,5877,5900,5901,5902,5903,5904,5906,5907,5910,5911,5915,5922,5925,5950,5952,5959,5960,5961,5962,5963,5987,5988,5989,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6009,6025,6059,6100,6101,6106,6112,6123,6129,6156,6346,6389,6502,6510,6543,6547,6565,6566,6567,6580,6646,6666,6667,6668,6669,6689,6692,6699,6779,6788,6789,6792,6839,6881,6901,6969,7000,7001,7002,7004,7007,7019,7025,7070,7100,7103,7106,7200,7201,7402,7435,7443,7496,7512,7625,7627,7676,7741,7777,7778,7800,7911,7920,7921,7937,7938,7999,8000,8001,8002,8007,8008,8009,8010,8011,8021,8022,8031,8042,8045,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8093,8099,8100,8180,8181,8192,8193,8194,8200,8222,8254,8290,8291,8292,8300,8333,8383,8400,8402,8443,8500,8600,8649,8651,8652,8654,8701,8800,8873,8888,8899,8994,9000,9001,9002,9003,9009,9010,9011,9040,9050,9071,9080,9081,9090,9091,9099,9100,9101,9102,9103,9110,9111,9200,9207,9220,9290,9415,9418,9485,9500,9502,9503,9535,9575,9593,9594,9595,9618,9666,9876,9877,9878,9898,9900,9917,9943,9944,9968,9998,9999,10000,10001,10002,10003,10004,10009,10010,10012,10024,10025,10082,10180,10215,10243,10566,10616,10617,10621,10626,10628,10629,10778,11110,11111,11967,12000,12174,12265,12345,13456,13722,13782,13783,14000,14238,14441,14442,15000,15002,15003,15004,15660,15742,16000,16001,16012,16016,16018,16080,16113,16992,16993,17877,17988,18040,18101,18988,19101,19283,19315,19350,19780,19801,19842,20000,20005,20031,20221,20222,20828,21571,22939,23502,24444,24800,25734,25735,26214,27000,27352,27353,27355,27356,27715,28201,30000,30718,30951,31038,31337,32768,32769,32770,32771,32772,32773,32774,32775,32776,32777,32778,32779,32780,32781,32782,32783,32784,32785,33354,33899,34571,34572,34573,35500,38292,40193,40911,41511,42510,44176,44442,44443,44501,45100,48080,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49163,49165,49167,49175,49176,49400,49999,50000,50001,50002,50003,50006,50300,50389,50500,50636,50800,51103,51493,52673,52822,52848,52869,54045,54328,55055,55056,55555,55600,56737,56738,57294,57797,58080,60020,60443,61532,61900,62078,63331,64623,64680,65000,65129,65389'; | ||||||
| 356 | } | ||||||
| 357 | elsif ($ports !~ /^[0-9,-]+$/) { | ||||||
| 358 | $log->fatal("Invalid port range for -port argument: [$ports]"); | ||||||
| 359 | } | ||||||
| 360 | |||||||
| 361 | my @ports = (); | ||||||
| 362 | for my $c (split(',', $ports)) { | ||||||
| 363 | $c =~ s/-/../g; | ||||||
| 364 | for my $p (eval($c)) { | ||||||
| 365 | push @ports, $p; | ||||||
| 366 | } | ||||||
| 367 | } | ||||||
| 368 | |||||||
| 369 | #$log->debug("Expanding target ports: Done (count: ".scalar(@ports).")"); | ||||||
| 370 | |||||||
| 371 | return \@ports; | ||||||
| 372 | } | ||||||
| 373 | |||||||
| 374 | sub expandFiles { | ||||||
| 375 | my $self = shift; | ||||||
| 376 | my %h = @_; | ||||||
| 377 | |||||||
| 378 | my $log = $self->log; | ||||||
| 379 | |||||||
| 380 | if (!defined($h{files})) { | ||||||
| 381 | $log->fatal("expandFiles: You must provide files attribute"); | ||||||
| 382 | } | ||||||
| 383 | my $files = $h{files}; | ||||||
| 384 | |||||||
| 385 | my @list = <{$files}>; | ||||||
| 386 | if (@list == 0) { | ||||||
| 387 | $log->warning("expandFiles: no file found"); | ||||||
| 388 | return; | ||||||
| 389 | } | ||||||
| 390 | |||||||
| 391 | return \@list; | ||||||
| 392 | } | ||||||
| 393 | |||||||
| 394 | sub lookupMac { | ||||||
| 395 | my $self = shift; | ||||||
| 396 | |||||||
| 397 | my $log = $self->log; | ||||||
| 398 | |||||||
| 399 | if (! $self->macLookup) { | ||||||
| 400 | $log->verbose("MAC lookup disabled"); | ||||||
| 401 | return; | ||||||
| 402 | } | ||||||
| 403 | |||||||
| 404 | print "XXX: TODO\n"; | ||||||
| 405 | |||||||
| 406 | return; | ||||||
| 407 | } | ||||||
| 408 | |||||||
| 409 | sub lookupMac6 { | ||||||
| 410 | my $self = shift; | ||||||
| 411 | my %h = @_; | ||||||
| 412 | |||||||
| 413 | my $log = $self->log; | ||||||
| 414 | |||||||
| 415 | if (! $self->macLookup) { | ||||||
| 416 | $log->verbose("MAC lookup disabled"); | ||||||
| 417 | return; | ||||||
| 418 | } | ||||||
| 419 | |||||||
| 420 | if (!defined($h{ipv6})) { | ||||||
| 421 | $log->fatal("lookupMac6: You must provide ipv6 attribute"); | ||||||
| 422 | } | ||||||
| 423 | my $ipv6 = $h{ipv6}; | ||||||
| 424 | |||||||
| 425 | $log->verbose("Trying to find MAC address for target IPv6: [$ipv6]"); | ||||||
| 426 | |||||||
| 427 | my $cacheArp = $self->cacheArp; | ||||||
| 428 | |||||||
| 429 | my $mac; | ||||||
| 430 | if (defined($cacheArp->{$ipv6})) { | ||||||
| 431 | $mac = $cacheArp->{$ipv6}; | ||||||
| 432 | $log->verbose("Found MAC address: [$mac] from cache"); | ||||||
| 433 | } | ||||||
| 434 | else { | ||||||
| 435 | my $dev = Net::Frame::Device->new( | ||||||
| 436 | target6 => $ipv6, | ||||||
| 437 | dev => $self->device, | ||||||
| 438 | ); | ||||||
| 439 | if (!defined($dev)) { | ||||||
| 440 | $log->fatal("lookupMac6: unable to acquire device for target6 [". | ||||||
| 441 | $ipv6."]"); | ||||||
| 442 | return; | ||||||
| 443 | } | ||||||
| 444 | |||||||
| 445 | $mac = $dev->lookupMac6($ipv6, $self->retry, $self->timeout); | ||||||
| 446 | if (!defined($mac)) { | ||||||
| 447 | $log->fatal("lookupMac6: unable to get MAC address for IPv6 [". | ||||||
| 448 | $ipv6."]"); | ||||||
| 449 | return; | ||||||
| 450 | } | ||||||
| 451 | $cacheArp->{$ipv6} = $mac; | ||||||
| 452 | $log->verbose("Found MAC address: [$mac] from lookup"); | ||||||
| 453 | } | ||||||
| 454 | |||||||
| 455 | return $mac; | ||||||
| 456 | } | ||||||
| 457 | |||||||
| 458 | sub _getHostIpv6Addr { | ||||||
| 459 | my ($host) = @_; | ||||||
| 460 | |||||||
| 461 | if (Net::IPv6Addr::is_ipv6($host)) { | ||||||
| 462 | return $host; | ||||||
| 463 | } | ||||||
| 464 | |||||||
| 465 | my @res = getaddrinfo($host, 'ssh', Socket6::AF_INET6(), SOCK_STREAM); | ||||||
| 466 | if (@res >= 5) { | ||||||
| 467 | my ($ipv6) = getnameinfo($res[3], NI_NUMERICHOST | NI_NUMERICSERV); | ||||||
| 468 | $ipv6 =~ s/%.*$//; | ||||||
| 469 | return $ipv6; | ||||||
| 470 | } | ||||||
| 471 | |||||||
| 472 | return; | ||||||
| 473 | } | ||||||
| 474 | |||||||
| 475 | sub _getHostIpv4Addr { | ||||||
| 476 | my ($host) = @_; | ||||||
| 477 | |||||||
| 478 | if ($host =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { | ||||||
| 479 | return $host; | ||||||
| 480 | } | ||||||
| 481 | |||||||
| 482 | my @addrs = (gethostbyname($host))[4]; | ||||||
| 483 | return @addrs ? join('.', CORE::unpack('C4', $addrs[0])) | ||||||
| 484 | : undef; | ||||||
| 485 | } | ||||||
| 486 | |||||||
| 487 | sub getHostAddr { | ||||||
| 488 | my $self = shift; | ||||||
| 489 | my %h = @_; | ||||||
| 490 | |||||||
| 491 | my $log = $self->log; | ||||||
| 492 | |||||||
| 493 | if (!defined($h{host})) { | ||||||
| 494 | $log->fatal("getHostAddr: You must provide host attribute"); | ||||||
| 495 | } | ||||||
| 496 | my $host = $h{host}; | ||||||
| 497 | |||||||
| 498 | my $ip = $self->ipv6 ? _getHostIpv6Addr($host) : _getHostIpv4Addr($host); | ||||||
| 499 | if (!defined($ip)) { | ||||||
| 500 | $log->warning("getHostAddr: unable to resolve ". | ||||||
| 501 | ($self->ipv6 ? 'IPv6' : 'IPv4'). | ||||||
| 502 | " address for hostname [$host]"); | ||||||
| 503 | return; | ||||||
| 504 | } | ||||||
| 505 | |||||||
| 506 | return $ip; | ||||||
| 507 | } | ||||||
| 508 | |||||||
| 509 | sub getAddrReverse { | ||||||
| 510 | my $self = shift; | ||||||
| 511 | my %h = @_; | ||||||
| 512 | |||||||
| 513 | my $log = $self->log; | ||||||
| 514 | |||||||
| 515 | if (!defined($h{addr})) { | ||||||
| 516 | $log->fatal("getAddrReverse: You must provide addr attribute"); | ||||||
| 517 | } | ||||||
| 518 | my $addr = $h{addr}; | ||||||
| 519 | |||||||
| 520 | $log->verbose("Trying reverse lookup for IP [$addr]"); | ||||||
| 521 | |||||||
| 522 | my $reverse; | ||||||
| 523 | if ($self->ipv6) { | ||||||
| 524 | my $inet = inet_pton(Socket6::AF_INET6(), $addr); | ||||||
| 525 | if (!defined($inet)) { | ||||||
| 526 | $log->warning("getAddrReverse: unable to get reverse on IPv6 ". | ||||||
| 527 | "[$addr]"); | ||||||
| 528 | return; | ||||||
| 529 | } | ||||||
| 530 | $reverse = gethostbyaddr($inet, Socket6::AF_INET6()); | ||||||
| 531 | } | ||||||
| 532 | else { | ||||||
| 533 | my $inet = inet_aton($addr); | ||||||
| 534 | if (!defined($inet)) { | ||||||
| 535 | $log->warning("getAddrReverse: unable to get reverse on IPv4 ". | ||||||
| 536 | "[$addr]"); | ||||||
| 537 | return; | ||||||
| 538 | } | ||||||
| 539 | $reverse = gethostbyaddr($inet, AF_INET); | ||||||
| 540 | } | ||||||
| 541 | |||||||
| 542 | if ($reverse) { | ||||||
| 543 | $log->verbose("Reverse lookup gave: [$reverse]"); | ||||||
| 544 | } | ||||||
| 545 | else { | ||||||
| 546 | $log->verbose("Reverse lookup gave nothing"); | ||||||
| 547 | } | ||||||
| 548 | |||||||
| 549 | return $reverse; | ||||||
| 550 | } | ||||||
| 551 | |||||||
| 552 | sub ipToInt { | ||||||
| 553 | my $self = shift; | ||||||
| 554 | my %h = @_; | ||||||
| 555 | |||||||
| 556 | my $log = $self->log; | ||||||
| 557 | |||||||
| 558 | if (! defined($h{ip})) { | ||||||
| 559 | $log->fatal("ipToInt: You must provide `ip' attribute"); | ||||||
| 560 | } | ||||||
| 561 | my $ip = $h{ip}; | ||||||
| 562 | |||||||
| 563 | if ($self->ipv6) { | ||||||
| 564 | # XXX: Should use inet_pton for IPv6 support | ||||||
| 565 | $log->warning("IPv6 to Int not supported, doing nothing"); | ||||||
| 566 | return $ip; | ||||||
| 567 | } | ||||||
| 568 | |||||||
| 569 | my $int = $ip; | ||||||
| 570 | # Is this not yet in Int format? | ||||||
| 571 | if ($ip !~ /^\d+$/) { | ||||||
| 572 | $int = unpack('N', inet_aton($ip)); | ||||||
| 573 | if (! defined($int)) { | ||||||
| 574 | $log->error("Unable to IP to Int address: [$ip]: $!"); | ||||||
| 575 | return; | ||||||
| 576 | } | ||||||
| 577 | } | ||||||
| 578 | |||||||
| 579 | return $int; | ||||||
| 580 | } | ||||||
| 581 | |||||||
| 582 | sub intToIp { | ||||||
| 583 | my $self = shift; | ||||||
| 584 | my %h = @_; | ||||||
| 585 | |||||||
| 586 | my $log = $self->log; | ||||||
| 587 | |||||||
| 588 | if (! defined($h{int})) { | ||||||
| 589 | $log->fatal("intToIp: You must provide `int' attribute"); | ||||||
| 590 | } | ||||||
| 591 | my $int = $h{int}; | ||||||
| 592 | |||||||
| 593 | if ($self->ipv6) { | ||||||
| 594 | # XXX: Should use inet_ntop for IPv6 support | ||||||
| 595 | $log->warning("Int to IPv6 not supported, doing nothing"); | ||||||
| 596 | return $int; | ||||||
| 597 | } | ||||||
| 598 | |||||||
| 599 | my $ip = $int; | ||||||
| 600 | # Is this in Int format? | ||||||
| 601 | if ($int =~ /^\d+$/) { | ||||||
| 602 | $ip = inet_ntoa(pack('N', $int)); | ||||||
| 603 | if (! defined($ip)) { | ||||||
| 604 | $log->error("Unable to Int to IP address: [$int]: $!"); | ||||||
| 605 | return; | ||||||
| 606 | } | ||||||
| 607 | } | ||||||
| 608 | |||||||
| 609 | return $ip; | ||||||
| 610 | } | ||||||
| 611 | |||||||
| 612 | sub getDumpOnline { | ||||||
| 613 | my $self = shift; | ||||||
| 614 | my %h = @_; | ||||||
| 615 | |||||||
| 616 | if (defined($h{filter})) { | ||||||
| 617 | $self->log->verbose("getDumpOnline: Using filter [$h{filter}]") | ||||||
| 618 | } | ||||||
| 619 | |||||||
| 620 | my $oDump = Net::Frame::Dump::Online2->new( | ||||||
| 621 | dev => $self->device, | ||||||
| 622 | timeoutOnNext => $self->timeout, | ||||||
| 623 | %h, | ||||||
| 624 | ); | ||||||
| 625 | |||||||
| 626 | return $oDump; | ||||||
| 627 | } | ||||||
| 628 | |||||||
| 629 | sub getDumpOffline { | ||||||
| 630 | my $self = shift; | ||||||
| 631 | my %h = @_; | ||||||
| 632 | |||||||
| 633 | my $log = $self->log; | ||||||
| 634 | |||||||
| 635 | if (!defined($h{file})) { | ||||||
| 636 | $log->fatal("getDumpOffline: You must provide file attribute"); | ||||||
| 637 | } | ||||||
| 638 | |||||||
| 639 | if (!-f $h{file}) { | ||||||
| 640 | $log->warning("getDumpOffline: File [$h{file}] not found"); | ||||||
| 641 | return; | ||||||
| 642 | } | ||||||
| 643 | |||||||
| 644 | if (defined($h{filter})) { | ||||||
| 645 | $log->verbose("getDumpOffline: Using filter [$h{filter}]") | ||||||
| 646 | } | ||||||
| 647 | |||||||
| 648 | my $oDump = Net::Frame::Dump::Offline->new(%h); | ||||||
| 649 | |||||||
| 650 | return $oDump; | ||||||
| 651 | } | ||||||
| 652 | |||||||
| 653 | sub getDumpWriter { | ||||||
| 654 | my $self = shift; | ||||||
| 655 | my %h = @_; | ||||||
| 656 | |||||||
| 657 | my $oDump = Net::Frame::Dump::Writer->new(%h); | ||||||
| 658 | |||||||
| 659 | return $oDump; | ||||||
| 660 | } | ||||||
| 661 | |||||||
| 662 | sub getWriteL2 { | ||||||
| 663 | my $self = shift; | ||||||
| 664 | |||||||
| 665 | my $oWrite = Net::Write::Layer2->new(dev => $self->device); | ||||||
| 666 | |||||||
| 667 | return $oWrite; | ||||||
| 668 | } | ||||||
| 669 | |||||||
| 670 | sub getWriteL3 { | ||||||
| 671 | my $self = shift; | ||||||
| 672 | my %h = @_; | ||||||
| 673 | |||||||
| 674 | my $log = $self->log; | ||||||
| 675 | |||||||
| 676 | if (!defined($h{dst})) { | ||||||
| 677 | $log->fatal("getWriteL3: You must provide dst attribute"); | ||||||
| 678 | } | ||||||
| 679 | |||||||
| 680 | my $oWrite = Net::Write::Layer3->new(%h); | ||||||
| 681 | |||||||
| 682 | return $oWrite; | ||||||
| 683 | } | ||||||
| 684 | |||||||
| 685 | sub getWrite { | ||||||
| 686 | my $self = shift; | ||||||
| 687 | my %h = @_; | ||||||
| 688 | |||||||
| 689 | return $self->ipv6 ? $self->getWriteL2(%h) | ||||||
| 690 | : $self->getWriteL3(%h); | ||||||
| 691 | |||||||
| 692 | return; | ||||||
| 693 | } | ||||||
| 694 | |||||||
| 695 | sub tcpConnect { | ||||||
| 696 | my $self = shift; | ||||||
| 697 | my %h = @_; | ||||||
| 698 | |||||||
| 699 | my $log = $self->log; | ||||||
| 700 | |||||||
| 701 | if (!defined($h{ip})) { | ||||||
| 702 | $log->fatal("tcpConnect: You must provide ip attribute"); | ||||||
| 703 | } | ||||||
| 704 | if (!defined($h{port})) { | ||||||
| 705 | $log->fatal("tcpConnect: You must provide port attribute"); | ||||||
| 706 | } | ||||||
| 707 | |||||||
| 708 | my $mod = $self->ipv6 ? 'IO::Socket::INET6' : 'IO::Socket::INET'; | ||||||
| 709 | my $socket = $mod->new( | ||||||
| 710 | PeerHost => $h{ip}, | ||||||
| 711 | PeerPort => $h{port}, | ||||||
| 712 | Proto => 'tcp', | ||||||
| 713 | Timeout => $self->timeout, | ||||||
| 714 | ); | ||||||
| 715 | if (!defined($socket)) { | ||||||
| 716 | $log->warning("tcpConnect: [$h{ip}]:$h{port}: $!"); | ||||||
| 717 | return; | ||||||
| 718 | } | ||||||
| 719 | |||||||
| 720 | $socket->blocking(0); | ||||||
| 721 | $socket->autoflush(1); | ||||||
| 722 | |||||||
| 723 | return $socket; | ||||||
| 724 | } | ||||||
| 725 | |||||||
| 726 | 1; | ||||||
| 727 | |||||||
| 728 | __END__ |