github.com/noisysockets/noisysockets@v0.21.2-0.20240515114641-7f467e651c90/internal/util/prefix_range.go (about) 1 // SPDX-License-Identifier: MPL-2.0 2 /* 3 * Copyright (C) 2024 The Noisy Sockets Authors. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 */ 9 10 package util 11 12 import ( 13 "fmt" 14 "net/netip" 15 ) 16 17 // PrefixRange takes a netip.Prefix and calculates the starting and ending IP addresses. 18 func PrefixRange(p netip.Prefix) (startAddr netip.Addr, endAddr netip.Addr, err error) { 19 if !p.IsValid() { 20 return startAddr, endAddr, fmt.Errorf("invalid prefix") 21 } 22 23 // Check for a valid mask length in case of a IPv4-mapped IPv6 address. 24 if p.Addr().Is4In6() && p.Bits() < 96 { 25 return startAddr, endAddr, fmt.Errorf("prefix with 4in6 address must have mask >= 96") 26 } 27 28 // Calculate the first address by applying the network mask, which zeroes out the host bits. 29 startAddr = p.Masked().Addr() 30 31 // Adjust mask bits for IPv4 addresses to accommodate the IPv4-mapped IPv6 address. 32 maskBits := p.Bits() 33 if startAddr.Is4() { 34 maskBits += 96 35 } 36 37 // Calculate the last address by setting the host bits of the address. 38 as16 := startAddr.As16() 39 for b := maskBits; b < 128; b++ { 40 byteIndex, bitIndex := b/8, 7-(b%8) 41 as16[byteIndex] |= 1 << uint(bitIndex) 42 } 43 44 endAddr = netip.AddrFrom16(as16) 45 46 // If the prefix is IPv4, unmap from the IPv4-mapped IPv6 address space. 47 if startAddr.Is4() { 48 endAddr = endAddr.Unmap() 49 } 50 51 return startAddr, endAddr, nil 52 }