summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/net/route/address.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/net/route/address.go')
-rw-r--r--vendor/golang.org/x/net/route/address.go425
1 files changed, 425 insertions, 0 deletions
diff --git a/vendor/golang.org/x/net/route/address.go b/vendor/golang.org/x/net/route/address.go
new file mode 100644
index 0000000..e6bfa39
--- /dev/null
+++ b/vendor/golang.org/x/net/route/address.go
@@ -0,0 +1,425 @@
+// Copyright 2016 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.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import "runtime"
+
+// An Addr represents an address associated with packet routing.
+type Addr interface {
+ // Family returns an address family.
+ Family() int
+}
+
+// A LinkAddr represents a link-layer address.
+type LinkAddr struct {
+ Index int // interface index when attached
+ Name string // interface name when attached
+ Addr []byte // link-layer address when attached
+}
+
+// Family implements the Family method of Addr interface.
+func (a *LinkAddr) Family() int { return sysAF_LINK }
+
+func (a *LinkAddr) lenAndSpace() (int, int) {
+ l := 8 + len(a.Name) + len(a.Addr)
+ return l, roundup(l)
+}
+
+func (a *LinkAddr) marshal(b []byte) (int, error) {
+ l, ll := a.lenAndSpace()
+ if len(b) < ll {
+ return 0, errShortBuffer
+ }
+ nlen, alen := len(a.Name), len(a.Addr)
+ if nlen > 255 || alen > 255 {
+ return 0, errInvalidAddr
+ }
+ b[0] = byte(l)
+ b[1] = sysAF_LINK
+ if a.Index > 0 {
+ nativeEndian.PutUint16(b[2:4], uint16(a.Index))
+ }
+ data := b[8:]
+ if nlen > 0 {
+ b[5] = byte(nlen)
+ copy(data[:nlen], a.Addr)
+ data = data[nlen:]
+ }
+ if alen > 0 {
+ b[6] = byte(alen)
+ copy(data[:alen], a.Name)
+ data = data[alen:]
+ }
+ return ll, nil
+}
+
+func parseLinkAddr(b []byte) (Addr, error) {
+ if len(b) < 8 {
+ return nil, errInvalidAddr
+ }
+ _, a, err := parseKernelLinkAddr(sysAF_LINK, b[4:])
+ if err != nil {
+ return nil, err
+ }
+ a.(*LinkAddr).Index = int(nativeEndian.Uint16(b[2:4]))
+ return a, nil
+}
+
+// parseKernelLinkAddr parses b as a link-layer address in
+// conventional BSD kernel form.
+func parseKernelLinkAddr(_ int, b []byte) (int, Addr, error) {
+ // The encoding looks like the following:
+ // +----------------------------+
+ // | Type (1 octet) |
+ // +----------------------------+
+ // | Name length (1 octet) |
+ // +----------------------------+
+ // | Address length (1 octet) |
+ // +----------------------------+
+ // | Selector length (1 octet) |
+ // +----------------------------+
+ // | Data (variable) |
+ // +----------------------------+
+ //
+ // On some platforms, all-bit-one of length field means "don't
+ // care".
+ nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
+ if nlen == 0xff {
+ nlen = 0
+ }
+ if alen == 0xff {
+ alen = 0
+ }
+ if slen == 0xff {
+ slen = 0
+ }
+ l := 4 + nlen + alen + slen
+ if len(b) < l {
+ return 0, nil, errInvalidAddr
+ }
+ data := b[4:]
+ var name string
+ var addr []byte
+ if nlen > 0 {
+ name = string(data[:nlen])
+ data = data[nlen:]
+ }
+ if alen > 0 {
+ addr = data[:alen]
+ data = data[alen:]
+ }
+ return l, &LinkAddr{Name: name, Addr: addr}, nil
+}
+
+// An Inet4Addr represents an internet address for IPv4.
+type Inet4Addr struct {
+ IP [4]byte // IP address
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet4Addr) Family() int { return sysAF_INET }
+
+func (a *Inet4Addr) lenAndSpace() (int, int) {
+ return sizeofSockaddrInet, roundup(sizeofSockaddrInet)
+}
+
+func (a *Inet4Addr) marshal(b []byte) (int, error) {
+ l, ll := a.lenAndSpace()
+ if len(b) < ll {
+ return 0, errShortBuffer
+ }
+ b[0] = byte(l)
+ b[1] = sysAF_INET
+ copy(b[4:8], a.IP[:])
+ return ll, nil
+}
+
+// An Inet6Addr represents an internet address for IPv6.
+type Inet6Addr struct {
+ IP [16]byte // IP address
+ ZoneID int // zone identifier
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet6Addr) Family() int { return sysAF_INET6 }
+
+func (a *Inet6Addr) lenAndSpace() (int, int) {
+ return sizeofSockaddrInet6, roundup(sizeofSockaddrInet6)
+}
+
+func (a *Inet6Addr) marshal(b []byte) (int, error) {
+ l, ll := a.lenAndSpace()
+ if len(b) < ll {
+ return 0, errShortBuffer
+ }
+ b[0] = byte(l)
+ b[1] = sysAF_INET6
+ copy(b[8:24], a.IP[:])
+ if a.ZoneID > 0 {
+ nativeEndian.PutUint32(b[24:28], uint32(a.ZoneID))
+ }
+ return ll, nil
+}
+
+// parseInetAddr parses b as an internet address for IPv4 or IPv6.
+func parseInetAddr(af int, b []byte) (Addr, error) {
+ switch af {
+ case sysAF_INET:
+ if len(b) < sizeofSockaddrInet {
+ return nil, errInvalidAddr
+ }
+ a := &Inet4Addr{}
+ copy(a.IP[:], b[4:8])
+ return a, nil
+ case sysAF_INET6:
+ if len(b) < sizeofSockaddrInet6 {
+ return nil, errInvalidAddr
+ }
+ a := &Inet6Addr{ZoneID: int(nativeEndian.Uint32(b[24:28]))}
+ copy(a.IP[:], b[8:24])
+ if a.IP[0] == 0xfe && a.IP[1]&0xc0 == 0x80 || a.IP[0] == 0xff && (a.IP[1]&0x0f == 0x01 || a.IP[1]&0x0f == 0x02) {
+ // KAME based IPv6 protocol stack usually
+ // embeds the interface index in the
+ // interface-local or link-local address as
+ // the kernel-internal form.
+ id := int(bigEndian.Uint16(a.IP[2:4]))
+ if id != 0 {
+ a.ZoneID = id
+ a.IP[2], a.IP[3] = 0, 0
+ }
+ }
+ return a, nil
+ default:
+ return nil, errInvalidAddr
+ }
+}
+
+// parseKernelInetAddr parses b as an internet address in conventional
+// BSD kernel form.
+func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
+ // The encoding looks similar to the NLRI encoding.
+ // +----------------------------+
+ // | Length (1 octet) |
+ // +----------------------------+
+ // | Address prefix (variable) |
+ // +----------------------------+
+ //
+ // The differences between the kernel form and the NLRI
+ // encoding are:
+ //
+ // - The length field of the kernel form indicates the prefix
+ // length in bytes, not in bits
+ //
+ // - In the kernel form, zero value of the length field
+ // doesn't mean 0.0.0.0/0 or ::/0
+ //
+ // - The kernel form appends leading bytes to the prefix field
+ // to make the <length, prefix> tuple to be conformed with
+ // the routing message boundary
+ l := int(b[0])
+ if runtime.GOOS == "darwin" {
+ // On Darwn, an address in the kernel form is also
+ // used as a message filler.
+ if l == 0 || len(b) > roundup(l) {
+ l = roundup(l)
+ }
+ } else {
+ l = roundup(l)
+ }
+ if len(b) < l {
+ return 0, nil, errInvalidAddr
+ }
+ // Don't reorder case expressions.
+ // The case expressions for IPv6 must come first.
+ const (
+ off4 = 4 // offset of in_addr
+ off6 = 8 // offset of in6_addr
+ )
+ switch {
+ case b[0] == sizeofSockaddrInet6:
+ a := &Inet6Addr{}
+ copy(a.IP[:], b[off6:off6+16])
+ return int(b[0]), a, nil
+ case af == sysAF_INET6:
+ a := &Inet6Addr{}
+ if l-1 < off6 {
+ copy(a.IP[:], b[1:l])
+ } else {
+ copy(a.IP[:], b[l-off6:l])
+ }
+ return int(b[0]), a, nil
+ case b[0] == sizeofSockaddrInet:
+ a := &Inet4Addr{}
+ copy(a.IP[:], b[off4:off4+4])
+ return int(b[0]), a, nil
+ default: // an old fashion, AF_UNSPEC or unknown means AF_INET
+ a := &Inet4Addr{}
+ if l-1 < off4 {
+ copy(a.IP[:], b[1:l])
+ } else {
+ copy(a.IP[:], b[l-off4:l])
+ }
+ return int(b[0]), a, nil
+ }
+}
+
+// A DefaultAddr represents an address of various operating
+// system-specific features.
+type DefaultAddr struct {
+ af int
+ Raw []byte // raw format of address
+}
+
+// Family implements the Family method of Addr interface.
+func (a *DefaultAddr) Family() int { return a.af }
+
+func (a *DefaultAddr) lenAndSpace() (int, int) {
+ l := len(a.Raw)
+ return l, roundup(l)
+}
+
+func (a *DefaultAddr) marshal(b []byte) (int, error) {
+ l, ll := a.lenAndSpace()
+ if len(b) < ll {
+ return 0, errShortBuffer
+ }
+ if l > 255 {
+ return 0, errInvalidAddr
+ }
+ b[1] = byte(l)
+ copy(b[:l], a.Raw)
+ return ll, nil
+}
+
+func parseDefaultAddr(b []byte) (Addr, error) {
+ if len(b) < 2 || len(b) < int(b[0]) {
+ return nil, errInvalidAddr
+ }
+ a := &DefaultAddr{af: int(b[1]), Raw: b[:b[0]]}
+ return a, nil
+}
+
+func addrsSpace(as []Addr) int {
+ var l int
+ for _, a := range as {
+ switch a := a.(type) {
+ case *LinkAddr:
+ _, ll := a.lenAndSpace()
+ l += ll
+ case *Inet4Addr:
+ _, ll := a.lenAndSpace()
+ l += ll
+ case *Inet6Addr:
+ _, ll := a.lenAndSpace()
+ l += ll
+ case *DefaultAddr:
+ _, ll := a.lenAndSpace()
+ l += ll
+ }
+ }
+ return l
+}
+
+// marshalAddrs marshals as and returns a bitmap indicating which
+// address is stored in b.
+func marshalAddrs(b []byte, as []Addr) (uint, error) {
+ var attrs uint
+ for i, a := range as {
+ switch a := a.(type) {
+ case *LinkAddr:
+ l, err := a.marshal(b)
+ if err != nil {
+ return 0, err
+ }
+ b = b[l:]
+ attrs |= 1 << uint(i)
+ case *Inet4Addr:
+ l, err := a.marshal(b)
+ if err != nil {
+ return 0, err
+ }
+ b = b[l:]
+ attrs |= 1 << uint(i)
+ case *Inet6Addr:
+ l, err := a.marshal(b)
+ if err != nil {
+ return 0, err
+ }
+ b = b[l:]
+ attrs |= 1 << uint(i)
+ case *DefaultAddr:
+ l, err := a.marshal(b)
+ if err != nil {
+ return 0, err
+ }
+ b = b[l:]
+ attrs |= 1 << uint(i)
+ }
+ }
+ return attrs, nil
+}
+
+func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ([]Addr, error) {
+ var as [sysRTAX_MAX]Addr
+ af := int(sysAF_UNSPEC)
+ for i := uint(0); i < sysRTAX_MAX && len(b) >= roundup(0); i++ {
+ if attrs&(1<<i) == 0 {
+ continue
+ }
+ if i <= sysRTAX_BRD {
+ switch b[1] {
+ case sysAF_LINK:
+ a, err := parseLinkAddr(b)
+ if err != nil {
+ return nil, err
+ }
+ as[i] = a
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
+ case sysAF_INET, sysAF_INET6:
+ af = int(b[1])
+ a, err := parseInetAddr(af, b)
+ if err != nil {
+ return nil, err
+ }
+ as[i] = a
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
+ default:
+ l, a, err := fn(af, b)
+ if err != nil {
+ return nil, err
+ }
+ as[i] = a
+ ll := roundup(l)
+ if len(b) < ll {
+ b = b[l:]
+ } else {
+ b = b[ll:]
+ }
+ }
+ } else {
+ a, err := parseDefaultAddr(b)
+ if err != nil {
+ return nil, err
+ }
+ as[i] = a
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
+ }
+ }
+ return as[:], nil
+}