How to convert an ip's network segment in Golang?

huangapple go评论82阅读模式
英文:

How to convert an ip's network segment in Golang?

问题

在golang中,你可以如何将"10.222.1.2/16"转换为"10.223.1.2/16"?可以将掩码视为相同。

例如:

func Netmap(ip string, dest string) string{}
Netmap("10.222.1.2/16", "10.223.0.0/16") // => "10.223.1.2/16"
Netmap("10.222.1.5/16", "10.224.0.0/16") // => "10.224.1.5/16"

==== 更新于2023/05/09 ====

@Volker:你目前尝试了什么?遇到了什么问题?

非常抱歉之前的描述不够详细。如果在纸上完成转换,我的思路如下:

How to convert an ip's network segment in Golang?

我尝试通过代码来实现这个过程,我找到了一系列可以将ip转换为:[]byte、uint32等的转换方法。

ip, ipNet, _ := net.ParseCIDR("10.222.1.2/16")
bytes := []byte(ip)
maskBits := binary.BigEndian.Uint32(ipNet.Mask)
ipBits := binary.BigEndian.Uint32(ip.To4())

prefix, _ := netip.ParsePrefix("10.222.1.2/16")
binary, _ := prefix.Addr().MarshalBinary()

但我不太确定这些东西的含义,以及如何操作这些数据。

非常感谢@Zeke Lu,我正在学习理解这行代码,我使用的位操作符太少,对它们不太熟悉:

v := ((v2 >> (32 - bits)) << (32 - bits)) | ((v1 << bits) >> bits)
英文:

In golang, how can I convert 10.222.1.2/16 to 10.223.1.2/16?
Masks can be considered the same.

For example:

func Netmap(ip string, dest string) string{}
Netmap(&quot;10.222.1.2/16&quot;, &quot;10.223.0.0/16&quot;) // =&gt; &quot;10.223.1.2/16&quot;
Netmap(&quot;10.222.1.5/16&quot;, &quot;10.224.0.0/16&quot;) // =&gt; &quot;10.224.1.5/16&quot;

==== Update 2023/05/09 ====

** @Volker: What have you tried so far? Where did you get stuck? **

I am very sorry that the previous description is not detailed enough. If the conversion is completed on paper, my thinking is as follows:

How to convert an ip's network segment in Golang?

I tried how to implement this process through code, and I found a series of conversion methods that can convert ip to: []byte, uint32, etc.

ip, ipNet, _ := net.ParseCIDR(&quot;10.222.1.2/16&quot;)
bytes := []byte(ip)
maskBits := binary.BigEndian.Uint32(ipNet.Mask)
ipBits := binary.BigEndian.Uint32(ip.To4())

prefix, _ := netip.ParsePrefix(&quot;10.222.1.2/16&quot;)
binary, _ := prefix.Addr().MarshalBinary()

But I'm not quite sure what these things mean, and how to manipulate the data.

Thank you very much @Zeke Lu, I'm learning to understand this line of code, I use too few bit operators, and I'm not familiar with them:

v := ((v2 &gt;&gt; (32 - bits)) &lt;&lt; (32 - bits)) | ((v1 &lt;&lt; bits) &gt;&gt; bits)

答案1

得分: 0

也许这是你想要的:

package main

import (
	"encoding/binary"
	"errors"
	"fmt"
	"net/netip"
)

func Netmap(ip string, dest string) (string, error) {
	v1, bits, err := parse(ip)
	if err != nil {
		return "", err
	}

	v2, bits2, err := parse(dest)
	if err != nil {
		return "", err
	}

	if bits2 != bits {
		return "", errors.New("bits not matched")
	}

	// 从v2的高位和v1的低位构造
	v := ((v2 >> (32 - bits)) << (32 - bits)) | ((v1 << bits) >> bits)

	a4 := [4]byte{}
	binary.BigEndian.PutUint32(a4[:], v)
	addr := netip.AddrFrom4(a4)

	p := netip.PrefixFrom(addr, bits)

	return p.String(), nil
}

// 解析前缀并将IPv4地址返回为uint32
func parse(prefix string) (uint32, int, error) {
	p, err := netip.ParsePrefix(prefix)
	if err != nil {
		return 0, 0, err
	}

	// 只关注IPv4
	if !p.Addr().Is4() {
		return 0, 0, errors.New("unsupported IP version")
	}

	a4 := p.Addr().As4()
	v := binary.BigEndian.Uint32(a4[:])

	return v, p.Bits(), nil
}

func main() {
	fmt.Println(Netmap("10.222.1.2/16", "10.223.0.0/16"))
	fmt.Println(Netmap("10.222.1.5/16", "10.224.0.0/16"))
}

注意:这个代码没有完全测试过,请谨慎使用。

英文:

Maybe this is what you want:

package main

import (
	&quot;encoding/binary&quot;
	&quot;errors&quot;
	&quot;fmt&quot;
	&quot;net/netip&quot;
)

func Netmap(ip string, dest string) (string, error) {
	v1, bits, err := parse(ip)
	if err != nil {
		return &quot;&quot;, err
	}

	v2, bits2, err := parse(dest)
	if err != nil {
		return &quot;&quot;, err
	}

	if bits2 != bits {
		return &quot;&quot;, errors.New(&quot;bits not matched&quot;)
	}

	// Construct from the high bits from v2 and the low bits from v1.
	v := ((v2 &gt;&gt; (32 - bits)) &lt;&lt; (32 - bits)) | ((v1 &lt;&lt; bits) &gt;&gt; bits)

	a4 := [4]byte{}
	binary.BigEndian.PutUint32(a4[:], v)
	addr := netip.AddrFrom4(a4)

	p := netip.PrefixFrom(addr, bits)

	return p.String(), nil
}

// parse parses the prefix and returns the IPv4 address as uint32.
func parse(prefix string) (uint32, int, error) {
	p, err := netip.ParsePrefix(prefix)
	if err != nil {
		return 0, 0, err
	}

	// Let&#39;s focus on IPv4.
	if !p.Addr().Is4() {
		return 0, 0, errors.New(&quot;unsupported IP version&quot;)
	}

	a4 := p.Addr().As4()
	v := binary.BigEndian.Uint32(a4[:])

	return v, p.Bits(), nil
}

func main() {
	fmt.Println(Netmap(&quot;10.222.1.2/16&quot;, &quot;10.223.0.0/16&quot;))
	fmt.Println(Netmap(&quot;10.222.1.5/16&quot;, &quot;10.224.0.0/16&quot;))
}

Note: this is not fully tested. Use with caution.

huangapple
  • 本文由 发表于 2023年5月8日 16:40:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76198867.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定