新增多个ip地址判断是否在配置ip范围内判断方法

master
chenxuanyu 2 years ago
parent d263760b26
commit 3794b39bad
  1. 104
      check.go

@ -2,7 +2,9 @@ package ipcheck
import (
"errors"
"fmt"
"gitea.drugeyes.vip/pharnexbase/ipcheck/utils"
"sort"
"strings"
)
@ -22,7 +24,7 @@ func SingleIpInRange(ip, ipConfigStr string) (bool, error) {
for _, ipConfig := range ipConfigArr {
containIp := utils.NewIpRange(ipConfig)
if containIp != nil && singleIp.Type() == containIp.Type() { //只有ip类型相同才判断范围
if containIp.IsContain(singleIp) == true {
if containIp.IsContain(singleIp) {
return true, nil
}
}
@ -30,3 +32,103 @@ func SingleIpInRange(ip, ipConfigStr string) (bool, error) {
return false, nil
}
// MultipleIpInRange 多个ip地址判断是否在配置ip范围内(该方法在ips很多,且配置ip很多的时候会有速度提升,单个ip的时候不建议使用该方法)
func MultipleIpInRange(ips, ipConfigStr []string) (bool, string, error) {
ownerIpv4s, ownerIpv6s, errIp, err := FilterIpAndSort(ips)
if err != nil {
return false, errIp, err
}
containIpv4s, containIpv6s, errIp, err := FilterIpAndSort(strings.Split(strings.ReplaceAll(strings.Join(ipConfigStr, "\n"), "\r\n", "\n"), "\n"))
if err != nil {
return false, errIp, err
}
//优化步骤
var ipv4Start uint32 = 0 //自己ip段重复也需要提示
//处理判断ipv4(双指针)
for i, j := 0, 0; i < len(ownerIpv4s) && j < len(containIpv4s); {
ownerLeft := utils.Ipv4ToUint32(ownerIpv4s[i][0])
ownerRight := utils.Ipv4ToUint32(ownerIpv4s[i][1])
if ownerLeft > utils.Ipv4ToUint32(containIpv4s[j][1]) { //如果范围ip右边值都比目标ip的左边值小则增加范围ip的指针
j++
continue
}
if containIpv4s[j].IsContain(ownerIpv4s[i]) || ownerIpv4s[i].IsContain(containIpv4s[j]) {
return true, fmt.Sprintf("%s<-->%s", ownerIpv4s[i].IpString(), containIpv4s[j].IpString()), errors.New("输入ip与已存在ip配置范围重叠!")
}
if ipv4Start >= ownerLeft { //判断自己ip段是否重复,重复就返回重复的ip
if i > 0 {
return false, fmt.Sprintf("%s<-->%s", ownerIpv4s[i-1].IpString(), ownerIpv4s[i].IpString()), errors.New("输入ip范围重叠!")
}
return false, ownerIpv4s[i].IpString(), errors.New("请勿填写0.0.0.0和0:0:0:0:0:0:0:0等无效ip!")
}
ipv4Start = ownerRight
i++
}
var ipv6Start = utils.Uint128{H: 0, L: 0} //自己ip段重复也需要提示
//处理判断ipv6(双指针)
for i, j := 0, 0; i < len(ownerIpv6s) && j < len(containIpv6s); {
ownerLeft := utils.Ipv6ToUint128(ownerIpv6s[i][0])
ownerRight := utils.Ipv6ToUint128(ownerIpv6s[i][1])
containRight := utils.Ipv6ToUint128(containIpv6s[j][1])
if (ownerLeft.H > containRight.H) || (ownerLeft.H == containRight.H && ownerLeft.L > containRight.L) {
j++
continue
}
if containIpv6s[j].IsContain(ownerIpv6s[i]) || ownerIpv6s[i].IsContain(containIpv6s[j]) {
return true, fmt.Sprintf("%s<-->%s", ownerIpv6s[i].IpString(), containIpv6s[j].IpString()), errors.New("输入ip与已存在ip配置范围重叠!")
}
if (ipv6Start.H > ownerLeft.H) || (ipv6Start.H == ownerLeft.H && ipv6Start.L >= ownerLeft.L) { //判断自己ip段是否重复,重复就返回重复的ip
if i > 0 {
return false, fmt.Sprintf("%s<-->%s", ownerIpv6s[i-1].IpString(), ownerIpv6s[i].IpString()), errors.New("输入ip范围重叠!")
}
return false, ownerIpv6s[i].IpString(), errors.New("请勿填写0.0.0.0和0:0:0:0:0:0:0:0等无效ip!")
}
ipv6Start = ownerRight
i++
}
return false, "", nil
}
// FilterIpAndSort 筛选出ipv4和ipv6并排序
func FilterIpAndSort(ips []string) (ipv4s []utils.Ipv4, ipv6s []utils.Ipv6, errIp string, err error) {
for _, ip := range ips {
ownerIp := utils.NewIpRange(ip)
if ownerIp == nil {
return ipv4s, ipv6s, ip, errors.New("ip格式错误!")
}
//判断ip范围是否满足从小到大的规则
if err := ownerIp.CheckIpRange(); err != nil {
return ipv4s, ipv6s, ip, err
}
if ownerIp.Type() == utils.Ipv4Type {
ipv4s = append(ipv4s, ownerIp.(utils.Ipv4))
} else {
ipv6s = append(ipv6s, ownerIp.(utils.Ipv6))
}
}
//处理排序
sort.Slice(ipv4s, func(i, j int) bool {
return utils.Ipv4ToUint32(ipv4s[i][0]) < utils.Ipv4ToUint32(ipv4s[j][0])
})
sort.Slice(ipv6s, func(i, j int) bool {
if utils.Ipv6ToUint128(ipv6s[i][0]).H < utils.Ipv6ToUint128(ipv6s[j][0]).H {
return true
}
return utils.Ipv6ToUint128(ipv6s[i][0]).H == utils.Ipv6ToUint128(ipv6s[j][0]).H && utils.Ipv6ToUint128(ipv6s[i][0]).L < utils.Ipv6ToUint128(ipv6s[j][0]).L
})
return
}

Loading…
Cancel
Save