判断ip是否满足规则
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ipcheck/utils/ip.go

144 lines
3.6 KiB

package utils
import (
"errors"
"net"
"strings"
)
const (
Ipv4Type = "ipv4"
Ipv6Type = "ipv6"
)
type (
Ipv4 [2]net.IP
Ipv6 [2]net.IP
)
type IpInter interface {
Type() string
CheckIpRange() error
IpString() string
IsContain(target IpInter) bool
}
//NewIpRange 创建一个ipv4或者ipv6的范围,如果为nil则是错误ip
func NewIpRange(s string) IpInter {
ipArr := strings.Split(s, "-")
if len(ipArr) == 1 {
ipArr = append(ipArr, ipArr[0])
}
var ips [2]net.IP
for i, v := range ipArr {
ip := net.ParseIP(v)
if ip == nil {
return nil
}
ips[i] = ip
}
for i := 0; i < len(s); i++ {
switch s[i] {
case '.':
return Ipv4(ips)
case ':':
return Ipv6(ips)
}
}
return nil
}
// Type 获取ip类型
func (i Ipv4) Type() string {
return Ipv4Type
}
func (i Ipv6) Type() string {
return Ipv6Type
}
// CheckIpRange 判断ip范围是否是由小到大
func (i Ipv4) CheckIpRange() error {
for j := 0; j < 16; j++ {
if i[0][j] < i[1][j] {
return nil
}
if i[0][j] > i[1][j] {
return errors.New("ip范围错误,不是由小到大配置!")
}
}
return nil
}
func (i Ipv6) CheckIpRange() error {
for j := 0; j < 16; j++ {
if i[0][j] < i[1][j] {
return nil
}
if i[0][j] > i[1][j] {
return errors.New("ip范围错误,不是由小到大配置!")
}
}
return nil
}
// IpString 返回ip的字符串
func (i Ipv4) IpString() string {
if i[0].String() == i[1].String() {
return i[0].String()
}
return strings.Join([]string{i[0].String(), i[1].String()}, "-")
}
func (i Ipv6) IpString() string {
if i[0].String() == i[1].String() {
return i[0].String()
}
return strings.Join([]string{i[0].String(), i[1].String()}, "-")
}
// IsContain 判断当前ip范围是否包含在目标配置ip范围内
func (i Ipv4) IsContain(target IpInter) bool {
iLeft := Ipv4ToUint32(i[0])
iRight := Ipv4ToUint32(i[1])
tLeft := Ipv4ToUint32(target.(Ipv4)[0])
tRight := Ipv4ToUint32(target.(Ipv4)[1])
if tLeft == tRight {
return i.isContainSingleIp(iLeft, iRight, tLeft)
}
return i.isContainSingleIp(iLeft, iRight, tLeft) || i.isContainSingleIp(iLeft, iRight, tRight)
}
func (i Ipv6) IsContain(target IpInter) bool {
iLeft := Ipv6ToUint128(i[0])
iRight := Ipv6ToUint128(i[1])
tLeft := Ipv6ToUint128(target.(Ipv6)[0])
tRight := Ipv6ToUint128(target.(Ipv6)[1])
if tLeft == tRight {
return i.isContainSingleIp(iLeft, iRight, tLeft)
}
return i.isContainSingleIp(iLeft, iRight, tLeft) || i.isContainSingleIp(iLeft, iRight, tRight)
}
// isContainSingleIp 判断当前ip范围中的单个ip是否包含在目标配置ip范围内
func (i Ipv4) isContainSingleIp(iLeft, iRight, targetIp uint32) bool {
return iLeft <= targetIp && iRight >= targetIp
}
func (i Ipv6) isContainSingleIp(iLeft, iRight, targetIp Uint128) bool {
return iLeft.H <= targetIp.H && iRight.H >= targetIp.H && iLeft.L <= targetIp.L && iRight.L >= targetIp.L
}
// Ipv4ToUint32 把ipv4转为uint32
func Ipv4ToUint32(ipv4 net.IP) uint32 {
b := ipv4.To4()
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}
// Ipv6ToUint128 把ipv6转为uint128
func Ipv6ToUint128(Ipv6 net.IP) Uint128 {
return makeUint128([]uint32{uint32(Ipv6[0])<<24 | uint32(Ipv6[1])<<16 | uint32(Ipv6[2])<<8 | uint32(Ipv6[3]), uint32(Ipv6[4])<<24 | uint32(Ipv6[5])<<16 | uint32(Ipv6[6])<<8 | uint32(Ipv6[7]), uint32(Ipv6[8])<<24 | uint32(Ipv6[9])<<16 | uint32(Ipv6[10])<<8 | uint32(Ipv6[11]), uint32(Ipv6[12])<<24 | uint32(Ipv6[13])<<16 | uint32(Ipv6[14])<<8 | uint32(Ipv6[15])})
}
func makeUint128(a []uint32) Uint128 {
return Uint128{H: uint64(a[0])<<32 | uint64(a[1]),
L: uint64(a[2])<<32 | uint64(a[3])}
}