nicer scan result path /tmp/nmap.what, store scan result in CouchDB
[pxelator] / lib / PXElator / nmap.pm
1 package nmap;
2
3 use warnings;
4 use strict;
5
6 use XML::Simple;
7 use Data::Dump qw/dump/;
8 use CouchDB;
9
10 use client;
11
12 sub scan {
13         my $what = shift;
14
15         my $path = $what;
16         $path =~ s{[^\w\d\.]+}{_}g;
17         $path = "/tmp/nmap.$path";
18
19         warn "# scan $what";
20
21         unlink $path if -f $path;
22
23         system("nmap -O -oX $path $what");
24
25         my $nmap = XMLin(
26                 "$path",
27                 KeyAttr => { address => 'addrtype' },
28                 ForceArray => [ 'host', 'address', 'osmatch', 'port' ],
29         );
30
31         CouchDB::audit( $what, $nmap );
32
33         my $count = 0;
34
35         while ( my $host = shift @{ $nmap->{host} } ) {
36
37                 warn '# host ',dump( $host );
38
39                 my $ip  = $host->{address}->{ipv4}->{addr} || die "ipv4";
40
41                 if ( my $mac = $host->{address}->{mac}->{addr} ) {
42                         print "$ip\t$mac\n";
43                         client::save_ip_mac( $ip, $mac );
44                 }
45
46                 if ( my $os = $host->{os}->{osmatch}->[0]->{name} ) {
47                         client::conf( $ip, 'os' => $os );
48                 }
49
50                 my @ports = map { [ $_->{portid}, $_->{protocol}, $_->{service}->{name} ] } @{ $host->{ports}->{port} };
51                 client::conf( $ip, 'ports' => join("\n", map { join("\t", @$_) } @ports) ) if @ports;
52
53                 $count++;
54         }
55
56         warn "# finish $count hosts";
57
58         return $count;
59 }
60
61 1;