netutil

package
v0.9.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2021 License: Unlicense Imports: 9 Imported by: 38

Documentation

Overview

Package netutil contains common utilities for IP, MAC, and other kinds of network addresses.

TODO(a.garipov): Add more examples.

Index

Examples

Constants

View Source
const (
	// ErrAddrIsEmpty is the underlying error returned from validation
	// functions when an address is empty.
	ErrAddrIsEmpty errors.Error = "address is empty"

	// ErrLabelIsEmpty is the underlying error returned from validation
	// functions when a domain name label is empty.
	ErrLabelIsEmpty errors.Error = "label is empty"

	// ErrNotAReversedIP is the underlying error returned from validation
	// functions when a domain name is not a full reversed IP address.
	ErrNotAReversedIP errors.Error = "not a full reversed ip address"
)
View Source
const MaxDomainLabelLen = 63

MaxDomainLabelLen is the maximum allowed length of a domain name label according to RFC 1035.

View Source
const MaxDomainNameLen = 253

MaxDomainNameLen is the maximum allowed length of a full domain name according to RFC 1035.

See also: https://stackoverflow.com/a/32294443/1892060.

Variables

This section is empty.

Functions

func CloneIP

func CloneIP(ip net.IP) (clone net.IP)

CloneIP returns a clone of an IP address that doesn't share the same underlying array with it.

func CloneIPs

func CloneIPs(ips []net.IP) (clone []net.IP)

CloneIPs returns a deep clone of ips.

func CloneMAC

func CloneMAC(mac net.HardwareAddr) (clone net.HardwareAddr)

CloneMAC returns a clone of a MAC address.

func CloneURL

func CloneURL(u *url.URL) (clone *url.URL)

CloneURL returns a deep clone of u. The User pointer of clone is the same, since a *url.Userinfo is effectively an immutable value.

func IPAndPortFromAddr

func IPAndPortFromAddr(addr net.Addr) (ip net.IP, port int)

IPAndPortFromAddr returns the IP address and the port from addr. If addr is neither a *net.TCPAddr nor a *net.UDPAddr, it returns nil and 0.

func IPFromReversedAddr

func IPFromReversedAddr(arpa string) (ip net.IP, err error)

IPFromReversedAddr tries to convert a full reversed ARPA address to a normal IP address. arpa can be domain name or an FQDN.

Any error returned will have the underlying type of *AddrError.

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	ip, err := netutil.IPFromReversedAddr("4.3.2.1.in-addr.arpa")
	if err != nil {
		panic(err)
	}

	fmt.Println(ip)

}
Output:


1.2.3.4
Example (Ipv6)
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	a := `4.3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa`
	ip, err := netutil.IPFromReversedAddr(a)
	if err != nil {
		panic(err)
	}

	fmt.Println(ip)

}
Output:


::abcd:1234

func IPToReversedAddr

func IPToReversedAddr(ip net.IP) (arpa string, err error)

IPToReversedAddr returns the reversed ARPA address of ip suitable for reverse DNS (PTR) record lookups. This is a modified version of function ReverseAddr from package github.com/miekg/dns package that accepts an IP.

Any error returned will have the underlying type of *AddrError.

Example
package main

import (
	"fmt"
	"net"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	arpa, err := netutil.IPToReversedAddr(net.IP{1, 2, 3, 4})
	if err != nil {
		panic(err)
	}

	fmt.Println(arpa)

}
Output:


4.3.2.1.in-addr.arpa
Example (Ipv6)
package main

import (
	"fmt"
	"net"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	ip := net.ParseIP("::abcd:1234")
	arpa, err := netutil.IPToReversedAddr(ip)
	if err != nil {
		panic(err)
	}

	fmt.Println(arpa)

}
Output:


4.3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa

func IPv4Zero added in v0.9.2

func IPv4Zero() (ip net.IP)

IPv4Zero returns a new unspecified (aka empty or null) IPv4 address, 0.0.0.0.

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	fmt.Println(netutil.IPv4Zero())

}
Output:


0.0.0.0

func IPv6Zero added in v0.9.2

func IPv6Zero() (ip net.IP)

IPv6Zero returns a new unspecified (aka empty or null) IPv6 address, [::].

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	fmt.Println(netutil.IPv6Zero())

}
Output:


::

func IsValidHostInnerRune

func IsValidHostInnerRune(r rune) (ok bool)

IsValidHostInnerRune returns true if r is a valid inner—that is, neither initial nor final—rune for a hostname label.

func IsValidHostOuterRune

func IsValidHostOuterRune(r rune) (ok bool)

IsValidHostOuterRune returns true if r is a valid initial or final rune for a hostname label.

func JoinHostPort

func JoinHostPort(host string, port int) (hostport string)

JoinHostPort is a convenient wrapper for net.JoinHostPort with port of type int.

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	fmt.Println(netutil.JoinHostPort("example.com", 12345))

}
Output:


example.com:12345

func ParseIP

func ParseIP(s string) (ip net.IP, err error)

ParseIP is a wrapper around net.ParseIP that returns a useful error.

Any error returned will have the underlying type of *AddrError.

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	ip, err := netutil.ParseIP("1.2.3.4")
	fmt.Println(ip, err)

	ip, err = netutil.ParseIP("1234::cdef")
	fmt.Println(ip, err)

	ip, err = netutil.ParseIP("!!!")
	fmt.Println(ip, err)

}
Output:


1.2.3.4 <nil>
1234::cdef <nil>
<nil> bad ip address "!!!"

func ParseIPv4

func ParseIPv4(s string) (ip net.IP, err error)

ParseIPv4 is a wrapper around net.ParseIP that makes sure that the parsed IP is an IPv4 address and returns a useful error.

Any error returned will have the underlying type of either *AddrError.

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	ip, err := netutil.ParseIPv4("1.2.3.4")
	fmt.Println(ip, err)

	ip, err = netutil.ParseIPv4("1234::cdef")
	fmt.Println(ip, err)

	ip, err = netutil.ParseIPv4("!!!")
	fmt.Println(ip, err)

}
Output:


1.2.3.4 <nil>
<nil> bad ipv4 address "1234::cdef"
<nil> bad ipv4 address "!!!"

func SplitHost

func SplitHost(hostport string) (host string, err error)

SplitHost is a wrapper for net.SplitHostPort for cases when the hostport may or may not contain a port.

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	host, err := netutil.SplitHost("example.com:12345")
	if err != nil {
		panic(err)
	}

	fmt.Println(host)

	host, err = netutil.SplitHost("example.org")
	if err != nil {
		panic(err)
	}

	fmt.Println(host)

	_, err = netutil.SplitHost("[BAD:!")
	fmt.Println(err)

}
Output:


example.com
example.org
address [BAD:!: missing ']' in address

func SplitHostPort

func SplitHostPort(hostport string) (host string, port int, err error)

SplitHostPort is a convenient wrapper for net.SplitHostPort with port of type int.

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	host, port, err := netutil.SplitHostPort("example.com:12345")
	if err != nil {
		panic(err)
	}

	fmt.Printf("%T(%[1]v)\n", host)
	fmt.Printf("%T(%[1]v)\n", port)

}
Output:


string(example.com)
int(12345)

func ValidateDomainName

func ValidateDomainName(name string) (err error)

ValidateDomainName validates the domain name in accordance to RFC 952, RFC 1035, and with RFC-1123's inclusion of digits at the start of the host. It doesn't validate against two or more hyphens to allow punycode and internationalized domains.

Any error returned will have the underlying type of *AddrError.

func ValidateDomainNameLabel

func ValidateDomainNameLabel(label string) (err error)

ValidateDomainNameLabel returns an error if label is not a valid label of a domain name. An empty label is considered invalid.

Any error returned will have the underlying type of *AddrError.

func ValidateIP added in v0.9.2

func ValidateIP(ip net.IP) (err error)

ValidateIP returns an error if ip is not a valid IPv4 or IPv6 address.

Any error returned will have the underlying type of *AddrError.

func ValidateMAC

func ValidateMAC(mac net.HardwareAddr) (err error)

ValidateMAC returns an error if mac is not a valid EUI-48, EUI-64, or 20-octet InfiniBand link-layer address.

Any error returned will have the underlying type of *AddrError.

Types

type AddrError

type AddrError struct {
	// Err is the underlying error, if any.
	Err error
	// Kind is the kind of address or address part.
	Kind AddrKind
	// Addr is the text of the invalid address.
	Addr string
}

AddrError is the underlying type of errors returned from validation functions when a domain name is invalid.

func (*AddrError) Error

func (err *AddrError) Error() (msg string)

Error implements the error interface for *AddrError.

func (*AddrError) Unwrap

func (err *AddrError) Unwrap() (unwrapped error)

Unwrap implements the errors.Wrapper interface for *AddrError. It returns err.Err.

type AddrKind

type AddrKind string

AddrKind is the kind of address or address part used for error reporting.

const (
	AddrKindARPA     AddrKind = "arpa domain name"
	AddrKindHostPort AddrKind = "hostport address"
	AddrKindIP       AddrKind = "ip address"
	AddrKindIPPort   AddrKind = "ipport address"
	AddrKindIPv4     AddrKind = "ipv4 address"
	AddrKindLabel    AddrKind = "domain name label"
	AddrKindMAC      AddrKind = "mac address"
	AddrKindName     AddrKind = "domain name"
)

Kinds of addresses for AddrError.

type HostPort

type HostPort struct {
	Host string
	Port int
}

HostPort is a convenient type for addresses that contain a hostname and a port, like "example.com:12345", "1.2.3.4:56789", or "[1234::cdef]:12345".

func CloneHostPorts

func CloneHostPorts(hps []*HostPort) (clone []*HostPort)

CloneHostPorts returns a deep copy of hps.

func ParseHostPort

func ParseHostPort(addr string) (hp *HostPort, err error)

ParseHostPort parses a HostPort from addr. Any error returned will have the underlying type of *AddrError.

func (*HostPort) Clone

func (hp *HostPort) Clone() (clone *HostPort)

Clone returns a clone of hp.

func (HostPort) MarshalText

func (hp HostPort) MarshalText() (b []byte, err error)

MarshalText implements the encoding.TextMarshaler interface for HostPort.

Example
package main

import (
	"encoding/json"
	"os"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	resp := struct {
		Hosts []netutil.HostPort `json:"hosts"`
	}{
		Hosts: []netutil.HostPort{{
			Host: "example.com",
			Port: 12345,
		}, {
			Host: "example.org",
			Port: 23456,
		}},
	}

	err := json.NewEncoder(os.Stdout).Encode(resp)
	if err != nil {
		panic(err)
	}

	respPtrs := struct {
		HostPtrs []*netutil.HostPort `json:"host_ptrs"`
	}{
		HostPtrs: []*netutil.HostPort{{
			Host: "example.com",
			Port: 12345,
		}, {
			Host: "example.org",
			Port: 23456,
		}},
	}

	err = json.NewEncoder(os.Stdout).Encode(respPtrs)
	if err != nil {
		panic(err)
	}

}
Output:


{"hosts":["example.com:12345","example.org:23456"]}
{"host_ptrs":["example.com:12345","example.org:23456"]}

func (HostPort) String

func (hp HostPort) String() (s string)

String implements the fmt.Stringer interface for *HostPort.

Example
package main

import (
	"fmt"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	hp := &netutil.HostPort{
		Host: "example.com",
		Port: 12345,
	}

	fmt.Println(hp)

	hp.Host = "1234::cdef"
	fmt.Println(hp)

	hp.Port = 0
	fmt.Println(hp)

	hp.Host = ""
	fmt.Println(hp)

}
Output:


example.com:12345
[1234::cdef]:12345
[1234::cdef]:0
:0

func (*HostPort) UnmarshalText

func (hp *HostPort) UnmarshalText(b []byte) (err error)

UnmarshalText implements the encoding.TextUnmarshaler interface for *HostPort. Any error returned will have the underlying type of *AddrError.

Example
package main

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	resp := &struct {
		Hosts []netutil.HostPort `json:"hosts"`
	}{}

	r := strings.NewReader(`{"hosts":["example.com:12345","example.org:23456"]}`)
	err := json.NewDecoder(r).Decode(resp)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%#v\n", resp.Hosts[0])
	fmt.Printf("%#v\n", resp.Hosts[1])

	respPtrs := &struct {
		HostPtrs []*netutil.HostPort `json:"host_ptrs"`
	}{}

	r = strings.NewReader(`{"host_ptrs":["example.com:12345","example.org:23456"]}`)
	err = json.NewDecoder(r).Decode(respPtrs)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%#v\n", respPtrs.HostPtrs[0])
	fmt.Printf("%#v\n", respPtrs.HostPtrs[1])

}
Output:


netutil.HostPort{Host:"example.com", Port:12345}
netutil.HostPort{Host:"example.org", Port:23456}
&netutil.HostPort{Host:"example.com", Port:12345}
&netutil.HostPort{Host:"example.org", Port:23456}

type IPMap

type IPMap struct {
	// contains filtered or unexported fields
}

IPMap is a map of IP addresses.

func NewIPMap

func NewIPMap(hint int) (m *IPMap)

NewIPMap returns a new empty IP map using hint as a size hint for the underlying map.

It is not safe for concurrent use, just like the usual Go maps aren't.

func (*IPMap) Del

func (m *IPMap) Del(ip net.IP)

Del deletes ip from the map. Calling Del on a nil *IPMap has no effect, just like delete on an empty map doesn't.

func (*IPMap) Get

func (m *IPMap) Get(ip net.IP) (v interface{}, ok bool)

Get returns the value from the map. Calling Get on a nil *IPMap returns nil and false, just like indexing on an empty map does.

func (*IPMap) Len

func (m *IPMap) Len() (n int)

Len returns the length of the map. A nil *IPMap has a length of zero, just like an empty map.

func (*IPMap) Range

func (m *IPMap) Range(f func(ip net.IP, v interface{}) (cont bool))

Range calls f with a copy of the key and the value for each key-value pair present in the map in an undefined order. If cont is false, range stops the iteration. Calling Range on a nil *IPMap has no effect, just like ranging over a nil map.

func (*IPMap) Set

func (m *IPMap) Set(ip net.IP, v interface{})

Set sets the value. Set panics if the m is a nil *IPMap, just like a nil map does.

func (*IPMap) ShallowClone

func (m *IPMap) ShallowClone() (sclone *IPMap)

ShallowClone returns a shallow clone of the map.

func (*IPMap) String

func (m *IPMap) String() (s string)

String implements the fmt.Stringer interface for *IPMap.

type IPPort

type IPPort struct {
	IP   net.IP
	Port int
}

IPPort is a convenient type for network addresses that contain an IP address and a port, like "1.2.3.4:56789" or "[1234::cdef]:12345".

func CloneIPPorts

func CloneIPPorts(ipps []*IPPort) (clone []*IPPort)

CloneIPPorts returns a deep copy of ipps.

func IPPortFromAddr

func IPPortFromAddr(a net.Addr) (ipp *IPPort)

IPPortFromAddr returns an *IPPort from a if its underlying type is either *net.TCPAddr or *net.UDPAddr. Otherwise, it returns nil.

func ParseIPPort

func ParseIPPort(addr string) (ipp *IPPort, err error)

ParseIPPort parses an *IPPort from addr. Any error returned will have the underlying type of *AddrError.

func (*IPPort) Clone

func (ipp *IPPort) Clone() (clone *IPPort)

Clone returns a clone of ipp.

func (IPPort) MarshalText

func (ipp IPPort) MarshalText() (b []byte, err error)

MarshalText implements the encoding.TextMarshaler interface for IPPort.

Example
package main

import (
	"encoding/json"
	"net"
	"os"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	ip4 := net.ParseIP("1.2.3.4")
	ip6 := net.ParseIP("1234::cdef")

	resp := struct {
		IPs []netutil.IPPort `json:"ips"`
	}{
		IPs: []netutil.IPPort{{
			IP:   ip4,
			Port: 12345,
		}, {
			IP:   ip6,
			Port: 23456,
		}},
	}

	err := json.NewEncoder(os.Stdout).Encode(resp)
	if err != nil {
		panic(err)
	}

	respPtrs := struct {
		IPPtrs []*netutil.IPPort `json:"ip_ptrs"`
	}{
		IPPtrs: []*netutil.IPPort{{
			IP:   ip4,
			Port: 12345,
		}, {
			IP:   ip6,
			Port: 23456,
		}},
	}

	err = json.NewEncoder(os.Stdout).Encode(respPtrs)
	if err != nil {
		panic(err)
	}

}
Output:


{"ips":["1.2.3.4:12345","[1234::cdef]:23456"]}
{"ip_ptrs":["1.2.3.4:12345","[1234::cdef]:23456"]}

func (IPPort) String

func (ipp IPPort) String() (s string)

String implements the fmt.Stringer interface for *IPPort.

Example
package main

import (
	"fmt"
	"net"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	ip4 := net.ParseIP("1.2.3.4")
	ip6 := net.ParseIP("1234::cdef")

	ipp := &netutil.IPPort{
		IP:   ip4,
		Port: 12345,
	}

	fmt.Println(ipp)

	ipp.IP = ip6
	fmt.Println(ipp)

	ipp.Port = 0
	fmt.Println(ipp)

	ipp.IP = nil
	fmt.Println(ipp)

}
Output:


1.2.3.4:12345
[1234::cdef]:12345
[1234::cdef]:0
:0

func (*IPPort) TCP

func (ipp *IPPort) TCP() (a *net.TCPAddr)

TCP returns a *net.TCPAddr with a clone of ipp's IP address and its port.

Example
package main

import (
	"fmt"
	"net"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	ipp := &netutil.IPPort{
		IP:   net.IP{1, 2, 3, 4},
		Port: 12345,
	}

	fmt.Printf("%#v\n", ipp.TCP())

}
Output:


&net.TCPAddr{IP:net.IP{0x1, 0x2, 0x3, 0x4}, Port:12345, Zone:""}

func (*IPPort) UDP

func (ipp *IPPort) UDP() (a *net.UDPAddr)

UDP returns a *net.UDPAddr with a clone of ipp's IP address and its port.

Example
package main

import (
	"fmt"
	"net"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	ipp := &netutil.IPPort{
		IP:   net.IP{1, 2, 3, 4},
		Port: 12345,
	}

	fmt.Printf("%#v\n", ipp.UDP())

}
Output:


&net.UDPAddr{IP:net.IP{0x1, 0x2, 0x3, 0x4}, Port:12345, Zone:""}

func (*IPPort) UnmarshalText

func (ipp *IPPort) UnmarshalText(b []byte) (err error)

UnmarshalText implements the encoding.TextUnmarshaler interface for *IPPort. Any error returned will have the underlying type of *AddrError.

Example
package main

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/AdguardTeam/golibs/netutil"
)

func main() {
	resp := &struct {
		IPs []netutil.IPPort `json:"ips"`
	}{}

	r := strings.NewReader(`{"ips":["1.2.3.4:12345","[1234::cdef]:23456"]}`)
	err := json.NewDecoder(r).Decode(resp)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%v\n", resp.IPs)

	respPtrs := &struct {
		IPPtrs []*netutil.IPPort `json:"ip_ptrs"`
	}{}

	r = strings.NewReader(`{"ip_ptrs":["1.2.3.4:12345","[1234::cdef]:23456"]}`)
	err = json.NewDecoder(r).Decode(respPtrs)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%v\n", respPtrs.IPPtrs)

}
Output:


[1.2.3.4:12345 [1234::cdef]:23456]
[1.2.3.4:12345 [1234::cdef]:23456]

type LengthError

type LengthError struct {
	// Kind is the kind of address or address part.
	Kind AddrKind
	// Allowed are the allowed lengths for this kind of address.  If allowed
	// is empty, Max should be non-zero.
	Allowed []int
	// Max is the maximum length for this part or address kind.  If Max is
	// zero, Allowed should be non-empty.
	Max int
	// Length is the length of the provided address.
	Length int
}

LengthError is the underlying type of errors returned from validation functions when an address or a part of an address has a bad length.

func (*LengthError) Error

func (err *LengthError) Error() (msg string)

Error implements the error interface for *LengthError.

type RuneError

type RuneError struct {
	// Kind is the kind of address or address part.
	Kind AddrKind
	// Rune is the invalid rune.
	Rune rune
}

RuneError is the underlying type of errors returned from validation functions when a rune in the address is invalid.

func (*RuneError) Error

func (err *RuneError) Error() (msg string)

Error implements the error interface for *RuneError.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL