mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-13 10:19:07 +02:00
Android 16+ local network protection derives the blocked prefixes from the interface address prefix. A /16 address turns the whole overlay into a local network, so apps without ACCESS_LOCAL_NETWORK cannot reach any peer. Pass the address as /32 and /128 and add the overlay networks to the route list that the Android side turns into VPN routes, on both the initial create and the renew path.
102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
package wgaddr
|
|
|
|
import (
|
|
"fmt"
|
|
"net/netip"
|
|
|
|
"github.com/netbirdio/netbird/shared/netiputil"
|
|
)
|
|
|
|
// Address WireGuard parsed address
|
|
type Address struct {
|
|
IP netip.Addr
|
|
Network netip.Prefix
|
|
|
|
// IPv6 overlay address, if assigned.
|
|
IPv6 netip.Addr
|
|
IPv6Net netip.Prefix
|
|
}
|
|
|
|
// ParseWGAddress parse a string ("1.2.3.4/24") address to WG Address
|
|
func ParseWGAddress(address string) (Address, error) {
|
|
prefix, err := netip.ParsePrefix(address)
|
|
if err != nil {
|
|
return Address{}, err
|
|
}
|
|
return Address{
|
|
IP: prefix.Addr().Unmap(),
|
|
Network: prefix.Masked(),
|
|
}, nil
|
|
}
|
|
|
|
// HasIPv6 reports whether a v6 overlay address is assigned.
|
|
func (addr Address) HasIPv6() bool {
|
|
return addr.IPv6.IsValid()
|
|
}
|
|
|
|
func (addr Address) String() string {
|
|
return addr.Prefix().String()
|
|
}
|
|
|
|
// IPv6String returns the v6 address in CIDR notation, or empty string if none.
|
|
func (addr Address) IPv6String() string {
|
|
if !addr.HasIPv6() {
|
|
return ""
|
|
}
|
|
return addr.IPv6Prefix().String()
|
|
}
|
|
|
|
// Prefix returns the v4 host address with its network prefix length (e.g. 100.64.0.1/16).
|
|
func (addr Address) Prefix() netip.Prefix {
|
|
return netip.PrefixFrom(addr.IP, addr.Network.Bits())
|
|
}
|
|
|
|
// IPv6Prefix returns the v6 host address with its network prefix length, or a zero prefix if none.
|
|
func (addr Address) IPv6Prefix() netip.Prefix {
|
|
if !addr.HasIPv6() {
|
|
return netip.Prefix{}
|
|
}
|
|
return netip.PrefixFrom(addr.IPv6, addr.IPv6Net.Bits())
|
|
}
|
|
|
|
// HostPrefix returns the v4 address as a single-host prefix.
|
|
func (addr Address) HostPrefix() netip.Prefix {
|
|
return netip.PrefixFrom(addr.IP, addr.IP.BitLen())
|
|
}
|
|
|
|
// IPv6HostPrefix returns the v6 address as a single-host prefix, or an invalid prefix when no v6 overlay address is assigned.
|
|
func (addr Address) IPv6HostPrefix() netip.Prefix {
|
|
if !addr.HasIPv6() {
|
|
return netip.Prefix{}
|
|
}
|
|
return netip.PrefixFrom(addr.IPv6, addr.IPv6.BitLen())
|
|
}
|
|
|
|
// SetIPv6FromCompact decodes a compact prefix (5 or 17 bytes) and sets the IPv6 fields.
|
|
// Returns an error if the bytes are invalid. A nil or empty input is a no-op.
|
|
//
|
|
//nolint:recvcheck
|
|
func (addr *Address) SetIPv6FromCompact(raw []byte) error {
|
|
if len(raw) == 0 {
|
|
return nil
|
|
}
|
|
prefix, err := netiputil.DecodePrefix(raw)
|
|
if err != nil {
|
|
return fmt.Errorf("decode v6 overlay address: %w", err)
|
|
}
|
|
if !prefix.Addr().Is6() {
|
|
return fmt.Errorf("expected IPv6 address, got %s", prefix.Addr())
|
|
}
|
|
addr.IPv6 = prefix.Addr()
|
|
addr.IPv6Net = prefix.Masked()
|
|
return nil
|
|
}
|
|
|
|
// ClearIPv6 removes the IPv6 overlay address, leaving only v4.
|
|
//
|
|
//nolint:recvcheck
|
|
func (addr *Address) ClearIPv6() {
|
|
addr.IPv6 = netip.Addr{}
|
|
addr.IPv6Net = netip.Prefix{}
|
|
}
|