Skip to content

Commit 976e804

Browse files
authored
Divide code into packages; Use hosts+index to improve performance; Output Grouping. (#21)
1 parent 6903304 commit 976e804

7 files changed

Lines changed: 199 additions & 169 deletions

File tree

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
GO=go
2+
all:
3+
"$(GO)" build -o lmap cmd/lmap/main.go

cmd/lmap/main.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"github.com/LinuxHub-Group/lmap/pkg/lmap"
7+
"os"
8+
)
9+
10+
func main() {
11+
isVerbose := false
12+
flag.BoolVar(&isVerbose, "v", false, "be verbose")
13+
flag.Parse()
14+
args := flag.Args()
15+
if len(args) < 1 {
16+
fmt.Fprintf(os.Stderr, "使用方法:%s [-v] <网络号>/<CIDR>\n", os.Args[0])
17+
os.Exit(-1)
18+
}
19+
lmap.CheckIP(args[0], isVerbose)
20+
}

lmap.go

Lines changed: 0 additions & 169 deletions
This file was deleted.

pkg/lmap/check_ip.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package lmap
2+
3+
import (
4+
"fmt"
5+
"net"
6+
"os"
7+
"sync"
8+
"time"
9+
)
10+
11+
const OUTPUT_IP_PER_LINE = 5
12+
13+
func CheckIP(subnet string, isVerbose bool) {
14+
checkerGroup := &sync.WaitGroup{}
15+
t := time.Now()
16+
hosts, _ := GetAllIPsFromCIDR(subnet)
17+
isUsedList := make([]bool, len(hosts))
18+
for index, _ := range hosts {
19+
time.Sleep(500)
20+
checkerGroup.Add(1)
21+
go func(index int) {
22+
defer checkerGroup.Done()
23+
isUsed := Ping(hosts[index])
24+
isUsedList[index] = isUsed
25+
if isVerbose {
26+
if isUsed {
27+
println("已使用IP:", hosts[index].String())
28+
} else {
29+
println("未使用IP:", hosts[index].String())
30+
}
31+
}
32+
}(index)
33+
}
34+
checkerGroup.Wait()
35+
elapsed := time.Since(t)
36+
fmt.Fprintln(os.Stderr, "IP扫描完成,耗时", elapsed)
37+
println("已使用IP:")
38+
printIPList(hosts, true, isUsedList)
39+
println("未使用IP:")
40+
printIPList(hosts, false, isUsedList)
41+
}
42+
43+
func printIPList(hosts []net.IP, boolFilter bool, boolFilterTargetList []bool) {
44+
firstIndex := 0
45+
count := 0
46+
for index, ip := range hosts {
47+
if boolFilterTargetList[index] == boolFilter {
48+
fmt.Print(ip.String())
49+
firstIndex = index
50+
count = 1
51+
break
52+
}
53+
}
54+
for index := firstIndex + 1; index < len(hosts); index++ {
55+
if boolFilterTargetList[index] == boolFilter {
56+
if count%OUTPUT_IP_PER_LINE == 0 {
57+
fmt.Println("")
58+
} else {
59+
fmt.Print(", ")
60+
}
61+
fmt.Print(hosts[index].String())
62+
count++
63+
}
64+
}
65+
fmt.Println("")
66+
}

pkg/lmap/common.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package lmap
2+
3+
type ICMP struct {
4+
Type uint8
5+
Code uint8
6+
Checksum uint16
7+
Identifier uint16
8+
SequenceNum uint16
9+
}

pkg/lmap/parse_subnet.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package lmap
2+
3+
import "net"
4+
5+
func GetAllIPsFromCIDR(cidr string) ([]net.IP, error) {
6+
ip, ipnet, err := net.ParseCIDR(cidr)
7+
if err != nil {
8+
return nil, err
9+
}
10+
11+
var ips []net.IP
12+
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
13+
ips = append(ips, dupIP(ip))
14+
}
15+
if len(ips) <= 2 {
16+
return ips, nil
17+
}
18+
return ips[1 : len(ips)-1], nil
19+
}
20+
21+
func inc(ip net.IP) {
22+
for j := len(ip) - 1; j >= 0; j-- {
23+
ip[j]++
24+
if ip[j] > 0 {
25+
break
26+
}
27+
}
28+
}
29+
30+
func dupIP(ip net.IP) net.IP {
31+
// To save space, try and only use 4 bytes
32+
if x := ip.To4(); x != nil {
33+
ip = x
34+
}
35+
dup := make(net.IP, len(ip))
36+
copy(dup, ip)
37+
return dup
38+
}

pkg/lmap/ping.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package lmap
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
"log"
7+
"net"
8+
"time"
9+
)
10+
11+
func Ping(ip net.IP) bool {
12+
var icmp ICMP
13+
//开始填充数据包
14+
icmp.Type = 8 //8->echo message 0->reply message
15+
16+
recvBuf := make([]byte, 32)
17+
var buffer bytes.Buffer
18+
19+
//先在buffer中写入icmp数据报求去校验和
20+
binary.Write(&buffer, binary.BigEndian, icmp)
21+
icmp.Checksum = checkSum(buffer.Bytes())
22+
//然后清空buffer并把求完校验和的icmp数据报写入其中准备发送
23+
buffer.Reset()
24+
binary.Write(&buffer, binary.BigEndian, icmp)
25+
26+
conn, err := net.DialTimeout("ip4:icmp", ip.String(), 1*time.Second)
27+
if err != nil {
28+
return false
29+
}
30+
_, err = conn.Write(buffer.Bytes())
31+
if err != nil {
32+
log.Println("conn.Write error:", err)
33+
return false
34+
}
35+
conn.SetReadDeadline(time.Now().Add(time.Second * 2))
36+
num, err := conn.Read(recvBuf)
37+
if err != nil {
38+
return false
39+
}
40+
41+
conn.SetReadDeadline(time.Time{})
42+
43+
return string(recvBuf[0:num]) != ""
44+
}
45+
46+
func checkSum(data []byte) uint16 {
47+
var (
48+
sum uint32
49+
length int = len(data)
50+
index int
51+
)
52+
for length > 1 {
53+
sum += uint32(data[index])<<8 + uint32(data[index+1])
54+
index += 2
55+
length -= 2
56+
}
57+
if length > 0 {
58+
sum += uint32(data[index])
59+
}
60+
sum += (sum >> 16)
61+
62+
return uint16(^sum)
63+
}

0 commit comments

Comments
 (0)