diff --git a/discovery/host.go b/discovery/host.go index d5d2968..abb1fc0 100644 --- a/discovery/host.go +++ b/discovery/host.go @@ -1,12 +1,12 @@ package discovery import ( - "bytes" "fmt" "net" "time" "git.loafle.net/commons_go/logging" + "git.loafle.net/commons_go/util/net/cidr" "github.com/google/gopacket" "github.com/google/gopacket/layers" @@ -21,6 +21,16 @@ func scanHost(zone *model.Zone, dh *model.DiscoveryHost, resultChan chan interfa // doneChan <- struct{}{} return } + cr, err := cidr.NewCIDRRanger(zone.Network) + if nil != err { + errChan <- err + return + } + hostRanges, err := getTargetHostRange(dh, cr) + if nil != err { + errChan <- err + return + } arpChan := ps.OpenARP() defer func() { @@ -40,21 +50,26 @@ func scanHost(zone *model.Zone, dh *model.DiscoveryHost, resultChan chan interfa logging.Logger().Debug(fmt.Sprintf("Discovery: arp channel is closed")) return } - if h := handlePacketARP(zone, hosts, packet); nil != h { + if h := handlePacketARP(zone, cr, hosts, packet); nil != h { logging.Logger().Debug(fmt.Sprintf("Discovery: Host[%v] is founded", h)) } } } }() + if err := sendARP(ps, zone, hostRanges); nil != err { + errChan <- err + return + } + time.Sleep(30 * time.Second) } -func handlePacketARP(zone *model.Zone, hosts map[string]*model.Host, packet *layers.ARP) *model.Host { +func handlePacketARP(zone *model.Zone, cr cidr.CIDRRanger, hosts map[string]*model.Host, packet *layers.ARP) *model.Host { // logging.Logger().Debug(fmt.Sprintf("Discovery: arp packet %v", packet)) ip := net.IP(packet.SourceProtAddress) - if _, ok := hosts[ip.String()]; ok { + if _, ok := hosts[ip.String()]; ok || !cr.Contains(ip) { return nil } h := &model.Host{} @@ -67,103 +82,47 @@ func handlePacketARP(zone *model.Zone, hosts map[string]*model.Host, packet *lay return h } -func sendARP(ps pcap.PCapScanner, zone *model.Zone, dh *model.DiscoveryHost) error { +func sendARP(ps pcap.PCapScanner, zone *model.Zone, hostRanges []net.IP) error { hwAddr, err := net.ParseMAC(zone.Mac) if nil != err { return err } ip := net.ParseIP(zone.IP) - if nil != ip { + if nil == ip { return fmt.Errorf("Discovery: IP(%s) of zone is not valid", zone.IP) } - ranges, err := getTargetHostRange(zone, dh) - if nil != err { - return err - } - ethPacket := makePacketEthernet(hwAddr) arpPacket := makePacketARP(hwAddr, ip) opts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true} buf := gopacket.NewSerializeBuffer() - for _, targetHost := range ranges { + for _, targetHost := range hostRanges { arpPacket.DstProtAddress = []byte(targetHost) gopacket.SerializeLayers(buf, opts, ethPacket, arpPacket) - // if err := ps.WritePacketData(buf.Bytes()); err != nil { - // return err - // } + if err := ps.WritePacketData(buf.Bytes()); err != nil { + return err + } time.Sleep(time.Microsecond * 500) } return nil } -func getTargetHostRange(zone *model.Zone, dh *model.DiscoveryHost) ([]net.IP, error) { - nIP, nIPNet, err := net.ParseCIDR(zone.Network) - if nil != err { - return nil, fmt.Errorf("Discovery: Network(%s) of zone is not valid", zone.Network) - } - - firstIP := net.ParseIP(dh.FirstScanRange) - lastIP := net.ParseIP(dh.LastScanRange) - if nil == firstIP || nil == lastIP { - return nil, fmt.Errorf("Discovery: IP Range(First:%s, Last:%s) is not valid", dh.FirstScanRange, dh.LastScanRange) - } - - firstIP16 := firstIP.To16() - lastIP16 := lastIP.To16() - if nil == firstIP16 || nil == lastIP16 { - return nil, fmt.Errorf("Discovery: IP Range(First:%s, Last:%s) is not valid", dh.FirstScanRange, dh.LastScanRange) - } - - excludeIP16s := make([]net.IP, 0) +func getTargetHostRange(dh *model.DiscoveryHost, cr cidr.CIDRRanger) ([]net.IP, error) { + excludeIPs := make([]net.IP, 0) for _, eHost := range dh.ExcludeHosts { eIP := net.ParseIP(eHost) if nil == eIP { return nil, fmt.Errorf("Discovery: IP(%v) of exclude host is not valid", eHost) } - eIP16 := eIP.To16() - if nil == eIP16 { - return nil, fmt.Errorf("Discovery: IP(%v) of exclude host is not valid", eHost) - } - excludeIP16s = append(excludeIP16s, eIP16) + excludeIPs = append(excludeIPs, eIP) } - ranges := make([]net.IP, 0) - - ip := nIP -Loop: - for ip := ip.Mask(nIPNet.Mask); nIPNet.Contains(ip); inc(ip) { - ip16 := ip.To16() - if nil == ip16 { - return nil, fmt.Errorf("Discovery: IP(%v) converting is failed", ip) - } - - if 0 > bytes.Compare(ip16, firstIP16) || 0 < bytes.Compare(ip16, lastIP16) { - continue - } - - for _, eIP16 := range excludeIP16s { - if 0 == bytes.Compare(eIP16, ip16) { - continue Loop - } - } - - ranges = append(ranges, ip) - } + ranges := cr.Range(excludeIPs) return ranges, nil } -func inc(ip net.IP) { - for j := len(ip) - 1; j >= 0; j-- { - ip[j]++ - if ip[j] > 0 { - break - } - } -} - func makePacketEthernet(hw net.HardwareAddr) *layers.Ethernet { return &layers.Ethernet{ SrcMAC: hw,