-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathscan.go
95 lines (78 loc) · 1.87 KB
/
scan.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package scan
import (
"fmt"
"net"
"github.com/juju/errors"
)
// Scan is the structure containing the CIDR and the result
type Scan struct {
CIDR *net.IPNet `json:"CIDR"`
Result []*Result `json:"Result"`
}
// Result contains the structured output of the nmap command
type Result struct {
Host string `json:"host"`
Name string `json:"name"`
}
// New initiliazes a new Scan struct.
// If the cidr is not valid, it returns an error.
func New(cidr string) (*Scan, error) {
_, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
return nil, errors.NewNotValid(err, "")
}
return &Scan{
CIDR: ipNet,
Result: []*Result{},
}, nil
}
// Scan executes the algorithm which scans the given CIDR.
// It updates the result field contained in the Scan struct.
func (s *Scan) Scan() error {
address, err := s.getHosts()
if err != nil {
return err
}
results := []*Result{}
for _, a := range address {
host, err := net.LookupAddr(a)
// If an error occurs, it assumes that the address is not used
// in the given CIDR.
if err != nil {
continue
}
result := &Result{
Host: a,
Name: host[0],
}
results = append(results, result)
}
s.Result = results
return nil
}
// getHosts returns a slice containing all addresses from a given CIDR.
func (s *Scan) getHosts() ([]string, error) {
ip, ipnet, err := net.ParseCIDR(s.CIDR.String())
if err != nil {
return nil, err
}
var ips []string
for ipAddr := ip.Mask(ipnet.Mask); ipnet.Contains(ipAddr); inc(ipAddr) {
ips = append(ips, ipAddr.String())
}
// remove network address and broadcast address
return ips[1 : len(ips)-1], nil
}
// inc increments the given IP address.
// http://play.golang.org/p/m8TNTtygK0
func inc(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}
func (r *Result) String() string {
return fmt.Sprintf("host: %s - name: %s\n", r.Host, r.Name)
}