k3s/vendor/github.com/flannel-io/flannel/pkg/ip/ipnet.go
Manuel Buil 681058bb40 Add dual-stack support
Signed-off-by: Manuel Buil <mbuil@suse.com>
2021-09-15 11:44:48 +02:00

192 lines
4.0 KiB
Go

// Copyright 2015 flannel authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ip
import (
"bytes"
"errors"
"fmt"
"net"
)
type IP4 uint32
func FromBytes(ip []byte) IP4 {
return IP4(uint32(ip[3]) |
(uint32(ip[2]) << 8) |
(uint32(ip[1]) << 16) |
(uint32(ip[0]) << 24))
}
func FromIP(ip net.IP) IP4 {
ipv4 := ip.To4()
if ipv4 == nil {
panic("Address is not an IPv4 address")
}
return FromBytes(ipv4)
}
func ParseIP4(s string) (IP4, error) {
ip := net.ParseIP(s)
if ip == nil {
return IP4(0), errors.New("Invalid IP address format")
}
return FromIP(ip), nil
}
func MustParseIP4(s string) IP4 {
ip, err := ParseIP4(s)
if err != nil {
panic(err)
}
return ip
}
func (ip IP4) Octets() (a, b, c, d byte) {
a, b, c, d = byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)
return
}
func (ip IP4) ToIP() net.IP {
return net.IPv4(ip.Octets())
}
func (ip IP4) NetworkOrder() uint32 {
if NativelyLittle() {
a, b, c, d := byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)
return uint32(a) | (uint32(b) << 8) | (uint32(c) << 16) | (uint32(d) << 24)
} else {
return uint32(ip)
}
}
func (ip IP4) String() string {
return ip.ToIP().String()
}
func (ip IP4) StringSep(sep string) string {
a, b, c, d := ip.Octets()
return fmt.Sprintf("%d%s%d%s%d%s%d", a, sep, b, sep, c, sep, d)
}
// MarshalJSON: json.Marshaler impl
func (ip IP4) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, ip)), nil
}
// UnmarshalJSON: json.Unmarshaler impl
func (ip *IP4) UnmarshalJSON(j []byte) error {
j = bytes.Trim(j, "\"")
if val, err := ParseIP4(string(j)); err != nil {
return err
} else {
*ip = val
return nil
}
}
// similar to net.IPNet but has uint based representation
type IP4Net struct {
IP IP4
PrefixLen uint
}
func (n IP4Net) String() string {
return fmt.Sprintf("%s/%d", n.IP.String(), n.PrefixLen)
}
func (n IP4Net) StringSep(octetSep, prefixSep string) string {
return fmt.Sprintf("%s%s%d", n.IP.StringSep(octetSep), prefixSep, n.PrefixLen)
}
func (n IP4Net) Network() IP4Net {
return IP4Net{
n.IP & IP4(n.Mask()),
n.PrefixLen,
}
}
func (n IP4Net) Next() IP4Net {
return IP4Net{
n.IP + (1 << (32 - n.PrefixLen)),
n.PrefixLen,
}
}
// IncrementIP() increments the IP of IP4Net CIDR by 1
func (n *IP4Net) IncrementIP() {
n.IP++
}
func FromIPNet(n *net.IPNet) IP4Net {
prefixLen, _ := n.Mask.Size()
return IP4Net{
FromIP(n.IP),
uint(prefixLen),
}
}
func (n IP4Net) ToIPNet() *net.IPNet {
return &net.IPNet{
IP: n.IP.ToIP(),
Mask: net.CIDRMask(int(n.PrefixLen), 32),
}
}
func (n IP4Net) Overlaps(other IP4Net) bool {
var mask uint32
if n.PrefixLen < other.PrefixLen {
mask = n.Mask()
} else {
mask = other.Mask()
}
return (uint32(n.IP) & mask) == (uint32(other.IP) & mask)
}
func (n IP4Net) Equal(other IP4Net) bool {
return n.IP == other.IP && n.PrefixLen == other.PrefixLen
}
func (n IP4Net) Mask() uint32 {
var ones uint32 = 0xFFFFFFFF
return ones << (32 - n.PrefixLen)
}
func (n IP4Net) Contains(ip IP4) bool {
return (uint32(n.IP) & n.Mask()) == (uint32(ip) & n.Mask())
}
func (n IP4Net) Empty() bool {
return n.IP == IP4(0) && n.PrefixLen == uint(0)
}
// MarshalJSON: json.Marshaler impl
func (n IP4Net) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, n)), nil
}
// UnmarshalJSON: json.Unmarshaler impl
func (n *IP4Net) UnmarshalJSON(j []byte) error {
j = bytes.Trim(j, "\"")
if _, val, err := net.ParseCIDR(string(j)); err != nil {
return err
} else {
*n = FromIPNet(val)
return nil
}
}