|
|
// 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 }
|