ip范围转换为CIDR

jan-bar · · 647 次点击 · 开始浏览    置顶

兼容ipv4和ipv6的方案,将ip范围转换为CIDR表示。 在线运行: <https://go.dev/play/p/Ynx1liLAGs2> ```go package main import ( "errors" "fmt" "math/big" "net/netip" "strconv" "strings" ) // Verify the result in the following way // https://www.ipaddressguide.com/cidr // https://www.ipaddressguide.com/ipv6-cidr func IpRangeToCIDR(cidr []string, start, end string) ([]string, error) { ips, err := netip.ParseAddr(start) if err != nil { return nil, err } ipe, err := netip.ParseAddr(end) if err != nil { return nil, err } isV4 := ips.Is4() if isV4 != ipe.Is4() { return nil, errors.New("start and end types are different") } if ips.Compare(ipe) > 0 { return nil, errors.New("start > end") } var ( ipsInt = new(big.Int).SetBytes(ips.AsSlice()) ipeInt = new(big.Int).SetBytes(ipe.AsSlice()) tmpInt = new(big.Int) mask = new(big.Int) one = big.NewInt(1) buf []byte bits, maxBit uint ) if isV4 { maxBit = 32 buf = make([]byte, 4) } else { maxBit = 128 buf = make([]byte, 16) } for { bits = 1 mask.SetUint64(1) for bits < maxBit { if (tmpInt.Or(ipsInt, mask).Cmp(ipeInt) > 0) || (tmpInt.Lsh(tmpInt.Rsh(ipsInt, bits), bits).Cmp(ipsInt) != 0) { bits-- mask.Rsh(mask, 1) break } bits++ mask.Add(mask.Lsh(mask, 1), one) } addr, _ := netip.AddrFromSlice(ipsInt.FillBytes(buf)) cidr = append(cidr, addr.String()+"/"+strconv.FormatUint(uint64(maxBit-bits), 10)) if tmpInt.Or(ipsInt, mask); tmpInt.Cmp(ipeInt) >= 0 { break } ipsInt.Add(tmpInt, one) } return cidr, nil } func main() { start, end := "10.5.6.0", "10.23.25.255" cidr, err := IpRangeToCIDR(nil, start, end) if err != nil { panic(err) } fmt.Println(strings.Join(cidr, "\n")) start = "2001:4860:4860:0000:0000:0000:0000:8888" end = "2001:4860:4860:0000:0000:0000:4567:1234" cidr, err = IpRangeToCIDR(cidr[:0], start, end) if err != nil { panic(err) } fmt.Println(strings.Join(cidr, "\n")) } ```

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

647 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传