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,v 451c3602d7b2 2015/11/25 06:13:53 gomor $ | ||||||
3 | # | ||||||
4 | package Net::SinFP3::Global; | ||||||
5 | 1 | 1 | 976 | use strict; | |||
1 | 2 | ||||||
1 | 30 | ||||||
6 | 1 | 1 | 161 | use warnings; | |||
1 | 2 | ||||||
1 | 37 | ||||||
7 | |||||||
8 | 1 | 1 | 5 | use base qw(Class::Gomor::Array); | |||
1 | 2 | ||||||
1 | 210 | ||||||
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 | 6 | use File::Glob ':globally'; | |||
1 | 2 | ||||||
1 | 62 | ||||||
68 | 1 | 1 | 2051 | use IO::Socket::INET; | |||
1 | 23499 | ||||||
1 | 7 | ||||||
69 | 1 | 1 | 1465 | use IO::Socket::INET6; | |||
1 | 5377 | ||||||
1 | 7 | ||||||
70 | 1 | 1 | 2457 | 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__ |