ipv4和ipv6与int互转通用处理方式
记录一下ipv4和ipv6与int互转通用处理方式,由于ipv6转的int比较大,因此需要使用big.Int来保存
另外记录一下将ip返回转换为CIDR表达方式 点击运行
package main
import (
"fmt"
"math/big"
"net/netip"
)
func IpRangeToCIDRRange(ipFrom, ipTo string) ([]string, error) {
url := "https://www.ipaddressguide.com/cidr"
if strings.IndexByte(ipFrom, '.') < 0 {
url = "https://www.ipaddressguide.com/ipv6-cidr"
}
resp, err := http.Post(url, "application/x-www-form-urlencoded",
strings.NewReader("mode=range&ipFrom="+ipFrom+"&ipTo="+ipTo))
if err != nil {
return nil, err
}
data, err := io.ReadAll(resp.Body)
_ = resp.Body.Close()
if err != nil {
return nil, err
}
if e := bytes.Index(data, []byte("</code></pre></div>")); e > 0 {
if s := bytes.LastIndexByte(data[:e], '>'); s > 0 {
return strings.Split(string(data[s+1:e]), "\n"), nil
}
}
return nil, errors.New("not find")
}
func InetNtoA(ip *big.Int, ipv4 int64) string {
if ip == nil {
return netip.AddrFrom4([4]byte{byte(ipv4 >> 24), byte(ipv4 >> 16),
byte(ipv4 >> 8), byte(ipv4)}).String()
}
var (
buf [16]byte
ipv6 = ip.Bytes()
index = len(buf) - len(ipv6)
)
if index < 0 || index >= 16 {
return ""
}
copy(buf[index:], ipv6)
return netip.AddrFrom16(buf).String()
}
func InetAtoN(ip string) (*big.Int, int64, error) {
addr, err := netip.ParseAddr(ip)
if err != nil {
return nil, 0, err
}
if addr.Is4() {
ipv4 := addr.As4()
return nil, int64(ipv4[0])<<24 | int64(ipv4[1])<<16 |
int64(ipv4[2])<<8 | int64(ipv4[3]), nil
}
ipv6 := addr.As16()
return new(big.Int).SetBytes(ipv6[:]), 0, nil
}
func main() {
ipv6 := "f000:0000:0000:0000:0000:ffff:192.168.100.228"
ipInt, ipv4, err := InetAtoN(ipv6)
if err != nil {
panic(err)
}
fmt.Println(ipInt, ipv4, InetNtoA(ipInt, ipv4))
ip := "192.168.78.123"
ipInt, ipv4, err = InetAtoN(ip)
if err != nil {
panic(err)
}
fmt.Println(ipInt, ipv4, InetNtoA(ipInt, ipv4))
}