package common import ( "bufio" "errors" "fmt" "net" "os" "regexp" "strconv" "strings" ) var ParseIPErr = errors.New(" host parsing error\n" + "format: \n" + "192.168.1.1\n" + "192.168.1.1/8\n" + "192.168.1.1/16\n" + "192.168.1.1/24\n" + "192.168.1.1,192.168.1.2\n" + "192.168.1.1-192.168.255.255\n" + "192.168.1.1-255") func ParseIP(ip string, filename string) (hosts []string, err error) { if ip != "" { hosts, err = ParseIPs(ip) } if filename != "" { var filehost []string filehost, _ = Readipfile(filename) hosts = append(hosts, filehost...) } hosts = RemoveDuplicate(hosts) return hosts, err } func ParseIPs(ip string) (hosts []string, err error) { if strings.Contains(ip, ",") { IPList := strings.Split(ip, ",") var ips []string for _, ip := range IPList { ips, err = ParseIPone(ip) CheckErr(ip, err) hosts = append(hosts, ips...) } return hosts, err } else { hosts, err = ParseIPone(ip) CheckErr(ip, err) return hosts, err } } func ParseIPone(ip string) ([]string, error) { reg := regexp.MustCompile(`[a-zA-Z]+`) switch { case strings.Contains(ip[len(ip)-3:], "/24"): return ParseIPA(ip) case strings.Contains(ip[len(ip)-3:], "/16"): return ParseIPD(ip) case strings.Contains(ip[len(ip)-2:], "/8"): return ParseIPE(ip) case strings.Count(ip, "-") == 1: return ParseIPC(ip) case reg.MatchString(ip): _, err := net.LookupHost(ip) if err != nil { return nil, err } return []string{ip}, nil default: testIP := net.ParseIP(ip) if testIP == nil { return nil, ParseIPErr } return []string{ip}, nil } } //Parsing CIDR IP func ParseIPA(ip string) ([]string, error) { realIP := ip[:len(ip)-3] testIP := net.ParseIP(realIP) if testIP == nil { return nil, ParseIPErr } IPrange := strings.Join(strings.Split(realIP, ".")[0:3], ".") var AllIP []string for i := 0; i <= 255; i++ { AllIP = append(AllIP, IPrange+"."+strconv.Itoa(i)) } return AllIP, nil } //Resolving a range of IP,for example: 192.168.111.1-255,192.168.111.1-192.168.112.255 func ParseIPC(ip string) ([]string, error) { IPRange := strings.Split(ip, "-") testIP := net.ParseIP(IPRange[0]) var AllIP []string if len(IPRange[1]) < 4 { Range, err := strconv.Atoi(IPRange[1]) if testIP == nil || Range > 255 || err != nil { return nil, ParseIPErr } SplitIP := strings.Split(IPRange[0], ".") ip1, err1 := strconv.Atoi(SplitIP[3]) ip2, err2 := strconv.Atoi(IPRange[1]) PrefixIP := strings.Join(SplitIP[0:3], ".") if ip1 > ip2 || err1 != nil || err2 != nil { return nil, ParseIPErr } for i := ip1; i <= ip2; i++ { AllIP = append(AllIP, PrefixIP+"."+strconv.Itoa(i)) } } else { SplitIP1 := strings.Split(IPRange[0], ".") SplitIP2 := strings.Split(IPRange[1], ".") if len(SplitIP1) != 4 || len(SplitIP2) != 4 { return nil, ParseIPErr } start, end := [4]int{}, [4]int{} for i := 0; i < 4; i++ { ip1, err1 := strconv.Atoi(SplitIP1[i]) ip2, err2 := strconv.Atoi(SplitIP2[i]) if ip1 > ip2 || err1 != nil || err2 != nil { return nil, ParseIPErr } start[i], end[i] = ip1, ip2 } startNum := start[0]<<24 | start[1]<<16 | start[2]<<8 | start[3] endNum := end[0]<<24 | end[1]<<16 | end[2]<<8 | end[3] for num := startNum; num <= endNum; num++ { ip := strconv.Itoa((num>>24)&0xff) + "." + strconv.Itoa((num>>16)&0xff) + "." + strconv.Itoa((num>>8)&0xff) + "." + strconv.Itoa((num)&0xff) AllIP = append(AllIP, ip) } } return AllIP, nil } func ParseIPD(ip string) ([]string, error) { realIP := ip[:len(ip)-3] testIP := net.ParseIP(realIP) if testIP == nil { return nil, ParseIPErr } IPrange := strings.Join(strings.Split(realIP, ".")[0:2], ".") var AllIP []string for a := 0; a <= 255; a++ { for b := 0; b <= 255; b++ { AllIP = append(AllIP, IPrange+"."+strconv.Itoa(a)+"."+strconv.Itoa(b)) } } return AllIP, nil } func ParseIPE(ip string) ([]string, error) { realIP := ip[:len(ip)-2] testIP := net.ParseIP(realIP) if testIP == nil { return nil, ParseIPErr } IPrange := strings.Join(strings.Split(realIP, ".")[0:1], ".") var AllIP []string for a := 0; a <= 255; a++ { for b := 0; b <= 255; b++ { AllIP = append(AllIP, IPrange+"."+strconv.Itoa(a)+"."+strconv.Itoa(b)+"."+strconv.Itoa(1)) AllIP = append(AllIP, IPrange+"."+strconv.Itoa(a)+"."+strconv.Itoa(b)+"."+strconv.Itoa(254)) } } return AllIP, nil } func Readipfile(filename string) ([]string, error) { file, err := os.Open(filename) if err != nil { fmt.Println("Open %s error, %v", filename, err) os.Exit(0) } defer file.Close() var content []string scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanLines) for scanner.Scan() { text := strings.TrimSpace(scanner.Text()) if text != "" { host, err := ParseIPs(text) CheckErr(text, err) content = append(content, host...) } } return content, nil } func RemoveDuplicate(old []string) []string { result := make([]string, 0, len(old)) temp := map[string]struct{}{} for _, item := range old { if _, ok := temp[item]; !ok { temp[item] = struct{}{} result = append(result, item) } } return result }