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 }