// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// IP address manipulations
//
// IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes.
// An IPv4 address can be converted to an IPv6 address by
// adding a canonical prefix (10 zeros, 2 0xFFs).
// This library accepts either size of byte slice but always
// returns 16-byte addresses.

package net

import (
	
	
	
	
)

// IP address lengths (bytes).
const (
	IPv4len = 4
	IPv6len = 16
)

// An IP is a single IP address, a slice of bytes.
// Functions in this package accept either 4-byte (IPv4)
// or 16-byte (IPv6) slices as input.
//
// Note that in this documentation, referring to an
// IP address as an IPv4 address or an IPv6 address
// is a semantic property of the address, not just the
// length of the byte slice: a 16-byte slice can still
// be an IPv4 address.
type IP []byte

// An IPMask is a bitmask that can be used to manipulate
// IP addresses for IP addressing and routing.
//
// See type [IPNet] and func [ParseCIDR] for details.
type IPMask []byte

// An IPNet represents an IP network.
type IPNet struct {
	IP   IP     // network number
	Mask IPMask // network mask
}

// IPv4 returns the IP address (in 16-byte form) of the
// IPv4 address a.b.c.d.
func (, , ,  byte) IP {
	 := make(IP, IPv6len)
	copy(, v4InV6Prefix)
	[12] = 
	[13] = 
	[14] = 
	[15] = 
	return 
}

var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}

// IPv4Mask returns the IP mask (in 4-byte form) of the
// IPv4 mask a.b.c.d.
func (, , ,  byte) IPMask {
	 := make(IPMask, IPv4len)
	[0] = 
	[1] = 
	[2] = 
	[3] = 
	return 
}

// CIDRMask returns an [IPMask] consisting of 'ones' 1 bits
// followed by 0s up to a total length of 'bits' bits.
// For a mask of this form, CIDRMask is the inverse of [IPMask.Size].
func (,  int) IPMask {
	if  != 8*IPv4len &&  != 8*IPv6len {
		return nil
	}
	if  < 0 ||  >  {
		return nil
	}
	 :=  / 8
	 := make(IPMask, )
	 := uint()
	for  := 0;  < ; ++ {
		if  >= 8 {
			[] = 0xff
			 -= 8
			continue
		}
		[] = ^byte(0xff >> )
		 = 0
	}
	return 
}

// Well-known IPv4 addresses
var (
	IPv4bcast     = IPv4(255, 255, 255, 255) // limited broadcast
	IPv4allsys    = IPv4(224, 0, 0, 1)       // all systems
	IPv4allrouter = IPv4(224, 0, 0, 2)       // all routers
	IPv4zero      = IPv4(0, 0, 0, 0)         // all zeros
)

// Well-known IPv6 addresses
var (
	IPv6zero                   = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	IPv6unspecified            = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	IPv6loopback               = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
	IPv6interfacelocalallnodes = IP{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
	IPv6linklocalallnodes      = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
	IPv6linklocalallrouters    = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}
)

// IsUnspecified reports whether ip is an unspecified address, either
// the IPv4 address "0.0.0.0" or the IPv6 address "::".
func ( IP) () bool {
	return .Equal(IPv4zero) || .Equal(IPv6unspecified)
}

// IsLoopback reports whether ip is a loopback address.
func ( IP) () bool {
	if  := .To4();  != nil {
		return [0] == 127
	}
	return .Equal(IPv6loopback)
}

// IsPrivate reports whether ip is a private address, according to
// RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses).
func ( IP) () bool {
	if  := .To4();  != nil {
		// Following RFC 1918, Section 3. Private Address Space which says:
		//   The Internet Assigned Numbers Authority (IANA) has reserved the
		//   following three blocks of the IP address space for private internets:
		//     10.0.0.0        -   10.255.255.255  (10/8 prefix)
		//     172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
		//     192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
		return [0] == 10 ||
			([0] == 172 && [1]&0xf0 == 16) ||
			([0] == 192 && [1] == 168)
	}
	// Following RFC 4193, Section 8. IANA Considerations which says:
	//   The IANA has assigned the FC00::/7 prefix to "Unique Local Unicast".
	return len() == IPv6len && [0]&0xfe == 0xfc
}

// IsMulticast reports whether ip is a multicast address.
func ( IP) () bool {
	if  := .To4();  != nil {
		return [0]&0xf0 == 0xe0
	}
	return len() == IPv6len && [0] == 0xff
}

// IsInterfaceLocalMulticast reports whether ip is
// an interface-local multicast address.
func ( IP) () bool {
	return len() == IPv6len && [0] == 0xff && [1]&0x0f == 0x01
}

// IsLinkLocalMulticast reports whether ip is a link-local
// multicast address.
func ( IP) () bool {
	if  := .To4();  != nil {
		return [0] == 224 && [1] == 0 && [2] == 0
	}
	return len() == IPv6len && [0] == 0xff && [1]&0x0f == 0x02
}

// IsLinkLocalUnicast reports whether ip is a link-local
// unicast address.
func ( IP) () bool {
	if  := .To4();  != nil {
		return [0] == 169 && [1] == 254
	}
	return len() == IPv6len && [0] == 0xfe && [1]&0xc0 == 0x80
}

// IsGlobalUnicast reports whether ip is a global unicast
// address.
//
// The identification of global unicast addresses uses address type
// identification as defined in RFC 1122, RFC 4632 and RFC 4291 with
// the exception of IPv4 directed broadcast addresses.
// It returns true even if ip is in IPv4 private address space or
// local IPv6 unicast address space.
func ( IP) () bool {
	return (len() == IPv4len || len() == IPv6len) &&
		!.Equal(IPv4bcast) &&
		!.IsUnspecified() &&
		!.IsLoopback() &&
		!.IsMulticast() &&
		!.IsLinkLocalUnicast()
}

// Is p all zeros?
func isZeros( IP) bool {
	for  := 0;  < len(); ++ {
		if [] != 0 {
			return false
		}
	}
	return true
}

// To4 converts the IPv4 address ip to a 4-byte representation.
// If ip is not an IPv4 address, To4 returns nil.
func ( IP) () IP {
	if len() == IPv4len {
		return 
	}
	if len() == IPv6len &&
		isZeros([0:10]) &&
		[10] == 0xff &&
		[11] == 0xff {
		return [12:16]
	}
	return nil
}

// To16 converts the IP address ip to a 16-byte representation.
// If ip is not an IP address (it is the wrong length), To16 returns nil.
func ( IP) () IP {
	if len() == IPv4len {
		return IPv4([0], [1], [2], [3])
	}
	if len() == IPv6len {
		return 
	}
	return nil
}

// Default route masks for IPv4.
var (
	classAMask = IPv4Mask(0xff, 0, 0, 0)
	classBMask = IPv4Mask(0xff, 0xff, 0, 0)
	classCMask = IPv4Mask(0xff, 0xff, 0xff, 0)
)

// DefaultMask returns the default IP mask for the IP address ip.
// Only IPv4 addresses have default masks; DefaultMask returns
// nil if ip is not a valid IPv4 address.
func ( IP) () IPMask {
	if  = .To4();  == nil {
		return nil
	}
	switch {
	case [0] < 0x80:
		return classAMask
	case [0] < 0xC0:
		return classBMask
	default:
		return classCMask
	}
}

func allFF( []byte) bool {
	for ,  := range  {
		if  != 0xff {
			return false
		}
	}
	return true
}

// Mask returns the result of masking the IP address ip with mask.
func ( IP) ( IPMask) IP {
	if len() == IPv6len && len() == IPv4len && allFF([:12]) {
		 = [12:]
	}
	if len() == IPv4len && len() == IPv6len && bytealg.Equal([:12], v4InV6Prefix) {
		 = [12:]
	}
	 := len()
	if  != len() {
		return nil
	}
	 := make(IP, )
	for  := 0;  < ; ++ {
		[] = [] & []
	}
	return 
}

// String returns the string form of the IP address ip.
// It returns one of 4 forms:
//   - "<nil>", if ip has length 0
//   - dotted decimal ("192.0.2.1"), if ip is an IPv4 or IP4-mapped IPv6 address
//   - IPv6 conforming to RFC 5952 ("2001:db8::1"), if ip is a valid IPv6 address
//   - the hexadecimal form of ip, without punctuation, if no other cases apply
func ( IP) () string {
	if len() == 0 {
		return "<nil>"
	}

	if len() != IPv4len && len() != IPv6len {
		return "?" + hexString()
	}

	var  []byte
	switch len() {
	case IPv4len:
		const  = len("255.255.255.255")
		 = make([]byte, 0, )
	case IPv6len:
		const  = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
		 = make([]byte, 0, )
	}
	 = .appendTo()
	return string()
}

func hexString( []byte) string {
	 := make([]byte, len()*2)
	for ,  := range  {
		[*2], [*2+1] = hexDigit[>>4], hexDigit[&0xf]
	}
	return string()
}

// ipEmptyString is like ip.String except that it returns
// an empty string when ip is unset.
func ipEmptyString( IP) string {
	if len() == 0 {
		return ""
	}
	return .String()
}

// appendTo appends the string representation of ip to b and returns the expanded b
// If len(ip) != IPv4len or IPv6len, it appends nothing.
func ( IP) ( []byte) []byte {
	// If IPv4, use dotted notation.
	if  := .To4(); len() == IPv4len {
		 = 
	}
	,  := netip.AddrFromSlice()
	return .AppendTo()
}

// AppendText implements the [encoding.TextAppender] interface.
// The encoding is the same as returned by [IP.String], with one exception:
// When len(ip) is zero, it appends nothing.
func ( IP) ( []byte) ([]byte, error) {
	if len() == 0 {
		return , nil
	}
	if len() != IPv4len && len() != IPv6len {
		return , &AddrError{Err: "invalid IP address", Addr: hexString()}
	}

	return .appendTo(), nil
}

// MarshalText implements the [encoding.TextMarshaler] interface.
// The encoding is the same as returned by [IP.String], with one exception:
// When len(ip) is zero, it returns an empty slice.
func ( IP) () ([]byte, error) {
	// 24 is satisfied with all IPv4 addresses and short IPv6 addresses
	,  := .AppendText(make([]byte, 0, 24))
	if  != nil {
		return nil, 
	}
	return , nil
}

// UnmarshalText implements the [encoding.TextUnmarshaler] interface.
// The IP address is expected in a form accepted by [ParseIP].
func ( *IP) ( []byte) error {
	if len() == 0 {
		* = nil
		return nil
	}
	 := string()
	 := ParseIP()
	if  == nil {
		return &ParseError{Type: "IP address", Text: }
	}
	* = 
	return nil
}

// Equal reports whether ip and x are the same IP address.
// An IPv4 address and that same address in IPv6 form are
// considered to be equal.
func ( IP) ( IP) bool {
	if len() == len() {
		return bytealg.Equal(, )
	}
	if len() == IPv4len && len() == IPv6len {
		return bytealg.Equal([0:12], v4InV6Prefix) && bytealg.Equal(, [12:])
	}
	if len() == IPv6len && len() == IPv4len {
		return bytealg.Equal([0:12], v4InV6Prefix) && bytealg.Equal([12:], )
	}
	return false
}

func ( IP) ( IP) bool {
	return .To4() != nil && .To4() != nil || .To16() != nil && .To4() == nil && .To16() != nil && .To4() == nil
}

// If mask is a sequence of 1 bits followed by 0 bits,
// return the number of 1 bits.
func simpleMaskLength( IPMask) int {
	var  int
	for ,  := range  {
		if  == 0xff {
			 += 8
			continue
		}
		// found non-ff byte
		// count 1 bits
		for &0x80 != 0 {
			++
			 <<= 1
		}
		// rest must be 0 bits
		if  != 0 {
			return -1
		}
		for ++;  < len(); ++ {
			if [] != 0 {
				return -1
			}
		}
		break
	}
	return 
}

// Size returns the number of leading ones and total bits in the mask.
// If the mask is not in the canonical form--ones followed by zeros--then
// Size returns 0, 0.
func ( IPMask) () (,  int) {
	,  = simpleMaskLength(), len()*8
	if  == -1 {
		return 0, 0
	}
	return
}

// String returns the hexadecimal form of m, with no punctuation.
func ( IPMask) () string {
	if len() == 0 {
		return "<nil>"
	}
	return hexString()
}

func networkNumberAndMask( *IPNet) ( IP,  IPMask) {
	if  = .IP.To4();  == nil {
		 = .IP
		if len() != IPv6len {
			return nil, nil
		}
	}
	 = .Mask
	switch len() {
	case IPv4len:
		if len() != IPv4len {
			return nil, nil
		}
	case IPv6len:
		if len() == IPv4len {
			 = [12:]
		}
	default:
		return nil, nil
	}
	return
}

// Contains reports whether the network includes ip.
func ( *IPNet) ( IP) bool {
	,  := networkNumberAndMask()
	if  := .To4();  != nil {
		 = 
	}
	 := len()
	if  != len() {
		return false
	}
	for  := 0;  < ; ++ {
		if []&[] != []&[] {
			return false
		}
	}
	return true
}

// Network returns the address's network name, "ip+net".
func ( *IPNet) () string { return "ip+net" }

// String returns the CIDR notation of n like "192.0.2.0/24"
// or "2001:db8::/48" as defined in RFC 4632 and RFC 4291.
// If the mask is not in the canonical form, it returns the
// string which consists of an IP address, followed by a slash
// character and a mask expressed as hexadecimal form with no
// punctuation like "198.51.100.0/c000ff00".
func ( *IPNet) () string {
	if  == nil {
		return "<nil>"
	}
	,  := networkNumberAndMask()
	if  == nil ||  == nil {
		return "<nil>"
	}
	 := simpleMaskLength()
	if  == -1 {
		return .String() + "/" + .String()
	}
	return .String() + "/" + itoa.Uitoa(uint())
}

// ParseIP parses s as an IP address, returning the result.
// The string s can be in IPv4 dotted decimal ("192.0.2.1"), IPv6
// ("2001:db8::68"), or IPv4-mapped IPv6 ("::ffff:192.0.2.1") form.
// If s is not a valid textual representation of an IP address,
// ParseIP returns nil. The returned address is always 16 bytes,
// IPv4 addresses are returned in IPv4-mapped IPv6 form.
func ( string) IP {
	if ,  := parseIP();  {
		return IP([:])
	}
	return nil
}

func parseIP( string) ([16]byte, bool) {
	,  := netip.ParseAddr()
	if  != nil || .Zone() != "" {
		return [16]byte{}, false
	}
	return .As16(), true
}

// ParseCIDR parses s as a CIDR notation IP address and prefix length,
// like "192.0.2.0/24" or "2001:db8::/32", as defined in
// RFC 4632 and RFC 4291.
//
// It returns the IP address and the network implied by the IP and
// prefix length.
// For example, ParseCIDR("192.0.2.1/24") returns the IP address
// 192.0.2.1 and the network 192.0.2.0/24.
func ( string) (IP, *IPNet, error) {
	, ,  := stringslite.Cut(, "/")
	if ! {
		return nil, nil, &ParseError{Type: "CIDR address", Text: }
	}

	,  := netip.ParseAddr()
	if  != nil || .Zone() != "" {
		return nil, nil, &ParseError{Type: "CIDR address", Text: }
	}

	, ,  := dtoi()
	if ! ||  != len() ||  < 0 ||  > .BitLen() {
		return nil, nil, &ParseError{Type: "CIDR address", Text: }
	}
	 := CIDRMask(, .BitLen())
	 := .As16()
	return IP([:]), &IPNet{IP: IP([:]).Mask(), Mask: }, nil
}

func copyIP( IP) IP {
	 := make(IP, len())
	copy(, )
	return 
}