text:
// Copyright 2012 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.

// Package ipv4 implements IP-level socket options for the Internet
// Protocol version 4.
//
// The package provides IP-level socket options that allow
// manipulation of IPv4 facilities.
//
// The IPv4 protocol and basic host requirements for IPv4 are defined
// in RFC 791 and RFC 1122.
// Host extensions for multicasting and socket interface extensions
// for multicast source filters are defined in RFC 1112 and RFC 3678.
// IGMPv1, IGMPv2 and IGMPv3 are defined in RFC 1112, RFC 2236 and RFC
// 3376.
// Source-specific multicast is defined in RFC 4607.
//
//
// Unicasting
//
// The options for unicasting are available for net.TCPConn,
// net.UDPConn and net.IPConn which are created as network connections
// that use the IPv4 transport. When a single TCP connection carrying
// a data flow of multiple packets needs to indicate the flow is
// important, Conn is used to set the type-of-service field on the
// IPv4 header for each packet.
//
//	ln, err := net.Listen("tcp4", "0.0.0.0:1024")
//	if err != nil {
//		// error handling
//	}
//	defer ln.Close()
//	for {
//		c, err := ln.Accept()
//		if err != nil {
//			// error handling
//		}
//		go func(c net.Conn) {
//			defer c.Close()
//
// The outgoing packets will be labeled DiffServ assured forwarding
// class 1 low drop precedence, known as AF11 packets.
//
//			if err := ipv4.NewConn(c).SetTOS(0x28); err != nil {
//				// error handling
//			}
//			if _, err := c.Write(data); err != nil {
//				// error handling
//			}
//		}(c)
//	}
//
//
// Multicasting
//
// The options for multicasting are available for net.UDPConn and
// net.IPconn which are created as network connections that use the
// IPv4 transport. A few network facilities must be prepared before
// you begin multicasting, at a minimum joining network interfaces and
// multicast groups.
//
//	en0, err := net.InterfaceByName("en0")
//	if err != nil {
//		// error handling
//	}
//	en1, err := net.InterfaceByIndex(911)
//	if err != nil {
//		// error handling
//	}
//	group := net.IPv4(224, 0, 0, 250)
//
// First, an application listens to an appropriate address with an
// appropriate service port.
//
//	c, err := net.ListenPacket("udp4", "0.0.0.0:1024")
//	if err != nil {
//		// error handling
//	}
//	defer c.Close()
//
// Second, the application joins multicast groups, starts listening to
// the groups on the specified network interfaces. Note that the
// service port for transport layer protocol does not matter with this
// operation as joining groups affects only network and link layer
// protocols, such as IPv4 and Ethernet.
//
//	p := ipv4.NewPacketConn(c)
//	if err := p.JoinGroup(en0, &net.UDPAddr{IP: group}); err != nil {
//		// error handling
//	}
//	if err := p.JoinGroup(en1, &net.UDPAddr{IP: group}); err != nil {
//		// error handling
//	}
//
// The application might set per packet control message transmissions
// between the protocol stack within the kernel. When the application
// needs a destination address on an incoming packet,
// SetControlMessage of PacketConn is used to enable control message
// transmissions.
//
//	if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
//		// error handling
//	}
//
// The application could identify whether the received packets are
// of interest by using the control message that contains the
// destination address of the received packet.
//
//	b := make([]byte, 1500)
//	for {
//		n, cm, src, err := p.ReadFrom(b)
//		if err != nil {
//			// error handling
//		}
//		if cm.Dst.IsMulticast() {
//			if cm.Dst.Equal(group) {
//				// joined group, do something
//			} else {
//				// unknown group, discard
//				continue
//			}
//		}
//
// The application can also send both unicast and multicast packets.
//
//		p.SetTOS(0x0)
//		p.SetTTL(16)
//		if _, err := p.WriteTo(data, nil, src); err != nil {
//			// error handling
//		}
//		dst := &net.UDPAddr{IP: group, Port: 1024}
//		for _, ifi := range []*net.Interface{en0, en1} {
//			if err := p.SetMulticastInterface(ifi); err != nil {
//				// error handling
//			}
//			p.SetMulticastTTL(2)
//			if _, err := p.WriteTo(data, nil, dst); err != nil {
//				// error handling
//			}
//		}
//	}
//
//
// More multicasting
//
// An application that uses PacketConn or RawConn may join multiple
// multicast groups. For example, a UDP listener with port 1024 might
// join two different groups across over two different network
// interfaces by using:
//
//	c, err := net.ListenPacket("udp4", "0.0.0.0:1024")
//	if err != nil {
//		// error handling
//	}
//	defer c.Close()
//	p := ipv4.NewPacketConn(c)
//	if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
//		// error handling
//	}
//	if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}); err != nil {
//		// error handling
//	}
//	if err := p.JoinGroup(en1, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}); err != nil {
//		// error handling
//	}
//
// It is possible for multiple UDP listeners that listen on the same
// UDP port to join the same multicast group. The net package will
// provide a socket that listens to a wildcard address with reusable
// UDP port when an appropriate multicast address prefix is passed to
// the net.ListenPacket or net.ListenUDP.
//
//	c1, err := net.ListenPacket("udp4", "224.0.0.0:1024")
//	if err != nil {
//		// error handling
//	}
//	defer c1.Close()
//	c2, err := net.ListenPacket("udp4", "224.0.0.0:1024")
//	if err != nil {
//		// error handling
//	}
//	defer c2.Close()
//	p1 := ipv4.NewPacketConn(c1)
//	if err := p1.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
//		// error handling
//	}
//	p2 := ipv4.NewPacketConn(c2)
//	if err := p2.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
//		// error handling
//	}
//
// Also it is possible for the application to leave or rejoin a
// multicast group on the network interface.
//
//	if err := p.LeaveGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 248)}); err != nil {
//		// error handling
//	}
//	if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 250)}); err != nil {
//		// error handling
//	}
//
//
// Source-specific multicasting
//
// An application that uses PacketConn or RawConn on IGMPv3 supported
// platform is able to join source-specific multicast groups.
// The application may use JoinSourceSpecificGroup and
// LeaveSourceSpecificGroup for the operation known as "include" mode,
//
//	ssmgroup := net.UDPAddr{IP: net.IPv4(232, 7, 8, 9)}
//	ssmsource := net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)})
//	if err := p.JoinSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
//		// error handling
//	}
//	if err := p.LeaveSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil {
//		// error handling
//	}
//
// or JoinGroup, ExcludeSourceSpecificGroup,
// IncludeSourceSpecificGroup and LeaveGroup for the operation known
// as "exclude" mode.
//
//	exclsource := net.UDPAddr{IP: net.IPv4(192, 168, 0, 254)}
//	if err := p.JoinGroup(en0, &ssmgroup); err != nil {
//		// error handling
//	}
//	if err := p.ExcludeSourceSpecificGroup(en0, &ssmgroup, &exclsource); err != nil {
//		// error handling
//	}
//	if err := p.LeaveGroup(en0, &ssmgroup); err != nil {
//		// error handling
//	}
//
// Note that it depends on each platform implementation what happens
// when an application which runs on IGMPv3 unsupported platform uses
// JoinSourceSpecificGroup and LeaveSourceSpecificGroup.
// In general the platform tries to fall back to conversations using
// IGMPv1 or IGMPv2 and starts to listen to multicast traffic.
// In the fallback case, ExcludeSourceSpecificGroup and
// IncludeSourceSpecificGroup may return an error.
package ipv4 // import "golang.org/x/net/ipv4"

// BUG(mikio): This package is not implemented on NaCl and Plan 9.


text:
// Copyright 2014 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,!linux,!netbsd,!openbsd,!solaris,!windows

package ipv4

var (
	ctlOpts = [ctlMax]ctlOpt{}

	sockOpts = map[int]*sockOpt{}
)

repo_name: dan-v/dosxvpn

repo_language: Go

mime_type: text/x-shellscript


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_openbsd.go

package ipv4

const (
	sysIP_OPTIONS     = 0x1
	sysIP_HDRINCL     = 0x2
	sysIP_TOS         = 0x3
	sysIP_TTL         = 0x4
	sysIP_RECVOPTS    = 0x5
	sysIP_RECVRETOPTS = 0x6
	sysIP_RECVDSTADDR = 0x7
	sysIP_RETOPTS     = 0x8
	sysIP_RECVIF      = 0x1e
	sysIP_RECVTTL     = 0x1f

	sysIP_MULTICAST_IF    = 0x9
	sysIP_MULTICAST_TTL   = 0xa
	sysIP_MULTICAST_LOOP  = 0xb
	sysIP_ADD_MEMBERSHIP  = 0xc
	sysIP_DROP_MEMBERSHIP = 0xd

	sizeofIPMreq = 0x8
)

type ipMreq struct {
	Multiaddr [4]byte /* in_addr */
	Interface [4]byte /* in_addr */
}


text:
// go generate gen.go
// Code generated by the command above; DO NOT EDIT.

package ipv4

// Internet Control Message Protocol (ICMP) Parameters, Updated: 2018-02-26
const (
	ICMPTypeEchoReply              ICMPType = 0  // Echo Reply
	ICMPTypeDestinationUnreachable ICMPType = 3  // Destination Unreachable
	ICMPTypeRedirect               ICMPType = 5  // Redirect
	ICMPTypeEcho                   ICMPType = 8  // Echo
	ICMPTypeRouterAdvertisement    ICMPType = 9  // Router Advertisement
	ICMPTypeRouterSolicitation     ICMPType = 10 // Router Solicitation
	ICMPTypeTimeExceeded           ICMPType = 11 // Time Exceeded
	ICMPTypeParameterProblem       ICMPType = 12 // Parameter Problem
	ICMPTypeTimestamp              ICMPType = 13 // Timestamp
	ICMPTypeTimestampReply         ICMPType = 14 // Timestamp Reply
	ICMPTypePhoturis               ICMPType = 40 // Photuris
	ICMPTypeExtendedEchoRequest    ICMPType = 42 // Extended Echo Request
	ICMPTypeExtendedEchoReply      ICMPType = 43 // Extended Echo Reply
)

// Internet Control Message Protocol (ICMP) Parameters, Updated: 2018-02-26
var icmpTypes = map[ICMPType]string{
	0:  "echo reply",
	3:  "destination unreachable",
	5:  "redirect",
	8:  "echo",
	9:  "router advertisement",
	10: "router solicitation",
	11: "time exceeded",
	12: "parameter problem",
	13: "timestamp",
	14: "timestamp reply",
	40: "photuris",
	42: "extended echo request",
	43: "extended echo reply",
}


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_netbsd.go

package ipv4

const (
	sysIP_OPTIONS     = 0x1
	sysIP_HDRINCL     = 0x2
	sysIP_TOS         = 0x3
	sysIP_TTL         = 0x4
	sysIP_RECVOPTS    = 0x5
	sysIP_RECVRETOPTS = 0x6
	sysIP_RECVDSTADDR = 0x7
	sysIP_RETOPTS     = 0x8
	sysIP_RECVIF      = 0x14
	sysIP_RECVTTL     = 0x17

	sysIP_MULTICAST_IF    = 0x9
	sysIP_MULTICAST_TTL   = 0xa
	sysIP_MULTICAST_LOOP  = 0xb
	sysIP_ADD_MEMBERSHIP  = 0xc
	sysIP_DROP_MEMBERSHIP = 0xd

	sizeofIPMreq = 0x8
)

type ipMreq struct {
	Multiaddr [4]byte /* in_addr */
	Interface [4]byte /* in_addr */
}


text:
// Copyright 2017 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.

package ipv4

import (
	"net"
	"syscall"

	"golang.org/x/net/internal/iana"
	"golang.org/x/net/internal/socket"
)

var (
	ctlOpts = [ctlMax]ctlOpt{
		ctlTTL:       {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
		ctlDst:       {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
		ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
	}

	sockOpts = map[int]*sockOpt{
		ssoTOS:                {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
		ssoTTL:                {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
		ssoMulticastTTL:       {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
		ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
		ssoMulticastLoopback:  {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
		ssoReceiveTTL:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
		ssoReceiveDst:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
		ssoReceiveInterface:   {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
		ssoHeaderPrepend:      {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
		ssoJoinGroup:          {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
		ssoLeaveGroup:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
	}
)


text:
// Copyright 2012 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.

package ipv4_test

import (
	"net"
	"runtime"
	"testing"

	"golang.org/x/net/internal/nettest"
	"golang.org/x/net/ipv4"
)

var packetConnMulticastSocketOptionTests = []struct {
	net, proto, addr string
	grp, src         net.Addr
}{
	{"udp4", "", "224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, nil}, // see RFC 4727
	{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil},  // see RFC 4727

	{"udp4", "", "232.0.0.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 249)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
	{"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}},  // see RFC 5771
}

func TestPacketConnMulticastSocketOptions(t *testing.T) {
	switch runtime.GOOS {
	case "nacl", "plan9":
		t.Skipf("not supported on %s", runtime.GOOS)
	}
	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
	if ifi == nil {
		t.Skipf("not available on %s", runtime.GOOS)
	}

	m, ok := nettest.SupportsRawIPSocket()
	for _, tt := range packetConnMulticastSocketOptionTests {
		if tt.net == "ip4" && !ok {
			t.Log(m)
			continue
		}
		c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
		if err != nil {
			t.Fatal(err)
		}
		defer c.Close()
		p := ipv4.NewPacketConn(c)
		defer p.Close()

		if tt.src == nil {
			testMulticastSocketOptions(t, p, ifi, tt.grp)
		} else {
			testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
		}
	}
}

var rawConnMulticastSocketOptionTests = []struct {
	grp, src net.Addr
}{
	{&net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727

	{&net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}

func TestRawConnMulticastSocketOptions(t *testing.T) {
	switch runtime.GOOS {
	case "nacl", "plan9":
		t.Skipf("not supported on %s", runtime.GOOS)
	}
	if m, ok := nettest.SupportsRawIPSocket(); !ok {
		t.Skip(m)
	}
	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
	if ifi == nil {
		t.Skipf("not available on %s", runtime.GOOS)
	}

	for _, tt := range rawConnMulticastSocketOptionTests {
		c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
		if err != nil {
			t.Fatal(err)
		}
		defer c.Close()
		r, err := ipv4.NewRawConn(c)
		if err != nil {
			t.Fatal(err)
		}
		defer r.Close()

		if tt.src == nil {
			testMulticastSocketOptions(t, r, ifi, tt.grp)
		} else {
			testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src)
		}
	}
}

type testIPv4MulticastConn interface {
	MulticastTTL() (int, error)
	SetMulticastTTL(ttl int) error
	MulticastLoopback() (bool, error)
	SetMulticastLoopback(bool) error
	JoinGroup(*net.Interface, net.Addr) error
	LeaveGroup(*net.Interface, net.Addr) error
	JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
	LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
	ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
	IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
}

func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp net.Addr) {
	const ttl = 255
	if err := c.SetMulticastTTL(ttl); err != nil {
		t.Error(err)
		return
	}
	if v, err := c.MulticastTTL(); err != nil {
		t.Error(err)
		return
	} else if v != ttl {
		t.Errorf("got %v; want %v", v, ttl)
		return
	}

	for _, toggle := range []bool{true, false} {
		if err := c.SetMulticastLoopback(toggle); err != nil {
			t.Error(err)
			return
		}
		if v, err := c.MulticastLoopback(); err != nil {
			t.Error(err)
			return
		} else if v != toggle {
			t.Errorf("got %v; want %v", v, toggle)
			return
		}
	}

	if err := c.JoinGroup(ifi, grp); err != nil {
		t.Error(err)
		return
	}
	if err := c.LeaveGroup(ifi, grp); err != nil {
		t.Error(err)
		return
	}
}

func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp, src net.Addr) {
	// MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP
	if err := c.JoinGroup(ifi, grp); err != nil {
		t.Error(err)
		return
	}
	if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil {
		switch runtime.GOOS {
		case "freebsd", "linux":
		default: // platforms that don't support IGMPv2/3 fail here
			t.Logf("not supported on %s", runtime.GOOS)
			return
		}
		t.Error(err)
		return
	}
	if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil {
		t.Error(err)
		return
	}
	if err := c.LeaveGroup(ifi, grp); err != nil {
		t.Error(err)
		return
	}

	// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP
	if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
		t.Error(err)
		return
	}
	if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil {
		t.Error(err)
		return
	}

	// MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP
	if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
		t.Error(err)
		return
	}
	if err := c.LeaveGroup(ifi, grp); err != nil {
		t.Error(err)
		return
	}
}


text:
// Copyright 2012 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.

package ipv4

import (
	"net"

	"golang.org/x/net/internal/socket"
)

// BUG(mikio): On Windows, the ControlMessage for ReadFrom and WriteTo
// methods of PacketConn is not implemented.

// A payloadHandler represents the IPv4 datagram payload handler.
type payloadHandler struct {
	net.PacketConn
	*socket.Conn
	rawOpt
}

func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil && c.Conn != nil }


text:
// Copyright 2014 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 ignore

// +godefs map struct_in_addr [4]byte /* in_addr */

package ipv4

/*
#include <sys/socket.h>

#include <netinet/in.h>
*/
import "C"

const (
	sysIP_OPTIONS     = C.IP_OPTIONS
	sysIP_HDRINCL     = C.IP_HDRINCL
	sysIP_TOS         = C.IP_TOS
	sysIP_TTL         = C.IP_TTL
	sysIP_RECVOPTS    = C.IP_RECVOPTS
	sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
	sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
	sysIP_RETOPTS     = C.IP_RETOPTS
	sysIP_RECVIF      = C.IP_RECVIF
	sysIP_RECVSLLA    = C.IP_RECVSLLA
	sysIP_RECVTTL     = C.IP_RECVTTL

	sysIP_MULTICAST_IF           = C.IP_MULTICAST_IF
	sysIP_MULTICAST_TTL          = C.IP_MULTICAST_TTL
	sysIP_MULTICAST_LOOP         = C.IP_MULTICAST_LOOP
	sysIP_ADD_MEMBERSHIP         = C.IP_ADD_MEMBERSHIP
	sysIP_DROP_MEMBERSHIP        = C.IP_DROP_MEMBERSHIP
	sysIP_BLOCK_SOURCE           = C.IP_BLOCK_SOURCE
	sysIP_UNBLOCK_SOURCE         = C.IP_UNBLOCK_SOURCE
	sysIP_ADD_SOURCE_MEMBERSHIP  = C.IP_ADD_SOURCE_MEMBERSHIP
	sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
	sysIP_NEXTHOP                = C.IP_NEXTHOP

	sysIP_PKTINFO     = C.IP_PKTINFO
	sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
	sysIP_DONTFRAG    = C.IP_DONTFRAG

	sysIP_BOUND_IF      = C.IP_BOUND_IF
	sysIP_UNSPEC_SRC    = C.IP_UNSPEC_SRC
	sysIP_BROADCAST_TTL = C.IP_BROADCAST_TTL
	sysIP_DHCPINIT_IF   = C.IP_DHCPINIT_IF

	sysIP_REUSEADDR = C.IP_REUSEADDR
	sysIP_DONTROUTE = C.IP_DONTROUTE
	sysIP_BROADCAST = C.IP_BROADCAST

	sysMCAST_JOIN_GROUP         = C.MCAST_JOIN_GROUP
	sysMCAST_LEAVE_GROUP        = C.MCAST_LEAVE_GROUP
	sysMCAST_BLOCK_SOURCE       = C.MCAST_BLOCK_SOURCE
	sysMCAST_UNBLOCK_SOURCE     = C.MCAST_UNBLOCK_SOURCE
	sysMCAST_JOIN_SOURCE_GROUP  = C.MCAST_JOIN_SOURCE_GROUP
	sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP

	sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
	sizeofSockaddrInet    = C.sizeof_struct_sockaddr_in
	sizeofInetPktinfo     = C.sizeof_struct_in_pktinfo

	sizeofIPMreq         = C.sizeof_struct_ip_mreq
	sizeofIPMreqSource   = C.sizeof_struct_ip_mreq_source
	sizeofGroupReq       = C.sizeof_struct_group_req
	sizeofGroupSourceReq = C.sizeof_struct_group_source_req
)

type sockaddrStorage C.struct_sockaddr_storage

type sockaddrInet C.struct_sockaddr_in

type inetPktinfo C.struct_in_pktinfo

type ipMreq C.struct_ip_mreq

type ipMreqSource C.struct_ip_mreq_source

type groupReq C.struct_group_req

type groupSourceReq C.struct_group_source_req


text:
// Copyright 2012 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,!linux,!netbsd,!openbsd,!solaris,!windows

package ipv4

import (
	"net"

	"golang.org/x/net/bpf"
	"golang.org/x/net/internal/socket"
)

func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) {
	return nil, errOpNoSupport
}

func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error {
	return errOpNoSupport
}

func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) {
	return nil, errOpNoSupport
}

func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error {
	return errOpNoSupport
}

func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
	return errOpNoSupport
}

func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
	return errOpNoSupport
}

func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error {
	return errOpNoSupport
}


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_linux.go

package ipv4

const (
	sysIP_TOS             = 0x1
	sysIP_TTL             = 0x2
	sysIP_HDRINCL         = 0x3
	sysIP_OPTIONS         = 0x4
	sysIP_ROUTER_ALERT    = 0x5
	sysIP_RECVOPTS        = 0x6
	sysIP_RETOPTS         = 0x7
	sysIP_PKTINFO         = 0x8
	sysIP_PKTOPTIONS      = 0x9
	sysIP_MTU_DISCOVER    = 0xa
	sysIP_RECVERR         = 0xb
	sysIP_RECVTTL         = 0xc
	sysIP_RECVTOS         = 0xd
	sysIP_MTU             = 0xe
	sysIP_FREEBIND        = 0xf
	sysIP_TRANSPARENT     = 0x13
	sysIP_RECVRETOPTS     = 0x7
	sysIP_ORIGDSTADDR     = 0x14
	sysIP_RECVORIGDSTADDR = 0x14
	sysIP_MINTTL          = 0x15
	sysIP_NODEFRAG        = 0x16
	sysIP_UNICAST_IF      = 0x32

	sysIP_MULTICAST_IF           = 0x20
	sysIP_MULTICAST_TTL          = 0x21
	sysIP_MULTICAST_LOOP         = 0x22
	sysIP_ADD_MEMBERSHIP         = 0x23
	sysIP_DROP_MEMBERSHIP        = 0x24
	sysIP_UNBLOCK_SOURCE         = 0x25
	sysIP_BLOCK_SOURCE           = 0x26
	sysIP_ADD_SOURCE_MEMBERSHIP  = 0x27
	sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
	sysIP_MSFILTER               = 0x29
	sysMCAST_JOIN_GROUP          = 0x2a
	sysMCAST_LEAVE_GROUP         = 0x2d
	sysMCAST_JOIN_SOURCE_GROUP   = 0x2e
	sysMCAST_LEAVE_SOURCE_GROUP  = 0x2f
	sysMCAST_BLOCK_SOURCE        = 0x2b
	sysMCAST_UNBLOCK_SOURCE      = 0x2c
	sysMCAST_MSFILTER            = 0x30
	sysIP_MULTICAST_ALL          = 0x31

	sysICMP_FILTER = 0x1

	sysSO_EE_ORIGIN_NONE         = 0x0
	sysSO_EE_ORIGIN_LOCAL        = 0x1
	sysSO_EE_ORIGIN_ICMP         = 0x2
	sysSO_EE_ORIGIN_ICMP6        = 0x3
	sysSO_EE_ORIGIN_TXSTATUS     = 0x4
	sysSO_EE_ORIGIN_TIMESTAMPING = 0x4

	sysSOL_SOCKET       = 0x1
	sysSO_ATTACH_FILTER = 0x1a

	sizeofKernelSockaddrStorage = 0x80
	sizeofSockaddrInet          = 0x10
	sizeofInetPktinfo           = 0xc
	sizeofSockExtendedErr       = 0x10

	sizeofIPMreq         = 0x8
	sizeofIPMreqn        = 0xc
	sizeofIPMreqSource   = 0xc
	sizeofGroupReq       = 0x84
	sizeofGroupSourceReq = 0x104

	sizeofICMPFilter = 0x4

	sizeofSockFprog = 0x8
)

type kernelSockaddrStorage struct {
	Family  uint16
	X__data [126]uint8
}

type sockaddrInet struct {
	Family uint16
	Port   uint16
	Addr   [4]byte /* in_addr */
	X__pad [8]uint8
}

type inetPktinfo struct {
	Ifindex  int32
	Spec_dst [4]byte /* in_addr */
	Addr     [4]byte /* in_addr */
}

type sockExtendedErr struct {
	Errno  uint32
	Origin uint8
	Type   uint8
	Code   uint8
	Pad    uint8
	Info   uint32
	Data   uint32
}

type ipMreq struct {
	Multiaddr [4]byte /* in_addr */
	Interface [4]byte /* in_addr */
}

type ipMreqn struct {
	Multiaddr [4]byte /* in_addr */
	Address   [4]byte /* in_addr */
	Ifindex   int32
}

type ipMreqSource struct {
	Multiaddr  uint32
	Interface  uint32
	Sourceaddr uint32
}

type groupReq struct {
	Interface uint32
	Group     kernelSockaddrStorage
}

type groupSourceReq struct {
	Interface uint32
	Group     kernelSockaddrStorage
	Source    kernelSockaddrStorage
}

type icmpFilter struct {
	Data uint32
}

type sockFProg struct {
	Len       uint16
	Pad_cgo_0 [2]byte
	Filter    *sockFilter
}

type sockFilter struct {
	Code uint16
	Jt   uint8
	Jf   uint8
	K    uint32
}


text:
// Copyright 2014 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 netbsd openbsd

package ipv4

import (
	"net"
	"syscall"

	"golang.org/x/net/internal/iana"
	"golang.org/x/net/internal/socket"
)

var (
	ctlOpts = [ctlMax]ctlOpt{
		ctlTTL:       {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
		ctlDst:       {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
		ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
	}

	sockOpts = map[int]*sockOpt{
		ssoTOS:                {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
		ssoTTL:                {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
		ssoMulticastTTL:       {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
		ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
		ssoMulticastLoopback:  {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 1}},
		ssoReceiveTTL:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
		ssoReceiveDst:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
		ssoReceiveInterface:   {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
		ssoHeaderPrepend:      {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
		ssoJoinGroup:          {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
		ssoLeaveGroup:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
	}
)


text:
// Copyright 2014 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,!freebsd,!linux

package ipv4

import (
	"net"

	"golang.org/x/net/internal/socket"
)

func (so *sockOpt) getIPMreqn(c *socket.Conn) (*net.Interface, error) {
	return nil, errOpNoSupport
}

func (so *sockOpt) setIPMreqn(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
	return errOpNoSupport
}


text:
// Copyright 2014 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.

package ipv4

func (f *icmpFilter) accept(typ ICMPType) {
	f.Data &^= 1 << (uint32(typ) & 31)
}

func (f *icmpFilter) block(typ ICMPType) {
	f.Data |= 1 << (uint32(typ) & 31)
}

func (f *icmpFilter) setAll(block bool) {
	if block {
		f.Data = 1<<32 - 1
	} else {
		f.Data = 0
	}
}

func (f *icmpFilter) willBlock(typ ICMPType) bool {
	return f.Data&(1<<(uint32(typ)&31)) != 0
}


text:
// Copyright 2014 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 ignore

// +godefs map struct_in_addr [4]byte /* in_addr */

package ipv4

/*
#include <netinet/in.h>
*/
import "C"

const (
	sysIP_OPTIONS     = C.IP_OPTIONS
	sysIP_HDRINCL     = C.IP_HDRINCL
	sysIP_TOS         = C.IP_TOS
	sysIP_TTL         = C.IP_TTL
	sysIP_RECVOPTS    = C.IP_RECVOPTS
	sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
	sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
	sysIP_RETOPTS     = C.IP_RETOPTS
	sysIP_RECVIF      = C.IP_RECVIF
	sysIP_RECVTTL     = C.IP_RECVTTL

	sysIP_MULTICAST_IF    = C.IP_MULTICAST_IF
	sysIP_MULTICAST_TTL   = C.IP_MULTICAST_TTL
	sysIP_MULTICAST_LOOP  = C.IP_MULTICAST_LOOP
	sysIP_ADD_MEMBERSHIP  = C.IP_ADD_MEMBERSHIP
	sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP

	sizeofIPMreq = C.sizeof_struct_ip_mreq
)

type ipMreq C.struct_ip_mreq


text:
// Copyright 2012 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.

package ipv4_test

import (
	"bytes"
	"net"
	"os"
	"runtime"
	"testing"
	"time"

	"golang.org/x/net/icmp"
	"golang.org/x/net/internal/iana"
	"golang.org/x/net/internal/nettest"
	"golang.org/x/net/ipv4"
)

var packetConnReadWriteMulticastUDPTests = []struct {
	addr     string
	grp, src *net.UDPAddr
}{
	{"224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727

	{"232.0.1.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}

func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
	switch runtime.GOOS {
	case "nacl", "plan9", "solaris", "windows":
		t.Skipf("not supported on %s", runtime.GOOS)
	}
	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
	if ifi == nil {
		t.Skipf("not available on %s", runtime.GOOS)
	}

	for _, tt := range packetConnReadWriteMulticastUDPTests {
		c, err := net.ListenPacket("udp4", tt.addr)
		if err != nil {
			t.Fatal(err)
		}
		defer c.Close()

		grp := *tt.grp
		grp.Port = c.LocalAddr().(*net.UDPAddr).Port
		p := ipv4.NewPacketConn(c)
		defer p.Close()
		if tt.src == nil {
			if err := p.JoinGroup(ifi, &grp); err != nil {
				t.Fatal(err)
			}
			defer p.LeaveGroup(ifi, &grp)
		} else {
			if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
				switch runtime.GOOS {
				case "freebsd", "linux":
				default: // platforms that don't support IGMPv2/3 fail here
					t.Logf("not supported on %s", runtime.GOOS)
					continue
				}
				t.Fatal(err)
			}
			defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
		}
		if err := p.SetMulticastInterface(ifi); err != nil {
			t.Fatal(err)
		}
		if _, err := p.MulticastInterface(); err != nil {
			t.Fatal(err)
		}
		if err := p.SetMulticastLoopback(true); err != nil {
			t.Fatal(err)
		}
		if _, err := p.MulticastLoopback(); err != nil {
			t.Fatal(err)
		}
		cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
		wb := []byte("HELLO-R-U-THERE")

		for i, toggle := range []bool{true, false, true} {
			if err := p.SetControlMessage(cf, toggle); err != nil {
				if nettest.ProtocolNotSupported(err) {
					t.Logf("not supported on %s", runtime.GOOS)
					continue
				}
				t.Fatal(err)
			}
			if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
				t.Fatal(err)
			}
			p.SetMulticastTTL(i + 1)
			if n, err := p.WriteTo(wb, nil, &grp); err != nil {
				t.Fatal(err)
			} else if n != len(wb) {
				t.Fatalf("got %v; want %v", n, len(wb))
			}
			rb := make([]byte, 128)
			if n, _, _, err := p.ReadFrom(rb); err != nil {
				t.Fatal(err)
			} else if !bytes.Equal(rb[:n], wb) {
				t.Fatalf("got %v; want %v", rb[:n], wb)
			}
		}
	}
}

var packetConnReadWriteMulticastICMPTests = []struct {
	grp, src *net.IPAddr
}{
	{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727

	{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}

func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
	switch runtime.GOOS {
	case "nacl", "plan9", "solaris", "windows":
		t.Skipf("not supported on %s", runtime.GOOS)
	}
	if m, ok := nettest.SupportsRawIPSocket(); !ok {
		t.Skip(m)
	}
	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
	if ifi == nil {
		t.Skipf("not available on %s", runtime.GOOS)
	}

	for _, tt := range packetConnReadWriteMulticastICMPTests {
		c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
		if err != nil {
			t.Fatal(err)
		}
		defer c.Close()

		p := ipv4.NewPacketConn(c)
		defer p.Close()
		if tt.src == nil {
			if err := p.JoinGroup(ifi, tt.grp); err != nil {
				t.Fatal(err)
			}
			defer p.LeaveGroup(ifi, tt.grp)
		} else {
			if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
				switch runtime.GOOS {
				case "freebsd", "linux":
				default: // platforms that don't support IGMPv2/3 fail here
					t.Logf("not supported on %s", runtime.GOOS)
					continue
				}
				t.Fatal(err)
			}
			defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
		}
		if err := p.SetMulticastInterface(ifi); err != nil {
			t.Fatal(err)
		}
		if _, err := p.MulticastInterface(); err != nil {
			t.Fatal(err)
		}
		if err := p.SetMulticastLoopback(true); err != nil {
			t.Fatal(err)
		}
		if _, err := p.MulticastLoopback(); err != nil {
			t.Fatal(err)
		}
		cf := ipv4.FlagDst | ipv4.FlagInterface
		if runtime.GOOS != "solaris" {
			// Solaris never allows to modify ICMP properties.
			cf |= ipv4.FlagTTL
		}

		for i, toggle := range []bool{true, false, true} {
			wb, err := (&icmp.Message{
				Type: ipv4.ICMPTypeEcho, Code: 0,
				Body: &icmp.Echo{
					ID: os.Getpid() & 0xffff, Seq: i + 1,
					Data: []byte("HELLO-R-U-THERE"),
				},
			}).Marshal(nil)
			if err != nil {
				t.Fatal(err)
			}
			if err := p.SetControlMessage(cf, toggle); err != nil {
				if nettest.ProtocolNotSupported(err) {
					t.Logf("not supported on %s", runtime.GOOS)
					continue
				}
				t.Fatal(err)
			}
			if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
				t.Fatal(err)
			}
			p.SetMulticastTTL(i + 1)
			if n, err := p.WriteTo(wb, nil, tt.grp); err != nil {
				t.Fatal(err)
			} else if n != len(wb) {
				t.Fatalf("got %v; want %v", n, len(wb))
			}
			rb := make([]byte, 128)
			if n, _, _, err := p.ReadFrom(rb); err != nil {
				t.Fatal(err)
			} else {
				m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
				if err != nil {
					t.Fatal(err)
				}
				switch {
				case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
				case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
				default:
					t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
				}
			}
		}
	}
}

var rawConnReadWriteMulticastICMPTests = []struct {
	grp, src *net.IPAddr
}{
	{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727

	{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
}

func TestRawConnReadWriteMulticastICMP(t *testing.T) {
	if testing.Short() {
		t.Skip("to avoid external network")
	}
	if m, ok := nettest.SupportsRawIPSocket(); !ok {
		t.Skip(m)
	}
	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
	if ifi == nil {
		t.Skipf("not available on %s", runtime.GOOS)
	}

	for _, tt := range rawConnReadWriteMulticastICMPTests {
		c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
		if err != nil {
			t.Fatal(err)
		}
		defer c.Close()

		r, err := ipv4.NewRawConn(c)
		if err != nil {
			t.Fatal(err)
		}
		defer r.Close()
		if tt.src == nil {
			if err := r.JoinGroup(ifi, tt.grp); err != nil {
				t.Fatal(err)
			}
			defer r.LeaveGroup(ifi, tt.grp)
		} else {
			if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
				switch runtime.GOOS {
				case "freebsd", "linux":
				default: // platforms that don't support IGMPv2/3 fail here
					t.Logf("not supported on %s", runtime.GOOS)
					continue
				}
				t.Fatal(err)
			}
			defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
		}
		if err := r.SetMulticastInterface(ifi); err != nil {
			t.Fatal(err)
		}
		if _, err := r.MulticastInterface(); err != nil {
			t.Fatal(err)
		}
		if err := r.SetMulticastLoopback(true); err != nil {
			t.Fatal(err)
		}
		if _, err := r.MulticastLoopback(); err != nil {
			t.Fatal(err)
		}
		cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface

		for i, toggle := range []bool{true, false, true} {
			wb, err := (&icmp.Message{
				Type: ipv4.ICMPTypeEcho, Code: 0,
				Body: &icmp.Echo{
					ID: os.Getpid() & 0xffff, Seq: i + 1,
					Data: []byte("HELLO-R-U-THERE"),
				},
			}).Marshal(nil)
			if err != nil {
				t.Fatal(err)
			}
			wh := &ipv4.Header{
				Version:  ipv4.Version,
				Len:      ipv4.HeaderLen,
				TOS:      i + 1,
				TotalLen: ipv4.HeaderLen + len(wb),
				Protocol: 1,
				Dst:      tt.grp.IP,
			}
			if err := r.SetControlMessage(cf, toggle); err != nil {
				if nettest.ProtocolNotSupported(err) {
					t.Logf("not supported on %s", runtime.GOOS)
					continue
				}
				t.Fatal(err)
			}
			if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
				t.Fatal(err)
			}
			r.SetMulticastTTL(i + 1)
			if err := r.WriteTo(wh, wb, nil); err != nil {
				t.Fatal(err)
			}
			rb := make([]byte, ipv4.HeaderLen+128)
			if rh, b, _, err := r.ReadFrom(rb); err != nil {
				t.Fatal(err)
			} else {
				m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
				if err != nil {
					t.Fatal(err)
				}
				switch {
				case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
				case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
				default:
					t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
				}
			}
		}
	}
}


text:
// Copyright 2012 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.

package ipv4

import (
	"syscall"

	"golang.org/x/net/internal/socket"
)

func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
	// TODO(mikio): implement this
	return syscall.EWINDOWS
}


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_linux.go

package ipv4

const (
	sysIP_TOS             = 0x1
	sysIP_TTL             = 0x2
	sysIP_HDRINCL         = 0x3
	sysIP_OPTIONS         = 0x4
	sysIP_ROUTER_ALERT    = 0x5
	sysIP_RECVOPTS        = 0x6
	sysIP_RETOPTS         = 0x7
	sysIP_PKTINFO         = 0x8
	sysIP_PKTOPTIONS      = 0x9
	sysIP_MTU_DISCOVER    = 0xa
	sysIP_RECVERR         = 0xb
	sysIP_RECVTTL         = 0xc
	sysIP_RECVTOS         = 0xd
	sysIP_MTU             = 0xe
	sysIP_FREEBIND        = 0xf
	sysIP_TRANSPARENT     = 0x13
	sysIP_RECVRETOPTS     = 0x7
	sysIP_ORIGDSTADDR     = 0x14
	sysIP_RECVORIGDSTADDR = 0x14
	sysIP_MINTTL          = 0x15
	sysIP_NODEFRAG        = 0x16
	sysIP_UNICAST_IF      = 0x32

	sysIP_MULTICAST_IF           = 0x20
	sysIP_MULTICAST_TTL          = 0x21
	sysIP_MULTICAST_LOOP         = 0x22
	sysIP_ADD_MEMBERSHIP         = 0x23
	sysIP_DROP_MEMBERSHIP        = 0x24
	sysIP_UNBLOCK_SOURCE         = 0x25
	sysIP_BLOCK_SOURCE           = 0x26
	sysIP_ADD_SOURCE_MEMBERSHIP  = 0x27
	sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
	sysIP_MSFILTER               = 0x29
	sysMCAST_JOIN_GROUP          = 0x2a
	sysMCAST_LEAVE_GROUP         = 0x2d
	sysMCAST_JOIN_SOURCE_GROUP   = 0x2e
	sysMCAST_LEAVE_SOURCE_GROUP  = 0x2f
	sysMCAST_BLOCK_SOURCE        = 0x2b
	sysMCAST_UNBLOCK_SOURCE      = 0x2c
	sysMCAST_MSFILTER            = 0x30
	sysIP_MULTICAST_ALL          = 0x31

	sysICMP_FILTER = 0x1

	sysSO_EE_ORIGIN_NONE         = 0x0
	sysSO_EE_ORIGIN_LOCAL        = 0x1
	sysSO_EE_ORIGIN_ICMP         = 0x2
	sysSO_EE_ORIGIN_ICMP6        = 0x3
	sysSO_EE_ORIGIN_TXSTATUS     = 0x4
	sysSO_EE_ORIGIN_TIMESTAMPING = 0x4

	sysSOL_SOCKET       = 0x1
	sysSO_ATTACH_FILTER = 0x1a

	sizeofKernelSockaddrStorage = 0x80
	sizeofSockaddrInet          = 0x10
	sizeofInetPktinfo           = 0xc
	sizeofSockExtendedErr       = 0x10

	sizeofIPMreq         = 0x8
	sizeofIPMreqn        = 0xc
	sizeofIPMreqSource   = 0xc
	sizeofGroupReq       = 0x88
	sizeofGroupSourceReq = 0x108

	sizeofICMPFilter = 0x4

	sizeofSockFprog = 0x10
)

type kernelSockaddrStorage struct {
	Family  uint16
	X__data [126]int8
}

type sockaddrInet struct {
	Family uint16
	Port   uint16
	Addr   [4]byte /* in_addr */
	X__pad [8]uint8
}

type inetPktinfo struct {
	Ifindex  int32
	Spec_dst [4]byte /* in_addr */
	Addr     [4]byte /* in_addr */
}

type sockExtendedErr struct {
	Errno  uint32
	Origin uint8
	Type   uint8
	Code   uint8
	Pad    uint8
	Info   uint32
	Data   uint32
}

type ipMreq struct {
	Multiaddr [4]byte /* in_addr */
	Interface [4]byte /* in_addr */
}

type ipMreqn struct {
	Multiaddr [4]byte /* in_addr */
	Address   [4]byte /* in_addr */
	Ifindex   int32
}

type ipMreqSource struct {
	Multiaddr  uint32
	Interface  uint32
	Sourceaddr uint32
}

type groupReq struct {
	Interface uint32
	Pad_cgo_0 [4]byte
	Group     kernelSockaddrStorage
}

type groupSourceReq struct {
	Interface uint32
	Pad_cgo_0 [4]byte
	Group     kernelSockaddrStorage
	Source    kernelSockaddrStorage
}

type icmpFilter struct {
	Data uint32
}

type sockFProg struct {
	Len       uint16
	Pad_cgo_0 [6]byte
	Filter    *sockFilter
}

type sockFilter struct {
	Code uint16
	Jt   uint8
	Jf   uint8
	K    uint32
}


text:
// Copyright 2012 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 nacl plan9 windows

package ipv4

import (
	"net"
	"syscall"
)

// ReadFrom reads a payload of the received IPv4 datagram, from the
// endpoint c, copying the payload into b. It returns the number of
// bytes copied into b, the control message cm and the source address
// src of the received datagram.
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
	if !c.ok() {
		return 0, nil, nil, syscall.EINVAL
	}
	if n, src, err = c.PacketConn.ReadFrom(b); err != nil {
		return 0, nil, nil, err
	}
	return
}

// WriteTo writes a payload of the IPv4 datagram, to the destination
// address dst through the endpoint c, copying the payload from b. It
// returns the number of bytes written. The control message cm allows
// the datagram path and the outgoing interface to be specified.
// Currently only Darwin and Linux support this. The cm may be nil if
// control of the outgoing datagram is not required.
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	if dst == nil {
		return 0, errMissingAddress
	}
	return c.PacketConn.WriteTo(b, dst)
}


text:
// Copyright 2014 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 ignore

// +godefs map struct_in_addr [4]byte /* in_addr */

package ipv4

/*
#include <sys/socket.h>

#include <netinet/in.h>
*/
import "C"

const (
	sysIP_OPTIONS     = C.IP_OPTIONS
	sysIP_HDRINCL     = C.IP_HDRINCL
	sysIP_TOS         = C.IP_TOS
	sysIP_TTL         = C.IP_TTL
	sysIP_RECVOPTS    = C.IP_RECVOPTS
	sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
	sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
	sysIP_SENDSRCADDR = C.IP_SENDSRCADDR
	sysIP_RETOPTS     = C.IP_RETOPTS
	sysIP_RECVIF      = C.IP_RECVIF
	sysIP_ONESBCAST   = C.IP_ONESBCAST
	sysIP_BINDANY     = C.IP_BINDANY
	sysIP_RECVTTL     = C.IP_RECVTTL
	sysIP_MINTTL      = C.IP_MINTTL
	sysIP_DONTFRAG    = C.IP_DONTFRAG
	sysIP_RECVTOS     = C.IP_RECVTOS

	sysIP_MULTICAST_IF           = C.IP_MULTICAST_IF
	sysIP_MULTICAST_TTL          = C.IP_MULTICAST_TTL
	sysIP_MULTICAST_LOOP         = C.IP_MULTICAST_LOOP
	sysIP_ADD_MEMBERSHIP         = C.IP_ADD_MEMBERSHIP
	sysIP_DROP_MEMBERSHIP        = C.IP_DROP_MEMBERSHIP
	sysIP_MULTICAST_VIF          = C.IP_MULTICAST_VIF
	sysIP_ADD_SOURCE_MEMBERSHIP  = C.IP_ADD_SOURCE_MEMBERSHIP
	sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
	sysIP_BLOCK_SOURCE           = C.IP_BLOCK_SOURCE
	sysIP_UNBLOCK_SOURCE         = C.IP_UNBLOCK_SOURCE
	sysMCAST_JOIN_GROUP          = C.MCAST_JOIN_GROUP
	sysMCAST_LEAVE_GROUP         = C.MCAST_LEAVE_GROUP
	sysMCAST_JOIN_SOURCE_GROUP   = C.MCAST_JOIN_SOURCE_GROUP
	sysMCAST_LEAVE_SOURCE_GROUP  = C.MCAST_LEAVE_SOURCE_GROUP
	sysMCAST_BLOCK_SOURCE        = C.MCAST_BLOCK_SOURCE
	sysMCAST_UNBLOCK_SOURCE      = C.MCAST_UNBLOCK_SOURCE

	sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
	sizeofSockaddrInet    = C.sizeof_struct_sockaddr_in

	sizeofIPMreq         = C.sizeof_struct_ip_mreq
	sizeofIPMreqn        = C.sizeof_struct_ip_mreqn
	sizeofIPMreqSource   = C.sizeof_struct_ip_mreq_source
	sizeofGroupReq       = C.sizeof_struct_group_req
	sizeofGroupSourceReq = C.sizeof_struct_group_source_req
)

type sockaddrStorage C.struct_sockaddr_storage

type sockaddrInet C.struct_sockaddr_in

type ipMreq C.struct_ip_mreq

type ipMreqn C.struct_ip_mreqn

type ipMreqSource C.struct_ip_mreq_source

type groupReq C.struct_group_req

type groupSourceReq C.struct_group_source_req


text:
// Copyright 2012 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.

package ipv4

import (
	"net"
	"syscall"

	"golang.org/x/net/bpf"
)

// MulticastTTL returns the time-to-live field value for outgoing
// multicast packets.
func (c *dgramOpt) MulticastTTL() (int, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	so, ok := sockOpts[ssoMulticastTTL]
	if !ok {
		return 0, errOpNoSupport
	}
	return so.GetInt(c.Conn)
}

// SetMulticastTTL sets the time-to-live field value for future
// outgoing multicast packets.
func (c *dgramOpt) SetMulticastTTL(ttl int) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoMulticastTTL]
	if !ok {
		return errOpNoSupport
	}
	return so.SetInt(c.Conn, ttl)
}

// MulticastInterface returns the default interface for multicast
// packet transmissions.
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
	if !c.ok() {
		return nil, syscall.EINVAL
	}
	so, ok := sockOpts[ssoMulticastInterface]
	if !ok {
		return nil, errOpNoSupport
	}
	return so.getMulticastInterface(c.Conn)
}

// SetMulticastInterface sets the default interface for future
// multicast packet transmissions.
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoMulticastInterface]
	if !ok {
		return errOpNoSupport
	}
	return so.setMulticastInterface(c.Conn, ifi)
}

// MulticastLoopback reports whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) MulticastLoopback() (bool, error) {
	if !c.ok() {
		return false, syscall.EINVAL
	}
	so, ok := sockOpts[ssoMulticastLoopback]
	if !ok {
		return false, errOpNoSupport
	}
	on, err := so.GetInt(c.Conn)
	if err != nil {
		return false, err
	}
	return on == 1, nil
}

// SetMulticastLoopback sets whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoMulticastLoopback]
	if !ok {
		return errOpNoSupport
	}
	return so.SetInt(c.Conn, boolint(on))
}

// JoinGroup joins the group address group on the interface ifi.
// By default all sources that can cast data to group are accepted.
// It's possible to mute and unmute data transmission from a specific
// source by using ExcludeSourceSpecificGroup and
// IncludeSourceSpecificGroup.
// JoinGroup uses the system assigned multicast interface when ifi is
// nil, although this is not recommended because the assignment
// depends on platforms and sometimes it might require routing
// configuration.
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoJoinGroup]
	if !ok {
		return errOpNoSupport
	}
	grp := netAddrToIP4(group)
	if grp == nil {
		return errMissingAddress
	}
	return so.setGroup(c.Conn, ifi, grp)
}

// LeaveGroup leaves the group address group on the interface ifi
// regardless of whether the group is any-source group or
// source-specific group.
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoLeaveGroup]
	if !ok {
		return errOpNoSupport
	}
	grp := netAddrToIP4(group)
	if grp == nil {
		return errMissingAddress
	}
	return so.setGroup(c.Conn, ifi, grp)
}

// JoinSourceSpecificGroup joins the source-specific group comprising
// group and source on the interface ifi.
// JoinSourceSpecificGroup uses the system assigned multicast
// interface when ifi is nil, although this is not recommended because
// the assignment depends on platforms and sometimes it might require
// routing configuration.
func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoJoinSourceGroup]
	if !ok {
		return errOpNoSupport
	}
	grp := netAddrToIP4(group)
	if grp == nil {
		return errMissingAddress
	}
	src := netAddrToIP4(source)
	if src == nil {
		return errMissingAddress
	}
	return so.setSourceGroup(c.Conn, ifi, grp, src)
}

// LeaveSourceSpecificGroup leaves the source-specific group on the
// interface ifi.
func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoLeaveSourceGroup]
	if !ok {
		return errOpNoSupport
	}
	grp := netAddrToIP4(group)
	if grp == nil {
		return errMissingAddress
	}
	src := netAddrToIP4(source)
	if src == nil {
		return errMissingAddress
	}
	return so.setSourceGroup(c.Conn, ifi, grp, src)
}

// ExcludeSourceSpecificGroup excludes the source-specific group from
// the already joined any-source groups by JoinGroup on the interface
// ifi.
func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoBlockSourceGroup]
	if !ok {
		return errOpNoSupport
	}
	grp := netAddrToIP4(group)
	if grp == nil {
		return errMissingAddress
	}
	src := netAddrToIP4(source)
	if src == nil {
		return errMissingAddress
	}
	return so.setSourceGroup(c.Conn, ifi, grp, src)
}

// IncludeSourceSpecificGroup includes the excluded source-specific
// group by ExcludeSourceSpecificGroup again on the interface ifi.
func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoUnblockSourceGroup]
	if !ok {
		return errOpNoSupport
	}
	grp := netAddrToIP4(group)
	if grp == nil {
		return errMissingAddress
	}
	src := netAddrToIP4(source)
	if src == nil {
		return errMissingAddress
	}
	return so.setSourceGroup(c.Conn, ifi, grp, src)
}

// ICMPFilter returns an ICMP filter.
// Currently only Linux supports this.
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
	if !c.ok() {
		return nil, syscall.EINVAL
	}
	so, ok := sockOpts[ssoICMPFilter]
	if !ok {
		return nil, errOpNoSupport
	}
	return so.getICMPFilter(c.Conn)
}

// SetICMPFilter deploys the ICMP filter.
// Currently only Linux supports this.
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoICMPFilter]
	if !ok {
		return errOpNoSupport
	}
	return so.setICMPFilter(c.Conn, f)
}

// SetBPF attaches a BPF program to the connection.
//
// Only supported on Linux.
func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
	if !c.ok() {
		return syscall.EINVAL
	}
	so, ok := sockOpts[ssoAttachFilter]
	if !ok {
		return errOpNoSupport
	}
	return so.setBPF(c.Conn, filter)
}


text:
// Copyright 2017 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,!solaris,!windows

package ipv4

import (
	"net"

	"golang.org/x/net/internal/socket"
)

func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
	return errOpNoSupport
}

func (so *sockOpt) getMulticastIf(c *socket.Conn) (*net.Interface, error) {
	return nil, errOpNoSupport
}

func (so *sockOpt) setMulticastIf(c *socket.Conn, ifi *net.Interface) error {
	return errOpNoSupport
}


text:
// 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.

package ipv4_test

import (
	"net"
	"runtime"
	"testing"
	"time"

	"golang.org/x/net/bpf"
	"golang.org/x/net/ipv4"
)

func TestBPF(t *testing.T) {
	if runtime.GOOS != "linux" {
		t.Skipf("not supported on %s", runtime.GOOS)
	}

	l, err := net.ListenPacket("udp4", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer l.Close()

	p := ipv4.NewPacketConn(l)

	// This filter accepts UDP packets whose first payload byte is
	// even.
	prog, err := bpf.Assemble([]bpf.Instruction{
		// Load the first byte of the payload (skipping UDP header).
		bpf.LoadAbsolute{Off: 8, Size: 1},
		// Select LSB of the byte.
		bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
		// Byte is even?
		bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
		// Accept.
		bpf.RetConstant{Val: 4096},
		// Ignore.
		bpf.RetConstant{Val: 0},
	})
	if err != nil {
		t.Fatalf("compiling BPF: %s", err)
	}

	if err = p.SetBPF(prog); err != nil {
		t.Fatalf("attaching filter to Conn: %s", err)
	}

	s, err := net.Dial("udp4", l.LocalAddr().String())
	if err != nil {
		t.Fatal(err)
	}
	defer s.Close()
	go func() {
		for i := byte(0); i < 10; i++ {
			s.Write([]byte{i})
		}
	}()

	l.SetDeadline(time.Now().Add(2 * time.Second))
	seen := make([]bool, 5)
	for {
		var b [512]byte
		n, _, err := l.ReadFrom(b[:])
		if err != nil {
			t.Fatalf("reading from listener: %s", err)
		}
		if n != 1 {
			t.Fatalf("unexpected packet length, want 1, got %d", n)
		}
		if b[0] >= 10 {
			t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
		}
		if b[0]%2 != 0 {
			t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
		}
		seen[b[0]/2] = true

		seenAll := true
		for _, v := range seen {
			if !v {
				seenAll = false
				break
			}
		}
		if seenAll {
			break
		}
	}
}


text:
// Copyright 2012 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 ipv4

import (
	"net"
	"syscall"
	"unsafe"

	"golang.org/x/net/internal/iana"
	"golang.org/x/net/internal/socket"
)

func marshalDst(b []byte, cm *ControlMessage) []byte {
	m := socket.ControlMessage(b)
	m.MarshalHeader(iana.ProtocolIP, sysIP_RECVDSTADDR, net.IPv4len)
	return m.Next(net.IPv4len)
}

func parseDst(cm *ControlMessage, b []byte) {
	if len(cm.Dst) < net.IPv4len {
		cm.Dst = make(net.IP, net.IPv4len)
	}
	copy(cm.Dst, b[:net.IPv4len])
}

func marshalInterface(b []byte, cm *ControlMessage) []byte {
	m := socket.ControlMessage(b)
	m.MarshalHeader(iana.ProtocolIP, sysIP_RECVIF, syscall.SizeofSockaddrDatalink)
	return m.Next(syscall.SizeofSockaddrDatalink)
}

func parseInterface(cm *ControlMessage, b []byte) {
	sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&b[0]))
	cm.IfIndex = int(sadl.Index)
}


text:
// Copyright 2014 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.

package ipv4

import (
	"net"
	"runtime"
	"strings"
	"syscall"
	"unsafe"

	"golang.org/x/net/internal/iana"
	"golang.org/x/net/internal/socket"
)

var (
	ctlOpts = [ctlMax]ctlOpt{
		ctlTTL:       {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
		ctlDst:       {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
		ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
	}

	sockOpts = map[int]*sockOpt{
		ssoTOS:                {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
		ssoTTL:                {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
		ssoMulticastTTL:       {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
		ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
		ssoMulticastLoopback:  {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
		ssoReceiveTTL:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
		ssoReceiveDst:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
		ssoReceiveInterface:   {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
		ssoHeaderPrepend:      {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
		ssoJoinGroup:          {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
		ssoLeaveGroup:         {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
		ssoJoinSourceGroup:    {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
		ssoLeaveSourceGroup:   {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
		ssoBlockSourceGroup:   {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
		ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
	}
)

func init() {
	freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
	if freebsdVersion >= 1000000 {
		sockOpts[ssoMulticastInterface] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: sizeofIPMreqn}, typ: ssoTypeIPMreqn}
	}
	if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
		archs, _ := syscall.Sysctl("kern.supported_archs")
		for _, s := range strings.Fields(archs) {
			if s == "amd64" {
				freebsd32o64 = true
				break
			}
		}
	}
}

func (gr *groupReq) setGroup(grp net.IP) {
	sa := (*sockaddrInet)(unsafe.Pointer(&gr.Group))
	sa.Len = sizeofSockaddrInet
	sa.Family = syscall.AF_INET
	copy(sa.Addr[:], grp)
}

func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) {
	sa := (*sockaddrInet)(unsafe.Pointer(&gsr.Group))
	sa.Len = sizeofSockaddrInet
	sa.Family = syscall.AF_INET
	copy(sa.Addr[:], grp)
	sa = (*sockaddrInet)(unsafe.Pointer(&gsr.Source))
	sa.Len = sizeofSockaddrInet
	sa.Family = syscall.AF_INET
	copy(sa.Addr[:], src)
}


text:
// 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.

package route

import "testing"

func TestFetchAndParseRIBOnDarwin(t *testing.T) {
	for _, typ := range []RIBType{sysNET_RT_FLAGS, sysNET_RT_DUMP2, sysNET_RT_IFLIST2} {
		var lastErr error
		var ms []Message
		for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
			rs, err := fetchAndParseRIB(af, typ)
			if err != nil {
				lastErr = err
				continue
			}
			ms = append(ms, rs...)
		}
		if len(ms) == 0 && lastErr != nil {
			t.Error(typ, lastErr)
			continue
		}
		ss, err := msgs(ms).validate()
		if err != nil {
			t.Error(typ, err)
			continue
		}
		for _, s := range ss {
			t.Log(s)
		}
	}
}


text:
// 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.

package route

import (
	"testing"
	"unsafe"
)

func TestFetchAndParseRIBOnFreeBSD(t *testing.T) {
	for _, typ := range []RIBType{sysNET_RT_IFMALIST} {
		var lastErr error
		var ms []Message
		for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
			rs, err := fetchAndParseRIB(af, typ)
			if err != nil {
				lastErr = err
				continue
			}
			ms = append(ms, rs...)
		}
		if len(ms) == 0 && lastErr != nil {
			t.Error(typ, lastErr)
			continue
		}
		ss, err := msgs(ms).validate()
		if err != nil {
			t.Error(typ, err)
			continue
		}
		for _, s := range ss {
			t.Log(s)
		}
	}
}

func TestFetchAndParseRIBOnFreeBSD10AndAbove(t *testing.T) {
	if _, err := FetchRIB(sysAF_UNSPEC, sysNET_RT_IFLISTL, 0); err != nil {
		t.Skip("NET_RT_IFLISTL not supported")
	}
	var p uintptr
	if kernelAlign != int(unsafe.Sizeof(p)) {
		t.Skip("NET_RT_IFLIST vs. NET_RT_IFLISTL doesn't work for 386 emulation on amd64")
	}

	var tests = [2]struct {
		typ  RIBType
		b    []byte
		msgs []Message
		ss   []string
	}{
		{typ: sysNET_RT_IFLIST},
		{typ: sysNET_RT_IFLISTL},
	}
	for i := range tests {
		var lastErr error
		for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
			rs, err := fetchAndParseRIB(af, tests[i].typ)
			if err != nil {
				lastErr = err
				continue
			}
			tests[i].msgs = append(tests[i].msgs, rs...)
		}
		if len(tests[i].msgs) == 0 && lastErr != nil {
			t.Error(tests[i].typ, lastErr)
			continue
		}
		tests[i].ss, lastErr = msgs(tests[i].msgs).validate()
		if lastErr != nil {
			t.Error(tests[i].typ, lastErr)
			continue
		}
		for _, s := range tests[i].ss {
			t.Log(s)
		}
	}
	for i := len(tests) - 1; i > 0; i-- {
		if len(tests[i].ss) != len(tests[i-1].ss) {
			t.Errorf("got %v; want %v", tests[i].ss, tests[i-1].ss)
			continue
		}
		for j, s1 := range tests[i].ss {
			s0 := tests[i-1].ss[j]
			if s1 != s0 {
				t.Errorf("got %s; want %s", s1, s0)
			}
		}
	}
}


text:
// 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

// This file contains duplicates of encoding/binary package.
//
// This package is supposed to be used by the net package of standard
// library. Therefore the package set used in the package must be the
// same as net package.

var (
	littleEndian binaryLittleEndian
	bigEndian    binaryBigEndian
)

type binaryByteOrder interface {
	Uint16([]byte) uint16
	Uint32([]byte) uint32
	PutUint16([]byte, uint16)
	PutUint32([]byte, uint32)
	Uint64([]byte) uint64
}

type binaryLittleEndian struct{}

func (binaryLittleEndian) Uint16(b []byte) uint16 {
	_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
	return uint16(b[0]) | uint16(b[1])<<8
}

func (binaryLittleEndian) PutUint16(b []byte, v uint16) {
	_ = b[1] // early bounds check to guarantee safety of writes below
	b[0] = byte(v)
	b[1] = byte(v >> 8)
}

func (binaryLittleEndian) Uint32(b []byte) uint32 {
	_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}

func (binaryLittleEndian) PutUint32(b []byte, v uint32) {
	_ = b[3] // early bounds check to guarantee safety of writes below
	b[0] = byte(v)
	b[1] = byte(v >> 8)
	b[2] = byte(v >> 16)
	b[3] = byte(v >> 24)
}

func (binaryLittleEndian) Uint64(b []byte) uint64 {
	_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
	return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
		uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}

type binaryBigEndian struct{}

func (binaryBigEndian) Uint16(b []byte) uint16 {
	_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
	return uint16(b[1]) | uint16(b[0])<<8
}

func (binaryBigEndian) PutUint16(b []byte, v uint16) {
	_ = b[1] // early bounds check to guarantee safety of writes below
	b[0] = byte(v >> 8)
	b[1] = byte(v)
}

func (binaryBigEndian) Uint32(b []byte) uint32 {
	_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
	return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}

func (binaryBigEndian) PutUint32(b []byte, v uint32) {
	_ = b[3] // early bounds check to guarantee safety of writes below
	b[0] = byte(v >> 24)
	b[1] = byte(v >> 16)
	b[2] = byte(v >> 8)
	b[3] = byte(v)
}

func (binaryBigEndian) Uint64(b []byte) uint64 {
	_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
	return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
}


text:
// 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 dragonfly freebsd netbsd

package route

func (w *wireFormat) parseInterfaceAnnounceMessage(_ RIBType, b []byte) (Message, error) {
	if len(b) < w.bodyOff {
		return nil, errMessageTooShort
	}
	l := int(nativeEndian.Uint16(b[:2]))
	if len(b) < l {
		return nil, errInvalidMessage
	}
	m := &InterfaceAnnounceMessage{
		Version: int(b[2]),
		Type:    int(b[3]),
		Index:   int(nativeEndian.Uint16(b[4:6])),
		What:    int(nativeEndian.Uint16(b[22:24])),
		raw:     b[:l],
	}
	for i := 0; i < 16; i++ {
		if b[6+i] != 0 {
			continue
		}
		m.Name = string(b[6 : 6+i])
		break
	}
	return m, nil
}


text:
// 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 ignore

package route

/*
#include <sys/socket.h>
#include <sys/sysctl.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>

#include <netinet/in.h>
*/
import "C"

const (
	sysAF_UNSPEC = C.AF_UNSPEC
	sysAF_INET   = C.AF_INET
	sysAF_ROUTE  = C.AF_ROUTE
	sysAF_LINK   = C.AF_LINK
	sysAF_INET6  = C.AF_INET6

	sysSOCK_RAW = C.SOCK_RAW

	sysNET_RT_DUMP    = C.NET_RT_DUMP
	sysNET_RT_FLAGS   = C.NET_RT_FLAGS
	sysNET_RT_IFLIST  = C.NET_RT_IFLIST
	sysNET_RT_STATS   = C.NET_RT_STATS
	sysNET_RT_TABLE   = C.NET_RT_TABLE
	sysNET_RT_IFNAMES = C.NET_RT_IFNAMES
	sysNET_RT_MAXID   = C.NET_RT_MAXID
)

const (
	sysCTL_MAXNAME = C.CTL_MAXNAME

	sysCTL_UNSPEC  = C.CTL_UNSPEC
	sysCTL_KERN    = C.CTL_KERN
	sysCTL_VM      = C.CTL_VM
	sysCTL_FS      = C.CTL_FS
	sysCTL_NET     = C.CTL_NET
	sysCTL_DEBUG   = C.CTL_DEBUG
	sysCTL_HW      = C.CTL_HW
	sysCTL_MACHDEP = C.CTL_MACHDEP
	sysCTL_DDB     = C.CTL_DDB
	sysCTL_VFS     = C.CTL_VFS
	sysCTL_MAXID   = C.CTL_MAXID
)

const (
	sysRTM_VERSION = C.RTM_VERSION

	sysRTM_ADD        = C.RTM_ADD
	sysRTM_DELETE     = C.RTM_DELETE
	sysRTM_CHANGE     = C.RTM_CHANGE
	sysRTM_GET        = C.RTM_GET
	sysRTM_LOSING     = C.RTM_LOSING
	sysRTM_REDIRECT   = C.RTM_REDIRECT
	sysRTM_MISS       = C.RTM_MISS
	sysRTM_LOCK       = C.RTM_LOCK
	sysRTM_RESOLVE    = C.RTM_RESOLVE
	sysRTM_NEWADDR    = C.RTM_NEWADDR
	sysRTM_DELADDR    = C.RTM_DELADDR
	sysRTM_IFINFO     = C.RTM_IFINFO
	sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
	sysRTM_DESYNC     = C.RTM_DESYNC
	sysRTM_INVALIDATE = C.RTM_INVALIDATE
	sysRTM_BFD        = C.RTM_BFD
	sysRTM_PROPOSAL   = C.RTM_PROPOSAL

	sysRTA_DST     = C.RTA_DST
	sysRTA_GATEWAY = C.RTA_GATEWAY
	sysRTA_NETMASK = C.RTA_NETMASK
	sysRTA_GENMASK = C.RTA_GENMASK
	sysRTA_IFP     = C.RTA_IFP
	sysRTA_IFA     = C.RTA_IFA
	sysRTA_AUTHOR  = C.RTA_AUTHOR
	sysRTA_BRD     = C.RTA_BRD
	sysRTA_SRC     = C.RTA_SRC
	sysRTA_SRCMASK = C.RTA_SRCMASK
	sysRTA_LABEL   = C.RTA_LABEL
	sysRTA_BFD     = C.RTA_BFD
	sysRTA_DNS     = C.RTA_DNS
	sysRTA_STATIC  = C.RTA_STATIC
	sysRTA_SEARCH  = C.RTA_SEARCH

	sysRTAX_DST     = C.RTAX_DST
	sysRTAX_GATEWAY = C.RTAX_GATEWAY
	sysRTAX_NETMASK = C.RTAX_NETMASK
	sysRTAX_GENMASK = C.RTAX_GENMASK
	sysRTAX_IFP     = C.RTAX_IFP
	sysRTAX_IFA     = C.RTAX_IFA
	sysRTAX_AUTHOR  = C.RTAX_AUTHOR
	sysRTAX_BRD     = C.RTAX_BRD
	sysRTAX_SRC     = C.RTAX_SRC
	sysRTAX_SRCMASK = C.RTAX_SRCMASK
	sysRTAX_LABEL   = C.RTAX_LABEL
	sysRTAX_BFD     = C.RTAX_BFD
	sysRTAX_DNS     = C.RTAX_DNS
	sysRTAX_STATIC  = C.RTAX_STATIC
	sysRTAX_SEARCH  = C.RTAX_SEARCH
	sysRTAX_MAX     = C.RTAX_MAX
)

const (
	sizeofRtMsghdr = C.sizeof_struct_rt_msghdr

	sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
	sizeofSockaddrInet    = C.sizeof_struct_sockaddr_in
	sizeofSockaddrInet6   = C.sizeof_struct_sockaddr_in6
)


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_dragonfly.go

package route

const (
	sysAF_UNSPEC = 0x0
	sysAF_INET   = 0x2
	sysAF_ROUTE  = 0x11
	sysAF_LINK   = 0x12
	sysAF_INET6  = 0x1c

	sysSOCK_RAW = 0x3

	sysNET_RT_DUMP   = 0x1
	sysNET_RT_FLAGS  = 0x2
	sysNET_RT_IFLIST = 0x3
	sysNET_RT_MAXID  = 0x4
)

const (
	sysCTL_MAXNAME = 0xc

	sysCTL_UNSPEC   = 0x0
	sysCTL_KERN     = 0x1
	sysCTL_VM       = 0x2
	sysCTL_VFS      = 0x3
	sysCTL_NET      = 0x4
	sysCTL_DEBUG    = 0x5
	sysCTL_HW       = 0x6
	sysCTL_MACHDEP  = 0x7
	sysCTL_USER     = 0x8
	sysCTL_P1003_1B = 0x9
	sysCTL_LWKT     = 0xa
	sysCTL_MAXID    = 0xb
)

const (
	sysRTM_VERSION = 0x6

	sysRTM_ADD        = 0x1
	sysRTM_DELETE     = 0x2
	sysRTM_CHANGE     = 0x3
	sysRTM_GET        = 0x4
	sysRTM_LOSING     = 0x5
	sysRTM_REDIRECT   = 0x6
	sysRTM_MISS       = 0x7
	sysRTM_LOCK       = 0x8
	sysRTM_OLDADD     = 0x9
	sysRTM_OLDDEL     = 0xa
	sysRTM_RESOLVE    = 0xb
	sysRTM_NEWADDR    = 0xc
	sysRTM_DELADDR    = 0xd
	sysRTM_IFINFO     = 0xe
	sysRTM_NEWMADDR   = 0xf
	sysRTM_DELMADDR   = 0x10
	sysRTM_IFANNOUNCE = 0x11
	sysRTM_IEEE80211  = 0x12

	sysRTA_DST     = 0x1
	sysRTA_GATEWAY = 0x2
	sysRTA_NETMASK = 0x4
	sysRTA_GENMASK = 0x8
	sysRTA_IFP     = 0x10
	sysRTA_IFA     = 0x20
	sysRTA_AUTHOR  = 0x40
	sysRTA_BRD     = 0x80
	sysRTA_MPLS1   = 0x100
	sysRTA_MPLS2   = 0x200
	sysRTA_MPLS3   = 0x400

	sysRTAX_DST     = 0x0
	sysRTAX_GATEWAY = 0x1
	sysRTAX_NETMASK = 0x2
	sysRTAX_GENMASK = 0x3
	sysRTAX_IFP     = 0x4
	sysRTAX_IFA     = 0x5
	sysRTAX_AUTHOR  = 0x6
	sysRTAX_BRD     = 0x7
	sysRTAX_MPLS1   = 0x8
	sysRTAX_MPLS2   = 0x9
	sysRTAX_MPLS3   = 0xa
	sysRTAX_MAX     = 0xb
)

const (
	sizeofIfMsghdrDragonFlyBSD4         = 0xb0
	sizeofIfaMsghdrDragonFlyBSD4        = 0x14
	sizeofIfmaMsghdrDragonFlyBSD4       = 0x10
	sizeofIfAnnouncemsghdrDragonFlyBSD4 = 0x18

	sizeofRtMsghdrDragonFlyBSD4  = 0x98
	sizeofRtMetricsDragonFlyBSD4 = 0x70

	sizeofSockaddrStorage = 0x80
	sizeofSockaddrInet    = 0x10
	sizeofSockaddrInet6   = 0x1c
)


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_freebsd.go

package route

const (
	sysAF_UNSPEC = 0x0
	sysAF_INET   = 0x2
	sysAF_ROUTE  = 0x11
	sysAF_LINK   = 0x12
	sysAF_INET6  = 0x1c

	sysSOCK_RAW = 0x3

	sysNET_RT_DUMP     = 0x1
	sysNET_RT_FLAGS    = 0x2
	sysNET_RT_IFLIST   = 0x3
	sysNET_RT_IFMALIST = 0x4
	sysNET_RT_IFLISTL  = 0x5
)

const (
	sysCTL_MAXNAME = 0x18

	sysCTL_UNSPEC   = 0x0
	sysCTL_KERN     = 0x1
	sysCTL_VM       = 0x2
	sysCTL_VFS      = 0x3
	sysCTL_NET      = 0x4
	sysCTL_DEBUG    = 0x5
	sysCTL_HW       = 0x6
	sysCTL_MACHDEP  = 0x7
	sysCTL_USER     = 0x8
	sysCTL_P1003_1B = 0x9
)

const (
	sysRTM_VERSION = 0x5

	sysRTM_ADD        = 0x1
	sysRTM_DELETE     = 0x2
	sysRTM_CHANGE     = 0x3
	sysRTM_GET        = 0x4
	sysRTM_LOSING     = 0x5
	sysRTM_REDIRECT   = 0x6
	sysRTM_MISS       = 0x7
	sysRTM_LOCK       = 0x8
	sysRTM_RESOLVE    = 0xb
	sysRTM_NEWADDR    = 0xc
	sysRTM_DELADDR    = 0xd
	sysRTM_IFINFO     = 0xe
	sysRTM_NEWMADDR   = 0xf
	sysRTM_DELMADDR   = 0x10
	sysRTM_IFANNOUNCE = 0x11
	sysRTM_IEEE80211  = 0x12

	sysRTA_DST     = 0x1
	sysRTA_GATEWAY = 0x2
	sysRTA_NETMASK = 0x4
	sysRTA_GENMASK = 0x8
	sysRTA_IFP     = 0x10
	sysRTA_IFA     = 0x20
	sysRTA_AUTHOR  = 0x40
	sysRTA_BRD     = 0x80

	sysRTAX_DST     = 0x0
	sysRTAX_GATEWAY = 0x1
	sysRTAX_NETMASK = 0x2
	sysRTAX_GENMASK = 0x3
	sysRTAX_IFP     = 0x4
	sysRTAX_IFA     = 0x5
	sysRTAX_AUTHOR  = 0x6
	sysRTAX_BRD     = 0x7
	sysRTAX_MAX     = 0x8
)

const (
	sizeofIfMsghdrlFreeBSD10        = 0x68
	sizeofIfaMsghdrFreeBSD10        = 0x14
	sizeofIfaMsghdrlFreeBSD10       = 0x6c
	sizeofIfmaMsghdrFreeBSD10       = 0x10
	sizeofIfAnnouncemsghdrFreeBSD10 = 0x18

	sizeofRtMsghdrFreeBSD10  = 0x5c
	sizeofRtMetricsFreeBSD10 = 0x38

	sizeofIfMsghdrFreeBSD7  = 0x70
	sizeofIfMsghdrFreeBSD8  = 0x70
	sizeofIfMsghdrFreeBSD9  = 0x70
	sizeofIfMsghdrFreeBSD10 = 0x70
	sizeofIfMsghdrFreeBSD11 = 0xa8

	sizeofIfDataFreeBSD7  = 0x60
	sizeofIfDataFreeBSD8  = 0x60
	sizeofIfDataFreeBSD9  = 0x60
	sizeofIfDataFreeBSD10 = 0x60
	sizeofIfDataFreeBSD11 = 0x98

	sizeofIfMsghdrlFreeBSD10Emu        = 0x68
	sizeofIfaMsghdrFreeBSD10Emu        = 0x14
	sizeofIfaMsghdrlFreeBSD10Emu       = 0x6c
	sizeofIfmaMsghdrFreeBSD10Emu       = 0x10
	sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18

	sizeofRtMsghdrFreeBSD10Emu  = 0x5c
	sizeofRtMetricsFreeBSD10Emu = 0x38

	sizeofIfMsghdrFreeBSD7Emu  = 0x70
	sizeofIfMsghdrFreeBSD8Emu  = 0x70
	sizeofIfMsghdrFreeBSD9Emu  = 0x70
	sizeofIfMsghdrFreeBSD10Emu = 0x70
	sizeofIfMsghdrFreeBSD11Emu = 0xa8

	sizeofIfDataFreeBSD7Emu  = 0x60
	sizeofIfDataFreeBSD8Emu  = 0x60
	sizeofIfDataFreeBSD9Emu  = 0x60
	sizeofIfDataFreeBSD10Emu = 0x60
	sizeofIfDataFreeBSD11Emu = 0x98

	sizeofSockaddrStorage = 0x80
	sizeofSockaddrInet    = 0x10
	sizeofSockaddrInet6   = 0x1c
)


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_freebsd.go

package route

const (
	sysAF_UNSPEC = 0x0
	sysAF_INET   = 0x2
	sysAF_ROUTE  = 0x11
	sysAF_LINK   = 0x12
	sysAF_INET6  = 0x1c

	sysSOCK_RAW = 0x3

	sysNET_RT_DUMP     = 0x1
	sysNET_RT_FLAGS    = 0x2
	sysNET_RT_IFLIST   = 0x3
	sysNET_RT_IFMALIST = 0x4
	sysNET_RT_IFLISTL  = 0x5
)

const (
	sysCTL_MAXNAME = 0x18

	sysCTL_UNSPEC   = 0x0
	sysCTL_KERN     = 0x1
	sysCTL_VM       = 0x2
	sysCTL_VFS      = 0x3
	sysCTL_NET      = 0x4
	sysCTL_DEBUG    = 0x5
	sysCTL_HW       = 0x6
	sysCTL_MACHDEP  = 0x7
	sysCTL_USER     = 0x8
	sysCTL_P1003_1B = 0x9
)

const (
	sysRTM_VERSION = 0x5

	sysRTM_ADD        = 0x1
	sysRTM_DELETE     = 0x2
	sysRTM_CHANGE     = 0x3
	sysRTM_GET        = 0x4
	sysRTM_LOSING     = 0x5
	sysRTM_REDIRECT   = 0x6
	sysRTM_MISS       = 0x7
	sysRTM_LOCK       = 0x8
	sysRTM_RESOLVE    = 0xb
	sysRTM_NEWADDR    = 0xc
	sysRTM_DELADDR    = 0xd
	sysRTM_IFINFO     = 0xe
	sysRTM_NEWMADDR   = 0xf
	sysRTM_DELMADDR   = 0x10
	sysRTM_IFANNOUNCE = 0x11
	sysRTM_IEEE80211  = 0x12

	sysRTA_DST     = 0x1
	sysRTA_GATEWAY = 0x2
	sysRTA_NETMASK = 0x4
	sysRTA_GENMASK = 0x8
	sysRTA_IFP     = 0x10
	sysRTA_IFA     = 0x20
	sysRTA_AUTHOR  = 0x40
	sysRTA_BRD     = 0x80

	sysRTAX_DST     = 0x0
	sysRTAX_GATEWAY = 0x1
	sysRTAX_NETMASK = 0x2
	sysRTAX_GENMASK = 0x3
	sysRTAX_IFP     = 0x4
	sysRTAX_IFA     = 0x5
	sysRTAX_AUTHOR  = 0x6
	sysRTAX_BRD     = 0x7
	sysRTAX_MAX     = 0x8
)

const (
	sizeofIfMsghdrlFreeBSD10        = 0xb0
	sizeofIfaMsghdrFreeBSD10        = 0x14
	sizeofIfaMsghdrlFreeBSD10       = 0xb0
	sizeofIfmaMsghdrFreeBSD10       = 0x10
	sizeofIfAnnouncemsghdrFreeBSD10 = 0x18

	sizeofRtMsghdrFreeBSD10  = 0x98
	sizeofRtMetricsFreeBSD10 = 0x70

	sizeofIfMsghdrFreeBSD7  = 0xa8
	sizeofIfMsghdrFreeBSD8  = 0xa8
	sizeofIfMsghdrFreeBSD9  = 0xa8
	sizeofIfMsghdrFreeBSD10 = 0xa8
	sizeofIfMsghdrFreeBSD11 = 0xa8

	sizeofIfDataFreeBSD7  = 0x98
	sizeofIfDataFreeBSD8  = 0x98
	sizeofIfDataFreeBSD9  = 0x98
	sizeofIfDataFreeBSD10 = 0x98
	sizeofIfDataFreeBSD11 = 0x98

	sizeofIfMsghdrlFreeBSD10Emu        = 0xb0
	sizeofIfaMsghdrFreeBSD10Emu        = 0x14
	sizeofIfaMsghdrlFreeBSD10Emu       = 0xb0
	sizeofIfmaMsghdrFreeBSD10Emu       = 0x10
	sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18

	sizeofRtMsghdrFreeBSD10Emu  = 0x98
	sizeofRtMetricsFreeBSD10Emu = 0x70

	sizeofIfMsghdrFreeBSD7Emu  = 0xa8
	sizeofIfMsghdrFreeBSD8Emu  = 0xa8
	sizeofIfMsghdrFreeBSD9Emu  = 0xa8
	sizeofIfMsghdrFreeBSD10Emu = 0xa8
	sizeofIfMsghdrFreeBSD11Emu = 0xa8

	sizeofIfDataFreeBSD7Emu  = 0x98
	sizeofIfDataFreeBSD8Emu  = 0x98
	sizeofIfDataFreeBSD9Emu  = 0x98
	sizeofIfDataFreeBSD10Emu = 0x98
	sizeofIfDataFreeBSD11Emu = 0x98

	sizeofSockaddrStorage = 0x80
	sizeofSockaddrInet    = 0x10
	sizeofSockaddrInet6   = 0x1c
)


text:
// 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.

package route

func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, error) {
	var extOff, bodyOff int
	if typ == sysNET_RT_IFLISTL {
		if len(b) < 20 {
			return nil, errMessageTooShort
		}
		extOff = int(nativeEndian.Uint16(b[18:20]))
		bodyOff = int(nativeEndian.Uint16(b[16:18]))
	} else {
		extOff = w.extOff
		bodyOff = w.bodyOff
	}
	if len(b) < extOff || len(b) < bodyOff {
		return nil, errInvalidMessage
	}
	l := int(nativeEndian.Uint16(b[:2]))
	if len(b) < l {
		return nil, errInvalidMessage
	}
	attrs := uint(nativeEndian.Uint32(b[4:8]))
	if attrs&sysRTA_IFP == 0 {
		return nil, nil
	}
	m := &InterfaceMessage{
		Version: int(b[2]),
		Type:    int(b[3]),
		Flags:   int(nativeEndian.Uint32(b[8:12])),
		Index:   int(nativeEndian.Uint16(b[12:14])),
		Addrs:   make([]Addr, sysRTAX_MAX),
		extOff:  extOff,
		raw:     b[:l],
	}
	a, err := parseLinkAddr(b[bodyOff:])
	if err != nil {
		return nil, err
	}
	m.Addrs[sysRTAX_IFP] = a
	m.Name = a.(*LinkAddr).Name
	return m, nil
}

func (w *wireFormat) parseInterfaceAddrMessage(typ RIBType, b []byte) (Message, error) {
	var bodyOff int
	if typ == sysNET_RT_IFLISTL {
		if len(b) < 24 {
			return nil, errMessageTooShort
		}
		bodyOff = int(nativeEndian.Uint16(b[16:18]))
	} else {
		bodyOff = w.bodyOff
	}
	if len(b) < bodyOff {
		return nil, errInvalidMessage
	}
	l := int(nativeEndian.Uint16(b[:2]))
	if len(b) < l {
		return nil, errInvalidMessage
	}
	m := &InterfaceAddrMessage{
		Version: int(b[2]),
		Type:    int(b[3]),
		Flags:   int(nativeEndian.Uint32(b[8:12])),
		Index:   int(nativeEndian.Uint16(b[12:14])),
		raw:     b[:l],
	}
	var err error
	m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[4:8])), parseKernelInetAddr, b[bodyOff:])
	if err != nil {
		return nil, err
	}
	return m, nil
}


text:
// 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

// An InterfaceMessage represents an interface message.
type InterfaceMessage struct {
	Version int    // message version
	Type    int    // message type
	Flags   int    // interface flags
	Index   int    // interface index
	Name    string // interface name
	Addrs   []Addr // addresses

	extOff int    // offset of header extension
	raw    []byte // raw message
}

// An InterfaceAddrMessage represents an interface address message.
type InterfaceAddrMessage struct {
	Version int    // message version
	Type    int    // message type
	Flags   int    // interface flags
	Index   int    // interface index
	Addrs   []Addr // addresses

	raw []byte // raw message
}

// Sys implements the Sys method of Message interface.
func (m *InterfaceAddrMessage) Sys() []Sys { return nil }

// An InterfaceMulticastAddrMessage represents an interface multicast
// address message.
type InterfaceMulticastAddrMessage struct {
	Version int    // message version
	Type    int    // messsage type
	Flags   int    // interface flags
	Index   int    // interface index
	Addrs   []Addr // addresses

	raw []byte // raw message
}

// Sys implements the Sys method of Message interface.
func (m *InterfaceMulticastAddrMessage) Sys() []Sys { return nil }

// An InterfaceAnnounceMessage represents an interface announcement
// message.
type InterfaceAnnounceMessage struct {
	Version int    // message version
	Type    int    // message type
	Index   int    // interface index
	Name    string // interface name
	What    int    // what type of announcement

	raw []byte // raw message
}

// Sys implements the Sys method of Message interface.
func (m *InterfaceAnnounceMessage) Sys() []Sys { return nil }


text:
// 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.

package route

func (typ RIBType) parseable() bool { return true }

// RouteMetrics represents route metrics.
type RouteMetrics struct {
	PathMTU int // path maximum transmission unit
}

// SysType implements the SysType method of Sys interface.
func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }

// Sys implements the Sys method of Message interface.
func (m *RouteMessage) Sys() []Sys {
	return []Sys{
		&RouteMetrics{
			PathMTU: int(nativeEndian.Uint64(m.raw[m.extOff+8 : m.extOff+16])),
		},
	}
}

// RouteMetrics represents route metrics.
type InterfaceMetrics struct {
	Type int // interface type
	MTU  int // maximum transmission unit
}

// SysType implements the SysType method of Sys interface.
func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }

// Sys implements the Sys method of Message interface.
func (m *InterfaceMessage) Sys() []Sys {
	return []Sys{
		&InterfaceMetrics{
			Type: int(m.raw[m.extOff]),
			MTU:  int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
		},
	}
}

func probeRoutingStack() (int, map[int]*wireFormat) {
	rtm := &wireFormat{extOff: 40, bodyOff: sizeofRtMsghdrNetBSD7}
	rtm.parse = rtm.parseRouteMessage
	ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrNetBSD7}
	ifm.parse = ifm.parseInterfaceMessage
	ifam := &wireFormat{extOff: sizeofIfaMsghdrNetBSD7, bodyOff: sizeofIfaMsghdrNetBSD7}
	ifam.parse = ifam.parseInterfaceAddrMessage
	ifanm := &wireFormat{extOff: sizeofIfAnnouncemsghdrNetBSD7, bodyOff: sizeofIfAnnouncemsghdrNetBSD7}
	ifanm.parse = ifanm.parseInterfaceAnnounceMessage
	// NetBSD 6 and above kernels require 64-bit aligned access to
	// routing facilities.
	return 8, map[int]*wireFormat{
		sysRTM_ADD:        rtm,
		sysRTM_DELETE:     rtm,
		sysRTM_CHANGE:     rtm,
		sysRTM_GET:        rtm,
		sysRTM_LOSING:     rtm,
		sysRTM_REDIRECT:   rtm,
		sysRTM_MISS:       rtm,
		sysRTM_LOCK:       rtm,
		sysRTM_RESOLVE:    rtm,
		sysRTM_NEWADDR:    ifam,
		sysRTM_DELADDR:    ifam,
		sysRTM_IFANNOUNCE: ifanm,
		sysRTM_IFINFO:     ifm,
	}
}


text:
// 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.

package route

import "unsafe"

func (typ RIBType) parseable() bool {
	switch typ {
	case sysNET_RT_STATS, sysNET_RT_TABLE:
		return false
	default:
		return true
	}
}

// RouteMetrics represents route metrics.
type RouteMetrics struct {
	PathMTU int // path maximum transmission unit
}

// SysType implements the SysType method of Sys interface.
func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }

// Sys implements the Sys method of Message interface.
func (m *RouteMessage) Sys() []Sys {
	return []Sys{
		&RouteMetrics{
			PathMTU: int(nativeEndian.Uint32(m.raw[60:64])),
		},
	}
}

// InterfaceMetrics represents interface metrics.
type InterfaceMetrics struct {
	Type int // interface type
	MTU  int // maximum transmission unit
}

// SysType implements the SysType method of Sys interface.
func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }

// Sys implements the Sys method of Message interface.
func (m *InterfaceMessage) Sys() []Sys {
	return []Sys{
		&InterfaceMetrics{
			Type: int(m.raw[24]),
			MTU:  int(nativeEndian.Uint32(m.raw[28:32])),
		},
	}
}

func probeRoutingStack() (int, map[int]*wireFormat) {
	var p uintptr
	rtm := &wireFormat{extOff: -1, bodyOff: -1}
	rtm.parse = rtm.parseRouteMessage
	ifm := &wireFormat{extOff: -1, bodyOff: -1}
	ifm.parse = ifm.parseInterfaceMessage
	ifam := &wireFormat{extOff: -1, bodyOff: -1}
	ifam.parse = ifam.parseInterfaceAddrMessage
	ifanm := &wireFormat{extOff: -1, bodyOff: -1}
	ifanm.parse = ifanm.parseInterfaceAnnounceMessage
	return int(unsafe.Sizeof(p)), map[int]*wireFormat{
		sysRTM_ADD:        rtm,
		sysRTM_DELETE:     rtm,
		sysRTM_CHANGE:     rtm,
		sysRTM_GET:        rtm,
		sysRTM_LOSING:     rtm,
		sysRTM_REDIRECT:   rtm,
		sysRTM_MISS:       rtm,
		sysRTM_LOCK:       rtm,
		sysRTM_RESOLVE:    rtm,
		sysRTM_NEWADDR:    ifam,
		sysRTM_DELADDR:    ifam,
		sysRTM_IFINFO:     ifm,
		sysRTM_IFANNOUNCE: ifanm,
		sysRTM_DESYNC:     rtm,
	}
}


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_freebsd.go

package route

const (
	sysAF_UNSPEC = 0x0
	sysAF_INET   = 0x2
	sysAF_ROUTE  = 0x11
	sysAF_LINK   = 0x12
	sysAF_INET6  = 0x1c

	sysSOCK_RAW = 0x3

	sysNET_RT_DUMP     = 0x1
	sysNET_RT_FLAGS    = 0x2
	sysNET_RT_IFLIST   = 0x3
	sysNET_RT_IFMALIST = 0x4
	sysNET_RT_IFLISTL  = 0x5
)

const (
	sysCTL_MAXNAME = 0x18

	sysCTL_UNSPEC   = 0x0
	sysCTL_KERN     = 0x1
	sysCTL_VM       = 0x2
	sysCTL_VFS      = 0x3
	sysCTL_NET      = 0x4
	sysCTL_DEBUG    = 0x5
	sysCTL_HW       = 0x6
	sysCTL_MACHDEP  = 0x7
	sysCTL_USER     = 0x8
	sysCTL_P1003_1B = 0x9
)

const (
	sysRTM_VERSION = 0x5

	sysRTM_ADD        = 0x1
	sysRTM_DELETE     = 0x2
	sysRTM_CHANGE     = 0x3
	sysRTM_GET        = 0x4
	sysRTM_LOSING     = 0x5
	sysRTM_REDIRECT   = 0x6
	sysRTM_MISS       = 0x7
	sysRTM_LOCK       = 0x8
	sysRTM_RESOLVE    = 0xb
	sysRTM_NEWADDR    = 0xc
	sysRTM_DELADDR    = 0xd
	sysRTM_IFINFO     = 0xe
	sysRTM_NEWMADDR   = 0xf
	sysRTM_DELMADDR   = 0x10
	sysRTM_IFANNOUNCE = 0x11
	sysRTM_IEEE80211  = 0x12

	sysRTA_DST     = 0x1
	sysRTA_GATEWAY = 0x2
	sysRTA_NETMASK = 0x4
	sysRTA_GENMASK = 0x8
	sysRTA_IFP     = 0x10
	sysRTA_IFA     = 0x20
	sysRTA_AUTHOR  = 0x40
	sysRTA_BRD     = 0x80

	sysRTAX_DST     = 0x0
	sysRTAX_GATEWAY = 0x1
	sysRTAX_NETMASK = 0x2
	sysRTAX_GENMASK = 0x3
	sysRTAX_IFP     = 0x4
	sysRTAX_IFA     = 0x5
	sysRTAX_AUTHOR  = 0x6
	sysRTAX_BRD     = 0x7
	sysRTAX_MAX     = 0x8
)

const (
	sizeofIfMsghdrlFreeBSD10        = 0x68
	sizeofIfaMsghdrFreeBSD10        = 0x14
	sizeofIfaMsghdrlFreeBSD10       = 0x6c
	sizeofIfmaMsghdrFreeBSD10       = 0x10
	sizeofIfAnnouncemsghdrFreeBSD10 = 0x18

	sizeofRtMsghdrFreeBSD10  = 0x5c
	sizeofRtMetricsFreeBSD10 = 0x38

	sizeofIfMsghdrFreeBSD7  = 0x60
	sizeofIfMsghdrFreeBSD8  = 0x60
	sizeofIfMsghdrFreeBSD9  = 0x60
	sizeofIfMsghdrFreeBSD10 = 0x64
	sizeofIfMsghdrFreeBSD11 = 0xa8

	sizeofIfDataFreeBSD7  = 0x50
	sizeofIfDataFreeBSD8  = 0x50
	sizeofIfDataFreeBSD9  = 0x50
	sizeofIfDataFreeBSD10 = 0x54
	sizeofIfDataFreeBSD11 = 0x98

	// MODIFIED BY HAND FOR 386 EMULATION ON AMD64
	// 386 EMULATION USES THE UNDERLYING RAW DATA LAYOUT

	sizeofIfMsghdrlFreeBSD10Emu        = 0xb0
	sizeofIfaMsghdrFreeBSD10Emu        = 0x14
	sizeofIfaMsghdrlFreeBSD10Emu       = 0xb0
	sizeofIfmaMsghdrFreeBSD10Emu       = 0x10
	sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18

	sizeofRtMsghdrFreeBSD10Emu  = 0x98
	sizeofRtMetricsFreeBSD10Emu = 0x70

	sizeofIfMsghdrFreeBSD7Emu  = 0xa8
	sizeofIfMsghdrFreeBSD8Emu  = 0xa8
	sizeofIfMsghdrFreeBSD9Emu  = 0xa8
	sizeofIfMsghdrFreeBSD10Emu = 0xa8
	sizeofIfMsghdrFreeBSD11Emu = 0xa8

	sizeofIfDataFreeBSD7Emu  = 0x98
	sizeofIfDataFreeBSD8Emu  = 0x98
	sizeofIfDataFreeBSD9Emu  = 0x98
	sizeofIfDataFreeBSD10Emu = 0x98
	sizeofIfDataFreeBSD11Emu = 0x98

	sizeofSockaddrStorage = 0x80
	sizeofSockaddrInet    = 0x10
	sizeofSockaddrInet6   = 0x1c
)


text:
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs defs_darwin.go

package route

const (
	sysAF_UNSPEC = 0x0
	sysAF_INET   = 0x2
	sysAF_ROUTE  = 0x11
	sysAF_LINK   = 0x12
	sysAF_INET6  = 0x1e

	sysSOCK_RAW = 0x3

	sysNET_RT_DUMP    = 0x1
	sysNET_RT_FLAGS   = 0x2
	sysNET_RT_IFLIST  = 0x3
	sysNET_RT_STAT    = 0x4
	sysNET_RT_TRASH   = 0x5
	sysNET_RT_IFLIST2 = 0x6
	sysNET_RT_DUMP2   = 0x7
	sysNET_RT_MAXID   = 0xa
)

const (
	sysCTL_MAXNAME = 0xc

	sysCTL_UNSPEC  = 0x0
	sysCTL_KERN    = 0x1
	sysCTL_VM      = 0x2
	sysCTL_VFS     = 0x3
	sysCTL_NET     = 0x4
	sysCTL_DEBUG   = 0x5
	sysCTL_HW      = 0x6
	sysCTL_MACHDEP = 0x7
	sysCTL_USER    = 0x8
	sysCTL_MAXID   = 0x9
)

const (
	sysRTM_VERSION = 0x5

	sysRTM_ADD       = 0x1
	sysRTM_DELETE    = 0x2
	sysRTM_CHANGE    = 0x3
	sysRTM_GET       = 0x4
	sysRTM_LOSING    = 0x5
	sysRTM_REDIRECT  = 0x6
	sysRTM_MISS      = 0x7
	sysRTM_LOCK      = 0x8
	sysRTM_OLDADD    = 0x9
	sysRTM_OLDDEL    = 0xa
	sysRTM_RESOLVE   = 0xb
	sysRTM_NEWADDR   = 0xc
	sysRTM_DELADDR   = 0xd
	sysRTM_IFINFO    = 0xe
	sysRTM_NEWMADDR  = 0xf
	sysRTM_DELMADDR  = 0x10
	sysRTM_IFINFO2   = 0x12
	sysRTM_NEWMADDR2 = 0x13
	sysRTM_GET2      = 0x14

	sysRTA_DST     = 0x1
	sysRTA_GATEWAY = 0x2
	sysRTA_NETMASK = 0x4
	sysRTA_GENMASK = 0x8
	sysRTA_IFP     = 0x10
	sysRTA_IFA     = 0x20
	sysRTA_AUTHOR  = 0x40
	sysRTA_BRD     = 0x80

	sysRTAX_DST     = 0x0
	sysRTAX_GATEWAY = 0x1
	sysRTAX_NETMASK = 0x2
	sysRTAX_GENMASK = 0x3
	sysRTAX_IFP     = 0x4
	sysRTAX_IFA     = 0x5
	sysRTAX_AUTHOR  = 0x6
	sysRTAX_BRD     = 0x7
	sysRTAX_MAX     = 0x8
)

const (
	sizeofIfMsghdrDarwin15    = 0x70
	sizeofIfaMsghdrDarwin15   = 0x14
	sizeofIfmaMsghdrDarwin15  = 0x10
	sizeofIfMsghdr2Darwin15   = 0xa0
	sizeofIfmaMsghdr2Darwin15 = 0x14
	sizeofIfDataDarwin15      = 0x60
	sizeofIfData64Darwin15    = 0x80

	sizeofRtMsghdrDarwin15  = 0x5c
	sizeofRtMsghdr2Darwin15 = 0x5c
	sizeofRtMetricsDarwin15 = 0x38

	sizeofSockaddrStorage = 0x80
	sizeofSockaddrInet    = 0x10
	sizeofSockaddrInet6   = 0x1c
)


text:
// 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 provides basic functions for the manipulation of
// packet routing facilities on BSD variants.
//
// The package supports any version of Darwin, any version of
// DragonFly BSD, FreeBSD 7 through 11, NetBSD 6 and above, and
// OpenBSD 5.6 and above.
package route

import (
	"errors"
	"os"
	"syscall"
)

var (
	errUnsupportedMessage = errors.New("unsupported message")
	errMessageMismatch    = errors.New("message mismatch")
	errMessageTooShort    = errors.New("message too short")
	errInvalidMessage     = errors.New("invalid message")
	errInvalidAddr        = errors.New("invalid address")
	errShortBuffer        = errors.New("short buffer")
)

// A RouteMessage represents a message conveying an address prefix, a
// nexthop address and an output interface.
//
// Unlike other messages, this message can be used to query adjacency
// information for the given address prefix, to add a new route, and
// to delete or modify the existing route from the routing information
// base inside the kernel by writing and reading route messages on a
// routing socket.
//
// For the manipulation of routing information, the route message must
// contain appropriate fields that include:
//
//	Version       = <must be specified>
//	Type          = <must be specified>
//	Flags         = <must be specified>
//	Index         = <must be specified if necessary>
//	ID            = <must be specified>
//	Seq           = <must be specified>
//	Addrs         = <must be specified>
//
// The Type field specifies a type of manipulation, the Flags field
// specifies a class of target information and the Addrs field
// specifies target information like the following:
//
//	route.RouteMessage{
//		Version: RTM_VERSION,
//		Type: RTM_GET,
//		Flags: RTF_UP | RTF_HOST,
//		ID: uintptr(os.Getpid()),
//		Seq: 1,
//		Addrs: []route.Addrs{
//			RTAX_DST: &route.Inet4Addr{ ... },
//			RTAX_IFP: &route.LinkAddr{ ... },
//			RTAX_BRD: &route.Inet4Addr{ ... },
//		},
//	}
//
// The values for the above fields depend on the implementation of
// each operating system.
//
// The Err field on a response message contains an error value on the
// requested operation. If non-nil, the requested operation is failed.
type RouteMessage struct {
	Version int     // message version
	Type    int     // message type
	Flags   int     // route flags
	Index   int     // interface index when atatched
	ID      uintptr // sender's identifier; usually process ID
	Seq     int     // sequence number
	Err     error   // error on requested operation
	Addrs   []Addr  // addresses

	extOff int    // offset of header extension
	raw    []byte // raw message
}

// Marshal returns the binary encoding of m.
func (m *RouteMessage) Marshal() ([]byte, error) {
	return m.marshal()
}

// A RIBType reprensents a type of routing information base.
type RIBType int

const (
	RIBTypeRoute     RIBType = syscall.NET_RT_DUMP
	RIBTypeInterface RIBType = syscall.NET_RT_IFLIST
)

// FetchRIB fetches a routing information base from the operating
// system.
//
// The provided af must be an address family.
//
// The provided arg must be a RIBType-specific argument.
// When RIBType is related to routes, arg might be a set of route
// flags. When RIBType is related to network interfaces, arg might be
// an interface index or a set of interface flags. In most cases, zero
// means a wildcard.
func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) {
	mib := [6]int32{sysCTL_NET, sysAF_ROUTE, 0, int32(af), int32(typ), int32(arg)}
	n := uintptr(0)
	if err := sysctl(mib[:], nil, &n, nil, 0); err != nil {
		return nil, os.NewSyscallError("sysctl", err)
	}
	if n == 0 {
		return nil, nil
	}
	b := make([]byte, n)
	if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil {
		return nil, os.NewSyscallError("sysctl", err)
	}
	return b[:n], nil
}


text:
// 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

package route

func (w *wireFormat) parseInterfaceMulticastAddrMessage(_ RIBType, b []byte) (Message, error) {
	if len(b) < w.bodyOff {
		return nil, errMessageTooShort
	}
	l := int(nativeEndian.Uint16(b[:2]))
	if len(b) < l {
		return nil, errInvalidMessage
	}
	m := &InterfaceMulticastAddrMessage{
		Version: int(b[2]),
		Type:    int(b[3]),
		Flags:   int(nativeEndian.Uint32(b[8:12])),
		Index:   int(nativeEndian.Uint16(b[12:14])),
		raw:     b[:l],
	}
	var err error
	m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[4:8])), parseKernelInetAddr, b[w.bodyOff:])
	if err != nil {
		return nil, err
	}
	return m, nil
}


text:
// 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

// A Message represents a routing message.
type Message interface {
	// Sys returns operating system-specific information.
	Sys() []Sys
}

// A Sys reprensents operating system-specific information.
type Sys interface {
	// SysType returns a type of operating system-specific
	// information.
	SysType() SysType
}

// A SysType represents a type of operating system-specific
// information.
type SysType int

const (
	SysMetrics SysType = iota
	SysStats
)

// ParseRIB parses b as a routing information base and returns a list
// of routing messages.
func ParseRIB(typ RIBType, b []byte) ([]Message, error) {
	if !typ.parseable() {
		return nil, errUnsupportedMessage
	}
	var msgs []Message
	nmsgs, nskips := 0, 0
	for len(b) > 4 {
		nmsgs++
		l := int(nativeEndian.Uint16(b[:2]))
		if l == 0 {
			return nil, errInvalidMessage
		}
		if len(b) < l {
			return nil, errMessageTooShort
		}
		if b[2] != sysRTM_VERSION {
			b = b[l:]
			continue
		}
		if w, ok := wireFormats[int(b[3])]; !ok {
			nskips++
		} else {
			m, err := w.parse(typ, b)
			if err != nil {
				return nil, err
			}
			if m == nil {
				nskips++
			} else {
				msgs = append(msgs, m)
			}
		}
		b = b[l:]
	}
	// We failed to parse any of the messages - version mismatch?
	if nmsgs != len(msgs)+nskips {
		return nil, errMessageMismatch
	}
	return msgs, nil
}


text:
// 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.

package route

import "syscall"

func (m *RouteMessage) marshal() ([]byte, error) {
	l := sizeofRtMsghdr + addrsSpace(m.Addrs)
	b := make([]byte, l)
	nativeEndian.PutUint16(b[:2], uint16(l))
	if m.Version == 0 {
		b[2] = sysRTM_VERSION
	} else {
		b[2] = byte(m.Version)
	}
	b[3] = byte(m.Type)
	nativeEndian.PutUint16(b[4:6], uint16(sizeofRtMsghdr))
	nativeEndian.PutUint32(b[16:20], uint32(m.Flags))
	nativeEndian.PutUint16(b[6:8], uint16(m.Index))
	nativeEndian.PutUint32(b[24:28], uint32(m.ID))
	nativeEndian.PutUint32(b[28:32], uint32(m.Seq))
	attrs, err := marshalAddrs(b[sizeofRtMsghdr:], m.Addrs)
	if err != nil {
		return nil, err
	}
	if attrs > 0 {
		nativeEndian.PutUint32(b[12:16], uint32(attrs))
	}
	return b, nil
}

func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) {
	if len(b) < sizeofRtMsghdr {
		return nil, errMessageTooShort
	}
	l := int(nativeEndian.Uint16(b[:2]))
	if len(b) < l {
		return nil, errInvalidMessage
	}
	m := &RouteMessage{
		Version: int(b[2]),
		Type:    int(b[3]),
		Flags:   int(nativeEndian.Uint32(b[16:20])),
		Index:   int(nativeEndian.Uint16(b[6:8])),
		ID:      uintptr(nativeEndian.Uint32(b[24:28])),
		Seq:     int(nativeEndian.Uint32(b[28:32])),
		raw:     b[:l],
	}
	ll := int(nativeEndian.Uint16(b[4:6]))
	if len(b) < ll {
		return nil, errInvalidMessage
	}
	errno := syscall.Errno(nativeEndian.Uint32(b[32:36]))
	if errno != 0 {
		m.Err = errno
	}
	as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[ll:])
	if err != nil {
		return nil, err
	}
	m.Addrs = as
	return m, nil
}


text:
// 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.

package route

import (
	"reflect"
	"testing"
)

type parseAddrsOnDarwinTest struct {
	attrs uint
	fn    func(int, []byte) (int, Addr, error)
	b     []byte
	as    []Addr
}

var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{
	{
		sysRTA_DST | sysRTA_GATEWAY | sysRTA_NETMASK,
		parseKernelInetAddr,
		[]byte{
			0x10, 0x2, 0x0, 0x0, 0xc0, 0xa8, 0x56, 0x0,
			0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,

			0x14, 0x12, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
			0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
			0x0, 0x0, 0x0, 0x0,

			0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
		},
		[]Addr{
			&Inet4Addr{IP: [4]byte{192, 168, 86, 0}},
			&LinkAddr{Index: 4},
			&Inet4Addr{IP: [4]byte{255, 255, 255, 255}},
			nil,
			nil,
			nil,
			nil,
			nil,
		},
	},
}

func TestParseAddrsOnDarwin(t *testing.T) {
	tests := parseAddrsOnDarwinLittleEndianTests
	if nativeEndian != littleEndian {
		t.Skip("no test for non-little endian machine yet")
	}

	for i, tt := range tests {
		as, err := parseAddrs(tt.attrs, tt.fn, tt.b)
		if err != nil {
			t.Error(i, err)
			continue
		}
		if !reflect.DeepEqual(as, tt.as) {
			t.Errorf("#%d: got %+v; want %+v", i, as, tt.as)
			continue
		}
	}
}