github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/ipaddr/ipaddr.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package ipaddr
    12  
    13  import (
    14  	"bytes"
    15  	"encoding/binary"
    16  	"io"
    17  	"math"
    18  	"math/rand"
    19  	"net"
    20  	"strconv"
    21  	"strings"
    22  
    23  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgcode"
    24  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgerror"
    25  	"github.com/cockroachdb/cockroachdb-parser/pkg/util/uint128"
    26  	"github.com/cockroachdb/errors"
    27  )
    28  
    29  var errResultOutOfRange = pgerror.WithCandidateCode(errors.New("result out of range"), pgcode.NumericValueOutOfRange)
    30  
    31  // Addr is the representation of the IP address. The Uint128 takes 16-bytes for
    32  // both IPv4 and IPv6.
    33  type Addr uint128.Uint128
    34  
    35  // IPAddr stores an IP address's family, IP, and host mask. This was chosen over
    36  // Go's "net" IP, as that struct doesn't work well for what we need to do.
    37  //   - It discards information when parsing IPv4, forcing it to be IPv6, and then
    38  //     assuming IPv4-mapped IPv6 addresses are purely IPv4 (only for printing).
    39  //     This is solved by having a Family field.
    40  //   - ParseIP and ParseCIDR are very strict, whereas postgres' INET and CIDR
    41  //     have very relaxed constraints for parsing an IP.
    42  //   - Doing int64 operations is much more efficient than byte slice operations.
    43  type IPAddr struct {
    44  	// Family denotes what type of IP the original IP was.
    45  	Family IPFamily
    46  	Mask   byte
    47  	Addr   Addr
    48  }
    49  
    50  // IPFamily denotes which classification the IP belongs to.
    51  type IPFamily byte
    52  
    53  const (
    54  	// IPv4family is for IPs in the IPv4 space.
    55  	IPv4family IPFamily = iota
    56  	// IPv6family is for IPs in the IPv6 space.
    57  	IPv6family
    58  )
    59  
    60  // IPv4size 1 byte for family, 1 byte for mask, 4 for IP.
    61  const IPv4size = net.IPv4len + 2
    62  
    63  // IPv6size 1 byte for family, 1 byte for mask, 16 for IP.
    64  const IPv6size = net.IPv6len + 2
    65  
    66  // IPv4mappedIPv6prefix is the byte prefix for IPv4-mapped IPv6.
    67  const IPv4mappedIPv6prefix = uint64(0xFFFF) << 32
    68  
    69  // IPv4mask is used to select only the lower 32 bits of uint128.
    70  // IPv4 addresses may not have the upper 96 bits of Addr set to 0.
    71  // IPv4 addresses mapped to IPv6 have prefix bits that should not change.
    72  const IPv4mask = uint64(0xFFFFFFFF)
    73  
    74  // IPv4max is used for overflows.
    75  const IPv4max = IPv4mask
    76  
    77  // ToBuffer appends the IPAddr encoding to a buffer and returns the final buffer.
    78  func (ipAddr *IPAddr) ToBuffer(appendTo []byte) []byte {
    79  	// Record the family as the first byte and the mask size as the second byte.
    80  	appendTo = append(appendTo, byte(ipAddr.Family), ipAddr.Mask)
    81  	if ipAddr.Family == IPv4family {
    82  		appendTo = append(appendTo, 0, 0, 0, 0)
    83  		binary.BigEndian.PutUint32(appendTo[len(appendTo)-4:], uint32(ipAddr.Addr.Lo))
    84  	} else {
    85  		appendTo = append(appendTo, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
    86  		binary.BigEndian.PutUint64(appendTo[len(appendTo)-16:len(appendTo)-8], ipAddr.Addr.Hi)
    87  		binary.BigEndian.PutUint64(appendTo[len(appendTo)-8:], ipAddr.Addr.Lo)
    88  	}
    89  	return appendTo
    90  }
    91  
    92  // FromBuffer populates an IPAddr with data from a byte slice, returning the
    93  // remaining buffer or an error.
    94  func (ipAddr *IPAddr) FromBuffer(data []byte) ([]byte, error) {
    95  	ipAddr.Family = IPFamily(data[0])
    96  	if ipAddr.Family != IPv4family && ipAddr.Family != IPv6family {
    97  		return nil, errors.AssertionFailedf(
    98  			"IPAddr decoding error: unexpected family, got %d", errors.Safe(ipAddr.Family))
    99  	}
   100  	ipAddr.Mask = data[1]
   101  
   102  	if ipAddr.Family == IPv4family {
   103  		ipAddr.Addr.Lo = uint64(binary.BigEndian.Uint32(data[2:])) | IPv4mappedIPv6prefix
   104  		return data[IPv4size:], nil
   105  	}
   106  	ipAddr.Addr = Addr(uint128.FromBytes(data[2:]))
   107  	return data[IPv6size:], nil
   108  }
   109  
   110  // String will convert the IP to the appropriate family formatted string
   111  // representation. In order to retain postgres compatibility we ensure
   112  // IPv4-mapped IPv6 stays in IPv6 format, unlike net.Addr.String().
   113  func (ipAddr IPAddr) String() string {
   114  	ip := net.IP(uint128.Uint128(ipAddr.Addr).GetBytes())
   115  	isIPv4MappedIPv6 := ipAddr.Family == IPv6family && ip.Equal(ip.To4())
   116  	var maskSize byte
   117  
   118  	if ipAddr.Family == IPv4family {
   119  		maskSize = 32
   120  	} else {
   121  		maskSize = 128
   122  	}
   123  	if ipAddr.Mask == maskSize && isIPv4MappedIPv6 {
   124  		return "::ffff:" + ip.String()
   125  	} else if ipAddr.Mask == maskSize {
   126  		return ip.String()
   127  	} else if isIPv4MappedIPv6 {
   128  		// Due to an issue with IPv4-mapped IPv6 the mask is also reduced to an IPv4
   129  		// mask during net.IPNet.String, so we need to add the mask manually.
   130  		return "::ffff:" + ip.String() + "/" + strconv.Itoa(int(ipAddr.Mask))
   131  	}
   132  	return ip.String() + "/" + strconv.Itoa(int(ipAddr.Mask))
   133  }
   134  
   135  // Compare two IPAddrs. IPv4-mapped IPv6 addresses are not equal to their IPv4
   136  // mapping. The order of order importance goes Family > Mask > IP-bytes.
   137  func (ipAddr IPAddr) Compare(other *IPAddr) int {
   138  	if ipAddr.Family < other.Family {
   139  		return -1
   140  	} else if ipAddr.Family > other.Family {
   141  		return 1
   142  	}
   143  
   144  	if ipAddr.Mask < other.Mask {
   145  		return -1
   146  	} else if ipAddr.Mask > other.Mask {
   147  		return 1
   148  	}
   149  	return ipAddr.Addr.Compare(other.Addr)
   150  }
   151  
   152  // Equal checks if the family, mask, and IP are equal.
   153  func (ipAddr *IPAddr) Equal(other *IPAddr) bool {
   154  	return ipAddr.Family == other.Family && ipAddr.Mask == other.Mask && ipAddr.Addr.Equal(other.Addr)
   155  }
   156  
   157  // getFamily checks what family the ip is in. If it doesn't appear to match
   158  // either, getFamily returns -1.
   159  func getFamily(addr string) IPFamily {
   160  	// Get the family of the IP.
   161  	for i := 0; i < len(addr); i++ {
   162  		switch addr[i] {
   163  		case '.':
   164  			return IPv4family
   165  		case ':':
   166  			return IPv6family
   167  		}
   168  	}
   169  	// Default to IPv4, as we need to handle '192/10'.
   170  	return IPv4family
   171  }
   172  
   173  // ParseINet parses postgres style INET types. See TestIPAddrParseINet for
   174  // examples.
   175  func ParseINet(s string, dest *IPAddr) error {
   176  	var maskSize byte
   177  	i := strings.IndexByte(s, '/')
   178  	family := getFamily(s)
   179  
   180  	// If no mask suffix was provided, implicitly don't mask.
   181  	if i < 0 {
   182  		// Trims IPv4 suffix "." to match postgres compitibility.
   183  		addr := s
   184  		if family == IPv4family {
   185  			addr = strings.TrimRight(addr, ".")
   186  			maskSize = 32
   187  		} else {
   188  			maskSize = 128
   189  		}
   190  		ip := ParseIP(addr)
   191  		if ip == nil {
   192  			return pgerror.WithCandidateCode(
   193  				errors.Errorf("could not parse %q as inet. invalid IP", s),
   194  				pgcode.InvalidTextRepresentation)
   195  		}
   196  
   197  		*dest = IPAddr{Family: family,
   198  			Addr: Addr(uint128.FromBytes(ip)),
   199  			Mask: maskSize,
   200  		}
   201  		return nil
   202  	}
   203  
   204  	addr, maskStr := s[:i], s[i+1:]
   205  	// Trims IPv4 suffix "." to match postgres compitibility.
   206  	if family == IPv4family {
   207  		addr = strings.TrimRight(addr, ".")
   208  	}
   209  	maskOnes, err := strconv.Atoi(maskStr)
   210  	if err != nil {
   211  		return pgerror.WithCandidateCode(
   212  			errors.Errorf("could not parse %q as inet. invalid mask", s),
   213  			pgcode.InvalidTextRepresentation)
   214  	} else if maskOnes < 0 || (family == IPv4family && maskOnes > 32) || (family == IPv6family && maskOnes > 128) {
   215  		return pgerror.WithCandidateCode(
   216  			errors.Errorf("could not parse %q as inet. invalid mask", s),
   217  			pgcode.InvalidTextRepresentation)
   218  	}
   219  
   220  	if family == IPv4family {
   221  		// If the mask is outside the defined octets, postgres will raise an error.
   222  		octetCount := strings.Count(addr, ".") + 1
   223  		if (octetCount+1)*8-1 < maskOnes {
   224  			return pgerror.WithCandidateCode(
   225  				errors.Errorf("could not parse %q as inet. mask is larger than provided octets", s),
   226  				pgcode.InvalidTextRepresentation)
   227  		}
   228  
   229  		// Append extra ".0" to ensure there are a total of 4 octets.
   230  		var buffer bytes.Buffer
   231  		buffer.WriteString(addr)
   232  		for i := 0; i < 4-octetCount; i++ {
   233  			buffer.WriteString(".0")
   234  		}
   235  		addr = buffer.String()
   236  
   237  	}
   238  
   239  	ip := ParseIP(addr)
   240  	if ip == nil {
   241  		return pgerror.WithCandidateCode(
   242  			errors.Errorf("could not parse %q as inet. invalid IP", s),
   243  			pgcode.InvalidTextRepresentation)
   244  	}
   245  
   246  	*dest = IPAddr{Family: family,
   247  		Addr: Addr(uint128.FromBytes(ip)),
   248  		Mask: byte(maskOnes),
   249  	}
   250  	return nil
   251  }
   252  
   253  // RandIPAddr generates a random IPAddr. This includes random mask size and IP
   254  // family.
   255  func RandIPAddr(rng *rand.Rand) IPAddr {
   256  	var ipAddr IPAddr
   257  	if rng.Intn(2) > 0 {
   258  		ipAddr.Family = IPv4family
   259  		ipAddr.Mask = byte(rng.Intn(33))
   260  		ipAddr.Addr = Addr(uint128.FromInts(0, uint64(rng.Uint32())|IPv4mappedIPv6prefix))
   261  	} else {
   262  		ipAddr.Family = IPv6family
   263  		ipAddr.Mask = byte(rng.Intn(129))
   264  		ipAddr.Addr = Addr(uint128.FromInts(rng.Uint64(), rng.Uint64()))
   265  	}
   266  	return ipAddr
   267  }
   268  
   269  // Hostmask returns the host masked IP. This is defined as the IP address bits
   270  // that are not masked.
   271  func (ipAddr *IPAddr) Hostmask() IPAddr {
   272  	var newIPAddr IPAddr
   273  	newIPAddr.Family = ipAddr.Family
   274  	newIPAddr.Addr = ipAddr.Addr
   275  
   276  	if ipAddr.Family == IPv4family {
   277  		LoMask := ^uint32(0) >> ipAddr.Mask
   278  		newIPAddr.Addr.Lo = uint64(LoMask) | IPv4mappedIPv6prefix
   279  	} else if ipAddr.Mask <= 64 {
   280  		newIPAddr.Addr.Hi = ^uint64(0) >> ipAddr.Mask
   281  		newIPAddr.Addr.Lo = ^uint64(0)
   282  	} else {
   283  		newIPAddr.Addr.Hi = uint64(0)
   284  		newIPAddr.Addr.Lo = ^uint64(0) >> (ipAddr.Mask - 64)
   285  	}
   286  
   287  	if newIPAddr.Family == IPv4family {
   288  		newIPAddr.Mask = 32
   289  	} else {
   290  		newIPAddr.Mask = 128
   291  	}
   292  
   293  	return newIPAddr
   294  }
   295  
   296  // Netmask returns the network masked IP. This is defined as the IP address bits
   297  // that are masked.
   298  func (ipAddr *IPAddr) Netmask() IPAddr {
   299  	var newIPAddr IPAddr
   300  	newIPAddr.Family = ipAddr.Family
   301  	newIPAddr.Addr = ipAddr.Addr
   302  
   303  	if ipAddr.Family == IPv4family {
   304  		LoMask := ^uint32(0) << (32 - ipAddr.Mask)
   305  		newIPAddr.Addr.Lo = uint64(LoMask) | IPv4mappedIPv6prefix
   306  	} else if ipAddr.Mask <= 64 {
   307  		newIPAddr.Addr.Hi = ^uint64(0) << (64 - ipAddr.Mask)
   308  		newIPAddr.Addr.Lo = uint64(0)
   309  	} else {
   310  		newIPAddr.Addr.Hi = ^uint64(0)
   311  		newIPAddr.Addr.Lo = ^uint64(0) << (128 - ipAddr.Mask)
   312  	}
   313  
   314  	if newIPAddr.Family == IPv4family {
   315  		newIPAddr.Mask = 32
   316  	} else {
   317  		newIPAddr.Mask = 128
   318  	}
   319  
   320  	return newIPAddr
   321  }
   322  
   323  // Broadcast returns a new IPAddr where the host mask of the IP address is a
   324  // full mask, i.e. 0xFF bytes.
   325  func (ipAddr *IPAddr) Broadcast() IPAddr {
   326  	var newIPAddr IPAddr
   327  	newIPAddr.Family = ipAddr.Family
   328  	newIPAddr.Mask = ipAddr.Mask
   329  	newIPAddr.Addr = ipAddr.Addr
   330  
   331  	if newIPAddr.Family == IPv4family {
   332  		LoMask := ^uint64(0) >> (32 + newIPAddr.Mask)
   333  		newIPAddr.Addr.Lo = newIPAddr.Addr.Lo | LoMask
   334  	} else if newIPAddr.Mask < 64 {
   335  		LoMask := ^uint64(0)
   336  		HiMask := ^uint64(0) >> newIPAddr.Mask
   337  		newIPAddr.Addr.Lo = newIPAddr.Addr.Lo | LoMask
   338  		newIPAddr.Addr.Hi = newIPAddr.Addr.Hi | HiMask
   339  	} else {
   340  		LoMask := ^uint64(0) >> (newIPAddr.Mask - 64)
   341  		newIPAddr.Addr.Lo = newIPAddr.Addr.Lo | LoMask
   342  	}
   343  
   344  	return newIPAddr
   345  }
   346  
   347  // Complement returns a new IPAddr which is the bitwise complement of the
   348  // original IP. Only the lower 32 bits are changed for IPv4.
   349  func (ipAddr *IPAddr) Complement() IPAddr {
   350  	var newIPAddr IPAddr
   351  
   352  	newIPAddr.Family = ipAddr.Family
   353  	newIPAddr.Mask = ipAddr.Mask
   354  
   355  	var familyMask uint128.Uint128
   356  	if newIPAddr.Family == IPv4family {
   357  		familyMask = uint128.Uint128{Hi: 0, Lo: IPv4mask}
   358  	} else {
   359  		familyMask = uint128.Uint128{Hi: math.MaxUint64, Lo: math.MaxUint64}
   360  	}
   361  	newIPAddr.Addr = Addr(uint128.Uint128(ipAddr.Addr).Xor(familyMask))
   362  
   363  	return newIPAddr
   364  }
   365  
   366  // And returns a new IPAddr which is the bitwise AND of two IPAddrs.
   367  // Only the lower 32 bits are changed for IPv4.
   368  func (ipAddr *IPAddr) And(other *IPAddr) (IPAddr, error) {
   369  	var newIPAddr IPAddr
   370  	if ipAddr.Family != other.Family {
   371  		return newIPAddr, pgerror.WithCandidateCode(
   372  			errors.New("cannot AND inet values of different sizes"),
   373  			pgcode.InvalidParameterValue)
   374  	}
   375  	newIPAddr.Family = ipAddr.Family
   376  
   377  	if ipAddr.Mask > other.Mask {
   378  		newIPAddr.Mask = ipAddr.Mask
   379  	} else {
   380  		newIPAddr.Mask = other.Mask
   381  	}
   382  
   383  	newIPAddr.Addr = ipAddr.Addr.and(other.Addr)
   384  
   385  	return newIPAddr, nil
   386  }
   387  
   388  // Or returns a new IPAddr which is the bitwise OR of two IPAddrs.
   389  // Only the lower 32 bits are changed for IPv4.
   390  func (ipAddr *IPAddr) Or(other *IPAddr) (IPAddr, error) {
   391  	var newIPAddr IPAddr
   392  	if ipAddr.Family != other.Family {
   393  		return newIPAddr, pgerror.WithCandidateCode(
   394  			errors.New("cannot OR inet values of different sizes"),
   395  			pgcode.InvalidParameterValue)
   396  	}
   397  	newIPAddr.Family = ipAddr.Family
   398  
   399  	if ipAddr.Mask > other.Mask {
   400  		newIPAddr.Mask = ipAddr.Mask
   401  	} else {
   402  		newIPAddr.Mask = other.Mask
   403  	}
   404  
   405  	newIPAddr.Addr = ipAddr.Addr.or(other.Addr)
   406  
   407  	return newIPAddr, nil
   408  }
   409  
   410  func (ipAddr *IPAddr) sum(o int64, neg bool) (IPAddr, error) {
   411  	// neg carries information about whether to add or subtract other.
   412  	// x - -y is the same as x + y, and x + -y is the same as x - y.
   413  	var newIPAddr IPAddr
   414  	newIPAddr.Family = ipAddr.Family
   415  	newIPAddr.Mask = ipAddr.Mask
   416  
   417  	var err error
   418  	var o2 uint64
   419  	if o < 0 {
   420  		neg = !neg
   421  		// PostgreSQL ver 10 seems to have an error with min int64.
   422  		// It does not handle the overflow correctly.
   423  		// maxip - minInt64 incorrectly returns a valid address.
   424  		if o == math.MinInt64 {
   425  			o2 = 1 << 63
   426  		} else {
   427  			o2 = uint64(-o)
   428  		}
   429  	} else {
   430  		o2 = uint64(o)
   431  	}
   432  
   433  	if ipAddr.Family == IPv4family {
   434  		if !neg {
   435  			newIPAddr.Addr, err = ipAddr.Addr.ipv4Add(o2)
   436  		} else {
   437  			newIPAddr.Addr, err = ipAddr.Addr.ipv4Sub(o2)
   438  		}
   439  	} else {
   440  		if !neg {
   441  			newIPAddr.Addr, err = ipAddr.Addr.ipv6Add(o2)
   442  		} else {
   443  			newIPAddr.Addr, err = ipAddr.Addr.ipv6Sub(o2)
   444  		}
   445  	}
   446  
   447  	return newIPAddr, err
   448  }
   449  
   450  // Add returns a new IPAddr that is incremented by an int64.
   451  func (ipAddr *IPAddr) Add(o int64) (IPAddr, error) {
   452  	return ipAddr.sum(o, false)
   453  }
   454  
   455  // Sub returns a new IPAddr that is decremented by an int64.
   456  func (ipAddr *IPAddr) Sub(o int64) (IPAddr, error) {
   457  	return ipAddr.sum(o, true)
   458  }
   459  
   460  // SubIPAddr returns the difference between two IPAddrs.
   461  func (ipAddr *IPAddr) SubIPAddr(other *IPAddr) (int64, error) {
   462  	var diff int64
   463  	if ipAddr.Family != other.Family {
   464  		return diff, pgerror.WithCandidateCode(
   465  			errors.New("cannot subtract inet addresses with different sizes"),
   466  			pgcode.InvalidParameterValue)
   467  	}
   468  
   469  	if ipAddr.Family == IPv4family {
   470  		return ipAddr.Addr.subIPAddrIPv4(other.Addr)
   471  	}
   472  	return ipAddr.Addr.subIPAddrIPv6(other.Addr)
   473  }
   474  
   475  func (ipAddr IPAddr) contains(other *IPAddr) bool {
   476  	addrNetmask := ipAddr.Netmask()
   477  	o, err := other.And(&addrNetmask)
   478  	if err != nil {
   479  		return false
   480  	}
   481  	t, _ := ipAddr.And(&addrNetmask)
   482  
   483  	return t.Equal(&o)
   484  }
   485  
   486  // ContainsOrEquals determines if one ipAddr is in the same
   487  // subnet as another or the addresses and subnets are equal.
   488  func (ipAddr IPAddr) ContainsOrEquals(other *IPAddr) bool {
   489  	return ipAddr.contains(other) && ipAddr.Mask <= other.Mask
   490  }
   491  
   492  // Contains determines if one ipAddr is in the same
   493  // subnet as another.
   494  func (ipAddr IPAddr) Contains(other *IPAddr) bool {
   495  	return ipAddr.contains(other) && ipAddr.Mask < other.Mask
   496  }
   497  
   498  // ContainedByOrEquals determines if one ipAddr is in the same
   499  // subnet as another or the addresses and subnets are equal.
   500  func (ipAddr IPAddr) ContainedByOrEquals(other *IPAddr) bool {
   501  	return other.contains(&ipAddr) && ipAddr.Mask >= other.Mask
   502  }
   503  
   504  // ContainedBy determines if one ipAddr is in the same
   505  // subnet as another.
   506  func (ipAddr IPAddr) ContainedBy(other *IPAddr) bool {
   507  	return other.contains(&ipAddr) && ipAddr.Mask > other.Mask
   508  }
   509  
   510  // ContainsOrContainedBy determines if one ipAddr is in the same
   511  // subnet as another or vice versa.
   512  func (ipAddr IPAddr) ContainsOrContainedBy(other *IPAddr) bool {
   513  	return ipAddr.contains(other) || other.contains(&ipAddr)
   514  }
   515  
   516  // WriteIPv4Bytes writes the 4-byte IPv4 representation. If the IP is IPv6 then
   517  // the first 12-bytes are truncated.
   518  func (ip Addr) WriteIPv4Bytes(writer io.Writer) error {
   519  	return binary.Write(writer, binary.BigEndian, uint32(ip.Lo))
   520  }
   521  
   522  // WriteIPv6Bytes gets the 16-byte IPv6 representation.
   523  func (ip Addr) WriteIPv6Bytes(writer io.Writer) error {
   524  	err := binary.Write(writer, binary.BigEndian, ip.Hi)
   525  	if err != nil {
   526  		return errors.NewAssertionErrorWithWrappedErrf(err, "unable to write to buffer")
   527  	}
   528  	return binary.Write(writer, binary.BigEndian, ip.Lo)
   529  }
   530  
   531  // Equal wraps the Uint128 equivilance.
   532  func (ip Addr) Equal(o Addr) bool {
   533  	return uint128.Uint128(ip).Equal(uint128.Uint128(o))
   534  }
   535  
   536  // Compare wraps the Uint128 equivilance.
   537  func (ip Addr) Compare(o Addr) int {
   538  	return uint128.Uint128(ip).Compare(uint128.Uint128(o))
   539  }
   540  
   541  // Sub wraps the Uint128 subtraction.
   542  func (ip Addr) Sub(o uint64) Addr {
   543  	return Addr(uint128.Uint128(ip).Sub(o))
   544  }
   545  
   546  // Add wraps the Uint128 addition.
   547  func (ip Addr) Add(o uint64) Addr {
   548  	return Addr(uint128.Uint128(ip).Add(o))
   549  }
   550  
   551  // String wraps net.IP.String().
   552  func (ip Addr) String() string {
   553  	return net.IP(uint128.Uint128(ip).GetBytes()).String()
   554  }
   555  
   556  // and wraps the Uint128 AND.
   557  func (ip Addr) and(o Addr) Addr {
   558  	return Addr(uint128.Uint128(ip).And(uint128.Uint128(o)))
   559  }
   560  
   561  // or wraps the Uint128 OR.
   562  func (ip Addr) or(o Addr) Addr {
   563  	return Addr(uint128.Uint128(ip).Or(uint128.Uint128(o)))
   564  }
   565  
   566  // ipv4Add adds uint64 to Uint128 and checks for IPv4 overflows.
   567  func (ip Addr) ipv4Add(o uint64) (Addr, error) {
   568  	if o > IPv4max || IPv4max-o < ip.Lo&IPv4mask {
   569  		var newAddr Addr
   570  		return newAddr, errResultOutOfRange
   571  	}
   572  	return ip.Add(o), nil
   573  }
   574  
   575  // ipv6Add adds uint64 to Uint128 and checks for IPv6 overflows.
   576  func (ip Addr) ipv6Add(o uint64) (Addr, error) {
   577  	newIP := ip.Add(o)
   578  	if newIP.Compare(ip) < 0 {
   579  		return newIP, errResultOutOfRange
   580  	}
   581  	return newIP, nil
   582  }
   583  
   584  // ipv4Add subtracts uint64 from Uint128 and checks for IPv4 overflows.
   585  func (ip Addr) ipv4Sub(o uint64) (Addr, error) {
   586  	if o > IPv4max || (ip.Lo&IPv4mask) < o {
   587  		var newAddr Addr
   588  		return newAddr, errResultOutOfRange
   589  	}
   590  	return ip.Sub(o), nil
   591  }
   592  
   593  // ipv6Sub subtracts uint64 from Uint128 and checks for IPv6 overflows.
   594  func (ip Addr) ipv6Sub(o uint64) (Addr, error) {
   595  	newIP := ip.Sub(o)
   596  	if newIP.Compare(ip) > 0 {
   597  		return newIP, errResultOutOfRange
   598  	}
   599  	return newIP, nil
   600  }
   601  
   602  // subIPAddrIPv4 adds two Uint128s to return int64 and checks for overflows.
   603  func (ip Addr) subIPAddrIPv4(o Addr) (int64, error) {
   604  	return int64(uint128.Uint128(ip).Lo&IPv4mask) - int64(uint128.Uint128(o).Lo&IPv4mask), nil
   605  }
   606  
   607  // subIPAddrIPv6 adds two Uint128s to return int64 and checks for overflows.
   608  func (ip Addr) subIPAddrIPv6(o Addr) (int64, error) {
   609  	var sign int64 = 1
   610  	if ip.Compare(o) < 0 {
   611  		ip, o = o, ip
   612  		sign = -1
   613  	}
   614  	var lo, hi uint64
   615  	lo = ip.Lo - o.Lo
   616  	hi = ip.Hi - o.Hi
   617  	if lo > ip.Lo {
   618  		hi--
   619  	}
   620  	var diff int64
   621  	if hi != 0 {
   622  		return diff, errResultOutOfRange
   623  	}
   624  	if lo == uint64(math.MaxInt64)+1 && sign == -1 {
   625  		return math.MinInt64, nil
   626  	}
   627  	if lo > uint64(math.MaxInt64) {
   628  		return diff, errResultOutOfRange
   629  	}
   630  	diff = sign * int64(lo)
   631  	return diff, nil
   632  }