text:
// Copyright 2015 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 icmp

import (
	"fmt"
	"net"
	"reflect"
	"testing"

	"golang.org/x/net/internal/iana"
	"golang.org/x/net/ipv4"
	"golang.org/x/net/ipv6"
)

func TestMarshalAndParseExtension(t *testing.T) {
	fn := func(t *testing.T, proto int, typ Type, hdr, obj []byte, te Extension) error {
		b, err := te.Marshal(proto)
		if err != nil {
			return err
		}
		if !reflect.DeepEqual(b, obj) {
			return fmt.Errorf("got %#v; want %#v", b, obj)
		}
		switch typ {
		case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
			exts, l, err := parseExtensions(typ, append(hdr, obj...), 0)
			if err != nil {
				return err
			}
			if l != 0 {
				return fmt.Errorf("got %d; want 0", l)
			}
			if !reflect.DeepEqual(exts, []Extension{te}) {
				return fmt.Errorf("got %#v; want %#v", exts[0], te)
			}
		default:
			for i, wire := range []struct {
				data     []byte // original datagram
				inlattr  int    // length of padded original datagram, a hint
				outlattr int    // length of padded original datagram, a want
				err      error
			}{
				{nil, 0, -1, errNoExtension},
				{make([]byte, 127), 128, -1, errNoExtension},

				{make([]byte, 128), 127, -1, errNoExtension},
				{make([]byte, 128), 128, -1, errNoExtension},
				{make([]byte, 128), 129, -1, errNoExtension},

				{append(make([]byte, 128), append(hdr, obj...)...), 127, 128, nil},
				{append(make([]byte, 128), append(hdr, obj...)...), 128, 128, nil},
				{append(make([]byte, 128), append(hdr, obj...)...), 129, 128, nil},

				{append(make([]byte, 512), append(hdr, obj...)...), 511, -1, errNoExtension},
				{append(make([]byte, 512), append(hdr, obj...)...), 512, 512, nil},
				{append(make([]byte, 512), append(hdr, obj...)...), 513, -1, errNoExtension},
			} {
				exts, l, err := parseExtensions(typ, wire.data, wire.inlattr)
				if err != wire.err {
					return fmt.Errorf("#%d: got %v; want %v", i, err, wire.err)
				}
				if wire.err != nil {
					continue
				}
				if l != wire.outlattr {
					return fmt.Errorf("#%d: got %d; want %d", i, l, wire.outlattr)
				}
				if !reflect.DeepEqual(exts, []Extension{te}) {
					return fmt.Errorf("#%d: got %#v; want %#v", i, exts[0], te)
				}
			}
		}
		return nil
	}

	t.Run("MPLSLabelStack", func(t *testing.T) {
		for _, et := range []struct {
			proto int
			typ   Type
			hdr   []byte
			obj   []byte
			ext   Extension
		}{
			// MPLS label stack with no label
			{
				proto: iana.ProtocolICMP,
				typ:   ipv4.ICMPTypeDestinationUnreachable,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x04, 0x01, 0x01,
				},
				ext: &MPLSLabelStack{
					Class: classMPLSLabelStack,
					Type:  typeIncomingMPLSLabelStack,
				},
			},
			// MPLS label stack with a single label
			{
				proto: iana.ProtocolIPv6ICMP,
				typ:   ipv6.ICMPTypeDestinationUnreachable,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x08, 0x01, 0x01,
					0x03, 0xe8, 0xe9, 0xff,
				},
				ext: &MPLSLabelStack{
					Class: classMPLSLabelStack,
					Type:  typeIncomingMPLSLabelStack,
					Labels: []MPLSLabel{
						{
							Label: 16014,
							TC:    0x4,
							S:     true,
							TTL:   255,
						},
					},
				},
			},
			// MPLS label stack with multiple labels
			{
				proto: iana.ProtocolICMP,
				typ:   ipv4.ICMPTypeDestinationUnreachable,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x0c, 0x01, 0x01,
					0x03, 0xe8, 0xde, 0xfe,
					0x03, 0xe8, 0xe1, 0xff,
				},
				ext: &MPLSLabelStack{
					Class: classMPLSLabelStack,
					Type:  typeIncomingMPLSLabelStack,
					Labels: []MPLSLabel{
						{
							Label: 16013,
							TC:    0x7,
							S:     false,
							TTL:   254,
						},
						{
							Label: 16014,
							TC:    0,
							S:     true,
							TTL:   255,
						},
					},
				},
			},
		} {
			if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
				t.Error(err)
			}
		}
	})
	t.Run("InterfaceInfo", func(t *testing.T) {
		for _, et := range []struct {
			proto int
			typ   Type
			hdr   []byte
			obj   []byte
			ext   Extension
		}{
			// Interface information with no attribute
			{
				proto: iana.ProtocolICMP,
				typ:   ipv4.ICMPTypeDestinationUnreachable,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x04, 0x02, 0x00,
				},
				ext: &InterfaceInfo{
					Class: classInterfaceInfo,
				},
			},
			// Interface information with ifIndex and name
			{
				proto: iana.ProtocolICMP,
				typ:   ipv4.ICMPTypeDestinationUnreachable,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x10, 0x02, 0x0a,
					0x00, 0x00, 0x00, 0x10,
					0x08, byte('e'), byte('n'), byte('1'),
					byte('0'), byte('1'), 0x00, 0x00,
				},
				ext: &InterfaceInfo{
					Class: classInterfaceInfo,
					Type:  0x0a,
					Interface: &net.Interface{
						Index: 16,
						Name:  "en101",
					},
				},
			},
			// Interface information with ifIndex, IPAddr, name and MTU
			{
				proto: iana.ProtocolIPv6ICMP,
				typ:   ipv6.ICMPTypeDestinationUnreachable,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x28, 0x02, 0x0f,
					0x00, 0x00, 0x00, 0x0f,
					0x00, 0x02, 0x00, 0x00,
					0xfe, 0x80, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x01,
					0x08, byte('e'), byte('n'), byte('1'),
					byte('0'), byte('1'), 0x00, 0x00,
					0x00, 0x00, 0x20, 0x00,
				},
				ext: &InterfaceInfo{
					Class: classInterfaceInfo,
					Type:  0x0f,
					Interface: &net.Interface{
						Index: 15,
						Name:  "en101",
						MTU:   8192,
					},
					Addr: &net.IPAddr{
						IP:   net.ParseIP("fe80::1"),
						Zone: "en101",
					},
				},
			},
		} {
			if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
				t.Error(err)
			}
		}
	})
	t.Run("InterfaceIdent", func(t *testing.T) {
		for _, et := range []struct {
			proto int
			typ   Type
			hdr   []byte
			obj   []byte
			ext   Extension
		}{
			// Interface identification by name
			{
				proto: iana.ProtocolICMP,
				typ:   ipv4.ICMPTypeExtendedEchoRequest,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x0c, 0x03, 0x01,
					byte('e'), byte('n'), byte('1'), byte('0'),
					byte('1'), 0x00, 0x00, 0x00,
				},
				ext: &InterfaceIdent{
					Class: classInterfaceIdent,
					Type:  typeInterfaceByName,
					Name:  "en101",
				},
			},
			// Interface identification by index
			{
				proto: iana.ProtocolIPv6ICMP,
				typ:   ipv6.ICMPTypeExtendedEchoRequest,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x0c, 0x03, 0x02,
					0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x03, 0x8f,
				},
				ext: &InterfaceIdent{
					Class: classInterfaceIdent,
					Type:  typeInterfaceByIndex,
					Index: 911,
				},
			},
			// Interface identification by address
			{
				proto: iana.ProtocolICMP,
				typ:   ipv4.ICMPTypeExtendedEchoRequest,
				hdr: []byte{
					0x20, 0x00, 0x00, 0x00,
				},
				obj: []byte{
					0x00, 0x10, 0x03, 0x03,
					byte(iana.AddrFamily48bitMAC >> 8), byte(iana.AddrFamily48bitMAC & 0x0f), 0x06, 0x00,
					0x01, 0x23, 0x45, 0x67,
					0x89, 0xab, 0x00, 0x00,
				},
				ext: &InterfaceIdent{
					Class: classInterfaceIdent,
					Type:  typeInterfaceByAddress,
					AFI:   iana.AddrFamily48bitMAC,
					Addr:  []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab},
				},
			},
		} {
			if err := fn(t, et.proto, et.typ, et.hdr, et.obj, et.ext); err != nil {
				t.Error(err)
			}
		}
	})
}

func TestParseInterfaceName(t *testing.T) {
	ifi := InterfaceInfo{Interface: &net.Interface{}}
	for i, tt := range []struct {
		b []byte
		error
	}{
		{[]byte{0, 'e', 'n', '0'}, errInvalidExtension},
		{[]byte{4, 'e', 'n', '0'}, nil},
		{[]byte{7, 'e', 'n', '0', 0xff, 0xff, 0xff, 0xff}, errInvalidExtension},
		{[]byte{8, 'e', 'n', '0', 0xff, 0xff, 0xff}, errMessageTooShort},
	} {
		if _, err := ifi.parseName(tt.b); err != tt.error {
			t.Errorf("#%d: got %v; want %v", i, err, tt.error)
		}
	}
}


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 icmp

import (
	"net"
	"strconv"
	"syscall"
)

func sockaddr(family int, address string) (syscall.Sockaddr, error) {
	switch family {
	case syscall.AF_INET:
		a, err := net.ResolveIPAddr("ip4", address)
		if err != nil {
			return nil, err
		}
		if len(a.IP) == 0 {
			a.IP = net.IPv4zero
		}
		if a.IP = a.IP.To4(); a.IP == nil {
			return nil, net.InvalidAddrError("non-ipv4 address")
		}
		sa := &syscall.SockaddrInet4{}
		copy(sa.Addr[:], a.IP)
		return sa, nil
	case syscall.AF_INET6:
		a, err := net.ResolveIPAddr("ip6", address)
		if err != nil {
			return nil, err
		}
		if len(a.IP) == 0 {
			a.IP = net.IPv6unspecified
		}
		if a.IP.Equal(net.IPv4zero) {
			a.IP = net.IPv6unspecified
		}
		if a.IP = a.IP.To16(); a.IP == nil || a.IP.To4() != nil {
			return nil, net.InvalidAddrError("non-ipv6 address")
		}
		sa := &syscall.SockaddrInet6{ZoneId: zoneToUint32(a.Zone)}
		copy(sa.Addr[:], a.IP)
		return sa, nil
	default:
		return nil, net.InvalidAddrError("unexpected family")
	}
}

func zoneToUint32(zone string) uint32 {
	if zone == "" {
		return 0
	}
	if ifi, err := net.InterfaceByName(zone); err == nil {
		return uint32(ifi.Index)
	}
	n, err := strconv.Atoi(zone)
	if err != nil {
		return 0
	}
	return uint32(n)
}

func last(s string, b byte) int {
	i := len(s)
	for i--; i >= 0; i-- {
		if s[i] == b {
			break
		}
	}
	return i
}

repo_name: dan-v/dosxvpn

repo_language: Go

mime_type: text/x-shellscript


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 icmp provides basic functions for the manipulation of
// messages used in the Internet Control Message Protocols,
// ICMPv4 and ICMPv6.
//
// ICMPv4 and ICMPv6 are defined in RFC 792 and RFC 4443.
// Multi-part message support for ICMP is defined in RFC 4884.
// ICMP extensions for MPLS are defined in RFC 4950.
// ICMP extensions for interface and next-hop identification are
// defined in RFC 5837.
// PROBE: A utility for probing interfaces is defined in RFC 8335.
package icmp // import "golang.org/x/net/icmp"

import (
	"encoding/binary"
	"errors"
	"net"
	"syscall"

	"golang.org/x/net/internal/iana"
	"golang.org/x/net/ipv4"
	"golang.org/x/net/ipv6"
)

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

var (
	errMessageTooShort  = errors.New("message too short")
	errHeaderTooShort   = errors.New("header too short")
	errBufferTooShort   = errors.New("buffer too short")
	errOpNoSupport      = errors.New("operation not supported")
	errNoExtension      = errors.New("no extension")
	errInvalidExtension = errors.New("invalid extension")
)

func checksum(b []byte) uint16 {
	csumcv := len(b) - 1 // checksum coverage
	s := uint32(0)
	for i := 0; i < csumcv; i += 2 {
		s += uint32(b[i+1])<<8 | uint32(b[i])
	}
	if csumcv&1 == 0 {
		s += uint32(b[csumcv])
	}
	s = s>>16 + s&0xffff
	s = s + s>>16
	return ^uint16(s)
}

// A Type represents an ICMP message type.
type Type interface {
	Protocol() int
}

// A Message represents an ICMP message.
type Message struct {
	Type     Type        // type, either ipv4.ICMPType or ipv6.ICMPType
	Code     int         // code
	Checksum int         // checksum
	Body     MessageBody // body
}

// Marshal returns the binary encoding of the ICMP message m.
//
// For an ICMPv4 message, the returned message always contains the
// calculated checksum field.
//
// For an ICMPv6 message, the returned message contains the calculated
// checksum field when psh is not nil, otherwise the kernel will
// compute the checksum field during the message transmission.
// When psh is not nil, it must be the pseudo header for IPv6.
func (m *Message) Marshal(psh []byte) ([]byte, error) {
	var mtype int
	switch typ := m.Type.(type) {
	case ipv4.ICMPType:
		mtype = int(typ)
	case ipv6.ICMPType:
		mtype = int(typ)
	default:
		return nil, syscall.EINVAL
	}
	b := []byte{byte(mtype), byte(m.Code), 0, 0}
	if m.Type.Protocol() == iana.ProtocolIPv6ICMP && psh != nil {
		b = append(psh, b...)
	}
	if m.Body != nil && m.Body.Len(m.Type.Protocol()) != 0 {
		mb, err := m.Body.Marshal(m.Type.Protocol())
		if err != nil {
			return nil, err
		}
		b = append(b, mb...)
	}
	if m.Type.Protocol() == iana.ProtocolIPv6ICMP {
		if psh == nil { // cannot calculate checksum here
			return b, nil
		}
		off, l := 2*net.IPv6len, len(b)-len(psh)
		binary.BigEndian.PutUint32(b[off:off+4], uint32(l))
	}
	s := checksum(b)
	// Place checksum back in header; using ^= avoids the
	// assumption the checksum bytes are zero.
	b[len(psh)+2] ^= byte(s)
	b[len(psh)+3] ^= byte(s >> 8)
	return b[len(psh):], nil
}

var parseFns = map[Type]func(int, Type, []byte) (MessageBody, error){
	ipv4.ICMPTypeDestinationUnreachable: parseDstUnreach,
	ipv4.ICMPTypeTimeExceeded:           parseTimeExceeded,
	ipv4.ICMPTypeParameterProblem:       parseParamProb,

	ipv4.ICMPTypeEcho:                parseEcho,
	ipv4.ICMPTypeEchoReply:           parseEcho,
	ipv4.ICMPTypeExtendedEchoRequest: parseExtendedEchoRequest,
	ipv4.ICMPTypeExtendedEchoReply:   parseExtendedEchoReply,

	ipv6.ICMPTypeDestinationUnreachable: parseDstUnreach,
	ipv6.ICMPTypePacketTooBig:           parsePacketTooBig,
	ipv6.ICMPTypeTimeExceeded:           parseTimeExceeded,
	ipv6.ICMPTypeParameterProblem:       parseParamProb,

	ipv6.ICMPTypeEchoRequest:         parseEcho,
	ipv6.ICMPTypeEchoReply:           parseEcho,
	ipv6.ICMPTypeExtendedEchoRequest: parseExtendedEchoRequest,
	ipv6.ICMPTypeExtendedEchoReply:   parseExtendedEchoReply,
}

// ParseMessage parses b as an ICMP message.
// Proto must be either the ICMPv4 or ICMPv6 protocol number.
func ParseMessage(proto int, b []byte) (*Message, error) {
	if len(b) < 4 {
		return nil, errMessageTooShort
	}
	var err error
	m := &Message{Code: int(b[1]), Checksum: int(binary.BigEndian.Uint16(b[2:4]))}
	switch proto {
	case iana.ProtocolICMP:
		m.Type = ipv4.ICMPType(b[0])
	case iana.ProtocolIPv6ICMP:
		m.Type = ipv6.ICMPType(b[0])
	default:
		return nil, syscall.EINVAL
	}
	if fn, ok := parseFns[m.Type]; !ok {
		m.Body, err = parseDefaultMessageBody(proto, b[4:])
	} else {
		m.Body, err = fn(proto, m.Type, b[4:])
	}
	if err != nil {
		return nil, err
	}
	return m, 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.

package icmp_test

import (
	"log"
	"net"
	"os"
	"runtime"

	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv6"
)

func ExamplePacketConn_nonPrivilegedPing() {
	switch runtime.GOOS {
	case "darwin":
	case "linux":
		log.Println("you may need to adjust the net.ipv4.ping_group_range kernel state")
	default:
		log.Println("not supported on", runtime.GOOS)
		return
	}

	c, err := icmp.ListenPacket("udp6", "fe80::1%en0")
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()

	wm := icmp.Message{
		Type: ipv6.ICMPTypeEchoRequest, Code: 0,
		Body: &icmp.Echo{
			ID: os.Getpid() & 0xffff, Seq: 1,
			Data: []byte("HELLO-R-U-THERE"),
		},
	}
	wb, err := wm.Marshal(nil)
	if err != nil {
		log.Fatal(err)
	}
	if _, err := c.WriteTo(wb, &net.UDPAddr{IP: net.ParseIP("ff02::1"), Zone: "en0"}); err != nil {
		log.Fatal(err)
	}

	rb := make([]byte, 1500)
	n, peer, err := c.ReadFrom(rb)
	if err != nil {
		log.Fatal(err)
	}
	rm, err := icmp.ParseMessage(58, rb[:n])
	if err != nil {
		log.Fatal(err)
	}
	switch rm.Type {
	case ipv6.ICMPTypeEchoReply:
		log.Printf("got reflection from %v", peer)
	default:
		log.Printf("got %+v; want echo reply", rm)
	}
}


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 icmp

// A MessageBody represents an ICMP message body.
type MessageBody interface {
	// Len returns the length of ICMP message body.
	// Proto must be either the ICMPv4 or ICMPv6 protocol number.
	Len(proto int) int

	// Marshal returns the binary encoding of ICMP message body.
	// Proto must be either the ICMPv4 or ICMPv6 protocol number.
	Marshal(proto int) ([]byte, error)
}

// A DefaultMessageBody represents the default message body.
type DefaultMessageBody struct {
	Data []byte // data
}

// Len implements the Len method of MessageBody interface.
func (p *DefaultMessageBody) Len(proto int) int {
	if p == nil {
		return 0
	}
	return len(p.Data)
}

// Marshal implements the Marshal method of MessageBody interface.
func (p *DefaultMessageBody) Marshal(proto int) ([]byte, error) {
	return p.Data, nil
}

// parseDefaultMessageBody parses b as an ICMP message body.
func parseDefaultMessageBody(proto int, b []byte) (MessageBody, error) {
	p := &DefaultMessageBody{Data: make([]byte, len(b))}
	copy(p.Data, b)
	return p, 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.

package icmp_test

import (
	"net"
	"reflect"
	"testing"

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

func TestMarshalAndParseMessage(t *testing.T) {
	fn := func(t *testing.T, proto int, tms []icmp.Message) {
		var pshs [][]byte
		switch proto {
		case iana.ProtocolICMP:
			pshs = [][]byte{nil}
		case iana.ProtocolIPv6ICMP:
			pshs = [][]byte{
				icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1")),
				nil,
			}
		}
		for i, tm := range tms {
			for _, psh := range pshs {
				b, err := tm.Marshal(psh)
				if err != nil {
					t.Fatal(err)
				}
				m, err := icmp.ParseMessage(proto, b)
				if err != nil {
					t.Fatal(err)
				}
				if m.Type != tm.Type || m.Code != tm.Code {
					t.Errorf("#%d: got %#v; want %#v", i, m, &tm)
				}
				if !reflect.DeepEqual(m.Body, tm.Body) {
					t.Errorf("#%d: got %#v; want %#v", i, m.Body, tm.Body)
				}
			}
		}
	}

	t.Run("IPv4", func(t *testing.T) {
		fn(t, iana.ProtocolICMP,
			[]icmp.Message{
				{
					Type: ipv4.ICMPTypeDestinationUnreachable, Code: 15,
					Body: &icmp.DstUnreach{
						Data: []byte("ERROR-INVOKING-PACKET"),
					},
				},
				{
					Type: ipv4.ICMPTypeTimeExceeded, Code: 1,
					Body: &icmp.TimeExceeded{
						Data: []byte("ERROR-INVOKING-PACKET"),
					},
				},
				{
					Type: ipv4.ICMPTypeParameterProblem, Code: 2,
					Body: &icmp.ParamProb{
						Pointer: 8,
						Data:    []byte("ERROR-INVOKING-PACKET"),
					},
				},
				{
					Type: ipv4.ICMPTypeEcho, Code: 0,
					Body: &icmp.Echo{
						ID: 1, Seq: 2,
						Data: []byte("HELLO-R-U-THERE"),
					},
				},
				{
					Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
					Body: &icmp.ExtendedEchoRequest{
						ID: 1, Seq: 2,
					},
				},
				{
					Type: ipv4.ICMPTypeExtendedEchoReply, Code: 0,
					Body: &icmp.ExtendedEchoReply{
						State: 4 /* Delay */, Active: true, IPv4: true,
					},
				},
				{
					Type: ipv4.ICMPTypePhoturis,
					Body: &icmp.DefaultMessageBody{
						Data: []byte{0x80, 0x40, 0x20, 0x10},
					},
				},
			})
	})
	t.Run("IPv6", func(t *testing.T) {
		fn(t, iana.ProtocolIPv6ICMP,
			[]icmp.Message{
				{
					Type: ipv6.ICMPTypeDestinationUnreachable, Code: 6,
					Body: &icmp.DstUnreach{
						Data: []byte("ERROR-INVOKING-PACKET"),
					},
				},
				{
					Type: ipv6.ICMPTypePacketTooBig, Code: 0,
					Body: &icmp.PacketTooBig{
						MTU:  1<<16 - 1,
						Data: []byte("ERROR-INVOKING-PACKET"),
					},
				},
				{
					Type: ipv6.ICMPTypeTimeExceeded, Code: 1,
					Body: &icmp.TimeExceeded{
						Data: []byte("ERROR-INVOKING-PACKET"),
					},
				},
				{
					Type: ipv6.ICMPTypeParameterProblem, Code: 2,
					Body: &icmp.ParamProb{
						Pointer: 8,
						Data:    []byte("ERROR-INVOKING-PACKET"),
					},
				},
				{
					Type: ipv6.ICMPTypeEchoRequest, Code: 0,
					Body: &icmp.Echo{
						ID: 1, Seq: 2,
						Data: []byte("HELLO-R-U-THERE"),
					},
				},
				{
					Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
					Body: &icmp.ExtendedEchoRequest{
						ID: 1, Seq: 2,
					},
				},
				{
					Type: ipv6.ICMPTypeExtendedEchoReply, Code: 0,
					Body: &icmp.ExtendedEchoReply{
						State: 5 /* Probe */, Active: true, IPv6: true,
					},
				},
				{
					Type: ipv6.ICMPTypeDuplicateAddressConfirmation,
					Body: &icmp.DefaultMessageBody{
						Data: []byte{0x80, 0x40, 0x20, 0x10},
					},
				},
			})
	})
}


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 icmp

// A TimeExceeded represents an ICMP time exceeded message body.
type TimeExceeded struct {
	Data       []byte      // data, known as original datagram field
	Extensions []Extension // extensions
}

// Len implements the Len method of MessageBody interface.
func (p *TimeExceeded) Len(proto int) int {
	if p == nil {
		return 0
	}
	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
	return 4 + l
}

// Marshal implements the Marshal method of MessageBody interface.
func (p *TimeExceeded) Marshal(proto int) ([]byte, error) {
	return marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
}

// parseTimeExceeded parses b as an ICMP time exceeded message body.
func parseTimeExceeded(proto int, typ Type, b []byte) (MessageBody, error) {
	if len(b) < 4 {
		return nil, errMessageTooShort
	}
	p := &TimeExceeded{}
	var err error
	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
	if err != nil {
		return nil, err
	}
	return p, 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.

package icmp

import "encoding/binary"

// A PacketTooBig represents an ICMP packet too big message body.
type PacketTooBig struct {
	MTU  int    // maximum transmission unit of the nexthop link
	Data []byte // data, known as original datagram field
}

// Len implements the Len method of MessageBody interface.
func (p *PacketTooBig) Len(proto int) int {
	if p == nil {
		return 0
	}
	return 4 + len(p.Data)
}

// Marshal implements the Marshal method of MessageBody interface.
func (p *PacketTooBig) Marshal(proto int) ([]byte, error) {
	b := make([]byte, 4+len(p.Data))
	binary.BigEndian.PutUint32(b[:4], uint32(p.MTU))
	copy(b[4:], p.Data)
	return b, nil
}

// parsePacketTooBig parses b as an ICMP packet too big message body.
func parsePacketTooBig(proto int, _ Type, b []byte) (MessageBody, error) {
	bodyLen := len(b)
	if bodyLen < 4 {
		return nil, errMessageTooShort
	}
	p := &PacketTooBig{MTU: int(binary.BigEndian.Uint32(b[:4]))}
	if bodyLen > 4 {
		p.Data = make([]byte, bodyLen-4)
		copy(p.Data, b[4:])
	}
	return p, 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.

package icmp_test

import (
	"errors"
	"fmt"
	"net"
	"os"
	"runtime"
	"sync"
	"testing"
	"time"

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

type diagTest struct {
	network, address string
	protocol         int
	m                icmp.Message
}

func TestDiag(t *testing.T) {
	if testing.Short() {
		t.Skip("avoid external network")
	}

	t.Run("Ping/NonPrivileged", func(t *testing.T) {
		switch runtime.GOOS {
		case "darwin":
		case "linux":
			t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
		default:
			t.Logf("not supported on %s", runtime.GOOS)
			return
		}
		for i, dt := range []diagTest{
			{
				"udp4", "0.0.0.0", iana.ProtocolICMP,
				icmp.Message{
					Type: ipv4.ICMPTypeEcho, Code: 0,
					Body: &icmp.Echo{
						ID:   os.Getpid() & 0xffff,
						Data: []byte("HELLO-R-U-THERE"),
					},
				},
			},

			{
				"udp6", "::", iana.ProtocolIPv6ICMP,
				icmp.Message{
					Type: ipv6.ICMPTypeEchoRequest, Code: 0,
					Body: &icmp.Echo{
						ID:   os.Getpid() & 0xffff,
						Data: []byte("HELLO-R-U-THERE"),
					},
				},
			},
		} {
			if err := doDiag(dt, i); err != nil {
				t.Error(err)
			}
		}
	})
	t.Run("Ping/Privileged", func(t *testing.T) {
		if m, ok := nettest.SupportsRawIPSocket(); !ok {
			t.Skip(m)
		}
		for i, dt := range []diagTest{
			{
				"ip4:icmp", "0.0.0.0", iana.ProtocolICMP,
				icmp.Message{
					Type: ipv4.ICMPTypeEcho, Code: 0,
					Body: &icmp.Echo{
						ID:   os.Getpid() & 0xffff,
						Data: []byte("HELLO-R-U-THERE"),
					},
				},
			},

			{
				"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP,
				icmp.Message{
					Type: ipv6.ICMPTypeEchoRequest, Code: 0,
					Body: &icmp.Echo{
						ID:   os.Getpid() & 0xffff,
						Data: []byte("HELLO-R-U-THERE"),
					},
				},
			},
		} {
			if err := doDiag(dt, i); err != nil {
				t.Error(err)
			}
		}
	})
	t.Run("Probe/Privileged", func(t *testing.T) {
		if m, ok := nettest.SupportsRawIPSocket(); !ok {
			t.Skip(m)
		}
		for i, dt := range []diagTest{
			{
				"ip4:icmp", "0.0.0.0", iana.ProtocolICMP,
				icmp.Message{
					Type: ipv4.ICMPTypeExtendedEchoRequest, Code: 0,
					Body: &icmp.ExtendedEchoRequest{
						ID:    os.Getpid() & 0xffff,
						Local: true,
						Extensions: []icmp.Extension{
							&icmp.InterfaceIdent{
								Class: 3, Type: 1,
								Name: "doesnotexist",
							},
						},
					},
				},
			},

			{
				"ip6:ipv6-icmp", "::", iana.ProtocolIPv6ICMP,
				icmp.Message{
					Type: ipv6.ICMPTypeExtendedEchoRequest, Code: 0,
					Body: &icmp.ExtendedEchoRequest{
						ID:    os.Getpid() & 0xffff,
						Local: true,
						Extensions: []icmp.Extension{
							&icmp.InterfaceIdent{
								Class: 3, Type: 1,
								Name: "doesnotexist",
							},
						},
					},
				},
			},
		} {
			if err := doDiag(dt, i); err != nil {
				t.Error(err)
			}
		}
	})
}

func doDiag(dt diagTest, seq int) error {
	c, err := icmp.ListenPacket(dt.network, dt.address)
	if err != nil {
		return err
	}
	defer c.Close()

	dst, err := googleAddr(c, dt.protocol)
	if err != nil {
		return err
	}

	if dt.network != "udp6" && dt.protocol == iana.ProtocolIPv6ICMP {
		var f ipv6.ICMPFilter
		f.SetAll(true)
		f.Accept(ipv6.ICMPTypeDestinationUnreachable)
		f.Accept(ipv6.ICMPTypePacketTooBig)
		f.Accept(ipv6.ICMPTypeTimeExceeded)
		f.Accept(ipv6.ICMPTypeParameterProblem)
		f.Accept(ipv6.ICMPTypeEchoReply)
		f.Accept(ipv6.ICMPTypeExtendedEchoReply)
		if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil {
			return err
		}
	}

	switch m := dt.m.Body.(type) {
	case *icmp.Echo:
		m.Seq = 1 << uint(seq)
	case *icmp.ExtendedEchoRequest:
		m.Seq = 1 << uint(seq)
	}
	wb, err := dt.m.Marshal(nil)
	if err != nil {
		return err
	}
	if n, err := c.WriteTo(wb, dst); err != nil {
		return err
	} else if n != len(wb) {
		return fmt.Errorf("got %v; want %v", n, len(wb))
	}

	rb := make([]byte, 1500)
	if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
		return err
	}
	n, peer, err := c.ReadFrom(rb)
	if err != nil {
		return err
	}
	rm, err := icmp.ParseMessage(dt.protocol, rb[:n])
	if err != nil {
		return err
	}
	switch {
	case dt.m.Type == ipv4.ICMPTypeEcho && rm.Type == ipv4.ICMPTypeEchoReply:
		fallthrough
	case dt.m.Type == ipv6.ICMPTypeEchoRequest && rm.Type == ipv6.ICMPTypeEchoReply:
		fallthrough
	case dt.m.Type == ipv4.ICMPTypeExtendedEchoRequest && rm.Type == ipv4.ICMPTypeExtendedEchoReply:
		fallthrough
	case dt.m.Type == ipv6.ICMPTypeExtendedEchoRequest && rm.Type == ipv6.ICMPTypeExtendedEchoReply:
		return nil
	default:
		return fmt.Errorf("got %+v from %v; want echo reply or extended echo reply", rm, peer)
	}
}

func googleAddr(c *icmp.PacketConn, protocol int) (net.Addr, error) {
	host := "ipv4.google.com"
	if protocol == iana.ProtocolIPv6ICMP {
		host = "ipv6.google.com"
	}
	ips, err := net.LookupIP(host)
	if err != nil {
		return nil, err
	}
	netaddr := func(ip net.IP) (net.Addr, error) {
		switch c.LocalAddr().(type) {
		case *net.UDPAddr:
			return &net.UDPAddr{IP: ip}, nil
		case *net.IPAddr:
			return &net.IPAddr{IP: ip}, nil
		default:
			return nil, errors.New("neither UDPAddr nor IPAddr")
		}
	}
	if len(ips) > 0 {
		return netaddr(ips[0])
	}
	return nil, errors.New("no A or AAAA record")
}

func TestConcurrentNonPrivilegedListenPacket(t *testing.T) {
	if testing.Short() {
		t.Skip("avoid external network")
	}
	switch runtime.GOOS {
	case "darwin":
	case "linux":
		t.Log("you may need to adjust the net.ipv4.ping_group_range kernel state")
	default:
		t.Skipf("not supported on %s", runtime.GOOS)
	}

	network, address := "udp4", "127.0.0.1"
	if !nettest.SupportsIPv4() {
		network, address = "udp6", "::1"
	}
	const N = 1000
	var wg sync.WaitGroup
	wg.Add(N)
	for i := 0; i < N; i++ {
		go func() {
			defer wg.Done()
			c, err := icmp.ListenPacket(network, address)
			if err != nil {
				t.Error(err)
				return
			}
			c.Close()
		}()
	}
	wg.Wait()
}


text:
// Copyright 2015 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 icmp

import (
	"encoding/binary"

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

// An Extension represents an ICMP extension.
type Extension interface {
	// Len returns the length of ICMP extension.
	// Proto must be either the ICMPv4 or ICMPv6 protocol number.
	Len(proto int) int

	// Marshal returns the binary encoding of ICMP extension.
	// Proto must be either the ICMPv4 or ICMPv6 protocol number.
	Marshal(proto int) ([]byte, error)
}

const extensionVersion = 2

func validExtensionHeader(b []byte) bool {
	v := int(b[0]&0xf0) >> 4
	s := binary.BigEndian.Uint16(b[2:4])
	if s != 0 {
		s = checksum(b)
	}
	if v != extensionVersion || s != 0 {
		return false
	}
	return true
}

// parseExtensions parses b as a list of ICMP extensions.
// The length attribute l must be the length attribute field in
// received icmp messages.
//
// It will return a list of ICMP extensions and an adjusted length
// attribute that represents the length of the padded original
// datagram field. Otherwise, it returns an error.
func parseExtensions(typ Type, b []byte, l int) ([]Extension, int, error) {
	// Still a lot of non-RFC 4884 compliant implementations are
	// out there. Set the length attribute l to 128 when it looks
	// inappropriate for backwards compatibility.
	//
	// A minimal extension at least requires 8 octets; 4 octets
	// for an extension header, and 4 octets for a single object
	// header.
	//
	// See RFC 4884 for further information.
	switch typ {
	case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
		if len(b) < 8 || !validExtensionHeader(b) {
			return nil, -1, errNoExtension
		}
		l = 0
	default:
		if 128 > l || l+8 > len(b) {
			l = 128
		}
		if l+8 > len(b) {
			return nil, -1, errNoExtension
		}
		if !validExtensionHeader(b[l:]) {
			if l == 128 {
				return nil, -1, errNoExtension
			}
			l = 128
			if !validExtensionHeader(b[l:]) {
				return nil, -1, errNoExtension
			}
		}
	}
	var exts []Extension
	for b = b[l+4:]; len(b) >= 4; {
		ol := int(binary.BigEndian.Uint16(b[:2]))
		if 4 > ol || ol > len(b) {
			break
		}
		switch b[2] {
		case classMPLSLabelStack:
			ext, err := parseMPLSLabelStack(b[:ol])
			if err != nil {
				return nil, -1, err
			}
			exts = append(exts, ext)
		case classInterfaceInfo:
			ext, err := parseInterfaceInfo(b[:ol])
			if err != nil {
				return nil, -1, err
			}
			exts = append(exts, ext)
		case classInterfaceIdent:
			ext, err := parseInterfaceIdent(b[:ol])
			if err != nil {
				return nil, -1, err
			}
			exts = append(exts, ext)
		}
		b = b[ol:]
	}
	return exts, l, nil
}


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 icmp

import "encoding/binary"

// An Echo represents an ICMP echo request or reply message body.
type Echo struct {
	ID   int    // identifier
	Seq  int    // sequence number
	Data []byte // data
}

// Len implements the Len method of MessageBody interface.
func (p *Echo) Len(proto int) int {
	if p == nil {
		return 0
	}
	return 4 + len(p.Data)
}

// Marshal implements the Marshal method of MessageBody interface.
func (p *Echo) Marshal(proto int) ([]byte, error) {
	b := make([]byte, 4+len(p.Data))
	binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
	binary.BigEndian.PutUint16(b[2:4], uint16(p.Seq))
	copy(b[4:], p.Data)
	return b, nil
}

// parseEcho parses b as an ICMP echo request or reply message body.
func parseEcho(proto int, _ Type, b []byte) (MessageBody, error) {
	bodyLen := len(b)
	if bodyLen < 4 {
		return nil, errMessageTooShort
	}
	p := &Echo{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(binary.BigEndian.Uint16(b[2:4]))}
	if bodyLen > 4 {
		p.Data = make([]byte, bodyLen-4)
		copy(p.Data, b[4:])
	}
	return p, nil
}

// An ExtendedEchoRequest represents an ICMP extended echo request
// message body.
type ExtendedEchoRequest struct {
	ID         int         // identifier
	Seq        int         // sequence number
	Local      bool        // must be true when identifying by name or index
	Extensions []Extension // extensions
}

// Len implements the Len method of MessageBody interface.
func (p *ExtendedEchoRequest) Len(proto int) int {
	if p == nil {
		return 0
	}
	l, _ := multipartMessageBodyDataLen(proto, false, nil, p.Extensions)
	return 4 + l
}

// Marshal implements the Marshal method of MessageBody interface.
func (p *ExtendedEchoRequest) Marshal(proto int) ([]byte, error) {
	b, err := marshalMultipartMessageBody(proto, false, nil, p.Extensions)
	if err != nil {
		return nil, err
	}
	bb := make([]byte, 4)
	binary.BigEndian.PutUint16(bb[:2], uint16(p.ID))
	bb[2] = byte(p.Seq)
	if p.Local {
		bb[3] |= 0x01
	}
	bb = append(bb, b...)
	return bb, nil
}

// parseExtendedEchoRequest parses b as an ICMP extended echo request
// message body.
func parseExtendedEchoRequest(proto int, typ Type, b []byte) (MessageBody, error) {
	if len(b) < 4+4 {
		return nil, errMessageTooShort
	}
	p := &ExtendedEchoRequest{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(b[2])}
	if b[3]&0x01 != 0 {
		p.Local = true
	}
	var err error
	_, p.Extensions, err = parseMultipartMessageBody(proto, typ, b[4:])
	if err != nil {
		return nil, err
	}
	return p, nil
}

// An ExtendedEchoReply represents an ICMP extended echo reply message
// body.
type ExtendedEchoReply struct {
	ID     int  // identifier
	Seq    int  // sequence number
	State  int  // 3-bit state working together with Message.Code
	Active bool // probed interface is active
	IPv4   bool // probed interface runs IPv4
	IPv6   bool // probed interface runs IPv6
}

// Len implements the Len method of MessageBody interface.
func (p *ExtendedEchoReply) Len(proto int) int {
	if p == nil {
		return 0
	}
	return 4
}

// Marshal implements the Marshal method of MessageBody interface.
func (p *ExtendedEchoReply) Marshal(proto int) ([]byte, error) {
	b := make([]byte, 4)
	binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
	b[2] = byte(p.Seq)
	b[3] = byte(p.State<<5) & 0xe0
	if p.Active {
		b[3] |= 0x04
	}
	if p.IPv4 {
		b[3] |= 0x02
	}
	if p.IPv6 {
		b[3] |= 0x01
	}
	return b, nil
}

// parseExtendedEchoReply parses b as an ICMP extended echo reply
// message body.
func parseExtendedEchoReply(proto int, _ Type, b []byte) (MessageBody, error) {
	if len(b) < 4 {
		return nil, errMessageTooShort
	}
	p := &ExtendedEchoReply{
		ID:    int(binary.BigEndian.Uint16(b[:2])),
		Seq:   int(b[2]),
		State: int(b[3]) >> 5,
	}
	if b[3]&0x04 != 0 {
		p.Active = true
	}
	if b[3]&0x02 != 0 {
		p.IPv4 = true
	}
	if b[3]&0x01 != 0 {
		p.IPv6 = true
	}
	return p, nil
}


text:
// Copyright 2013 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 icmp

import (
	"net"

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

const ipv6PseudoHeaderLen = 2*net.IPv6len + 8

// IPv6PseudoHeader returns an IPv6 pseudo header for checksum
// calculation.
func IPv6PseudoHeader(src, dst net.IP) []byte {
	b := make([]byte, ipv6PseudoHeaderLen)
	copy(b, src.To16())
	copy(b[net.IPv6len:], dst.To16())
	b[len(b)-1] = byte(iana.ProtocolIPv6ICMP)
	return b
}


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 icmp

import "syscall"

func init() {
	freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
}


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 solaris

package lif

// 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
	Uint64([]byte) uint64
	PutUint16([]byte, uint16)
	PutUint32([]byte, uint32)
	PutUint64([]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
}

func (binaryLittleEndian) PutUint64(b []byte, v uint64) {
	_ = b[7] // 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)
	b[4] = byte(v >> 32)
	b[5] = byte(v >> 40)
	b[6] = byte(v >> 48)
	b[7] = byte(v >> 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
}

func (binaryBigEndian) PutUint64(b []byte, v uint64) {
	_ = b[7] // early bounds check to guarantee safety of writes below
	b[0] = byte(v >> 56)
	b[1] = byte(v >> 48)
	b[2] = byte(v >> 40)
	b[3] = byte(v >> 32)
	b[4] = byte(v >> 24)
	b[5] = byte(v >> 16)
	b[6] = byte(v >> 8)
	b[7] = byte(v)
}


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

package lif

const (
	sysAF_UNSPEC = 0x0
	sysAF_INET   = 0x2
	sysAF_INET6  = 0x1a

	sysSOCK_DGRAM = 0x1
)

type sockaddrStorage struct {
	Family     uint16
	X_ss_pad1  [6]int8
	X_ss_align float64
	X_ss_pad2  [240]int8
}

const (
	sysLIFC_NOXMIT          = 0x1
	sysLIFC_EXTERNAL_SOURCE = 0x2
	sysLIFC_TEMPORARY       = 0x4
	sysLIFC_ALLZONES        = 0x8
	sysLIFC_UNDER_IPMP      = 0x10
	sysLIFC_ENABLED         = 0x20

	sysSIOCGLIFADDR    = -0x3f87968f
	sysSIOCGLIFDSTADDR = -0x3f87968d
	sysSIOCGLIFFLAGS   = -0x3f87968b
	sysSIOCGLIFMTU     = -0x3f879686
	sysSIOCGLIFNETMASK = -0x3f879683
	sysSIOCGLIFMETRIC  = -0x3f879681
	sysSIOCGLIFNUM     = -0x3ff3967e
	sysSIOCGLIFINDEX   = -0x3f87967b
	sysSIOCGLIFSUBNET  = -0x3f879676
	sysSIOCGLIFLNKINFO = -0x3f879674
	sysSIOCGLIFCONF    = -0x3fef965b
	sysSIOCGLIFHWADDR  = -0x3f879640
)

const (
	sysIFF_UP          = 0x1
	sysIFF_BROADCAST   = 0x2
	sysIFF_DEBUG       = 0x4
	sysIFF_LOOPBACK    = 0x8
	sysIFF_POINTOPOINT = 0x10
	sysIFF_NOTRAILERS  = 0x20
	sysIFF_RUNNING     = 0x40
	sysIFF_NOARP       = 0x80
	sysIFF_PROMISC     = 0x100
	sysIFF_ALLMULTI    = 0x200
	sysIFF_INTELLIGENT = 0x400
	sysIFF_MULTICAST   = 0x800
	sysIFF_MULTI_BCAST = 0x1000
	sysIFF_UNNUMBERED  = 0x2000
	sysIFF_PRIVATE     = 0x8000
)

const (
	sizeofLifnum       = 0xc
	sizeofLifreq       = 0x178
	sizeofLifconf      = 0x18
	sizeofLifIfinfoReq = 0x10
)

type lifnum struct {
	Family    uint16
	Pad_cgo_0 [2]byte
	Flags     int32
	Count     int32
}

type lifreq struct {
	Name   [32]int8
	Lifru1 [4]byte
	Type   uint32
	Lifru  [336]byte
}

type lifconf struct {
	Family    uint16
	Pad_cgo_0 [2]byte
	Flags     int32
	Len       int32
	Pad_cgo_1 [4]byte
	Lifcu     [8]byte
}

type lifIfinfoReq struct {
	Maxhops      uint8
	Pad_cgo_0    [3]byte
	Reachtime    uint32
	Reachretrans uint32
	Maxmtu       uint32
}

const (
	sysIFT_IPV4 = 0xc8
	sysIFT_IPV6 = 0xc9
	sysIFT_6TO4 = 0xca
)


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.

#include "textflag.h"

TEXT ·sysvicall6(SB),NOSPLIT,$0-88
	JMP	syscall·sysvicall6(SB)


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 solaris

package lif

import (
	"fmt"
	"testing"
)

type addrFamily int

func (af addrFamily) String() string {
	switch af {
	case sysAF_UNSPEC:
		return "unspec"
	case sysAF_INET:
		return "inet4"
	case sysAF_INET6:
		return "inet6"
	default:
		return fmt.Sprintf("%d", af)
	}
}

const hexDigit = "0123456789abcdef"

type llAddr []byte

func (a llAddr) String() string {
	if len(a) == 0 {
		return ""
	}
	buf := make([]byte, 0, len(a)*3-1)
	for i, b := range a {
		if i > 0 {
			buf = append(buf, ':')
		}
		buf = append(buf, hexDigit[b>>4])
		buf = append(buf, hexDigit[b&0xF])
	}
	return string(buf)
}

type ipAddr []byte

func (a ipAddr) String() string {
	if len(a) == 0 {
		return "<nil>"
	}
	if len(a) == 4 {
		return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
	}
	if len(a) == 16 {
		return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
	}
	s := make([]byte, len(a)*2)
	for i, tn := range a {
		s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
	}
	return string(s)
}

func (a *Inet4Addr) String() string {
	return fmt.Sprintf("(%s %s %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.PrefixLen)
}

func (a *Inet6Addr) String() string {
	return fmt.Sprintf("(%s %s %d %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.PrefixLen, a.ZoneID)
}

type addrPack struct {
	af int
	as []Addr
}

func addrPacks() ([]addrPack, error) {
	var lastErr error
	var aps []addrPack
	for _, af := range [...]int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
		as, err := Addrs(af, "")
		if err != nil {
			lastErr = err
			continue
		}
		aps = append(aps, addrPack{af: af, as: as})
	}
	return aps, lastErr
}

func TestAddrs(t *testing.T) {
	aps, err := addrPacks()
	if len(aps) == 0 && err != nil {
		t.Fatal(err)
	}
	lps, err := linkPacks()
	if len(lps) == 0 && err != nil {
		t.Fatal(err)
	}
	for _, lp := range lps {
		n := 0
		for _, ll := range lp.lls {
			as, err := Addrs(lp.af, ll.Name)
			if err != nil {
				t.Fatal(lp.af, ll.Name, err)
			}
			t.Logf("af=%s name=%s %v", addrFamily(lp.af), ll.Name, as)
			n += len(as)
		}
		for _, ap := range aps {
			if ap.af != lp.af {
				continue
			}
			if n != len(ap.as) {
				t.Errorf("af=%s got %d; want %d", addrFamily(lp.af), n, len(ap.as))
				continue
			}
		}
	}
}


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 solaris

// Package lif provides basic functions for the manipulation of
// logical network interfaces and interface addresses on Solaris.
//
// The package supports Solaris 11 or above.
package lif

import "syscall"

type endpoint struct {
	af int
	s  uintptr
}

func (ep *endpoint) close() error {
	return syscall.Close(int(ep.s))
}

func newEndpoints(af int) ([]endpoint, error) {
	var lastErr error
	var eps []endpoint
	afs := []int{sysAF_INET, sysAF_INET6}
	if af != sysAF_UNSPEC {
		afs = []int{af}
	}
	for _, af := range afs {
		s, err := syscall.Socket(af, sysSOCK_DGRAM, 0)
		if err != nil {
			lastErr = err
			continue
		}
		eps = append(eps, endpoint{af: af, s: uintptr(s)})
	}
	if len(eps) == 0 {
		return nil, lastErr
	}
	return eps, 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 solaris

package lif

import "unsafe"

// A Link represents logical data link information.
//
// It also represents base information for logical network interface.
// On Solaris, each logical network interface represents network layer
// adjacency information and the interface has a only single network
// address or address pair for tunneling. It's usual that multiple
// logical network interfaces share the same logical data link.
type Link struct {
	Name  string // name, equivalent to IP interface name
	Index int    // index, equivalent to IP interface index
	Type  int    // type
	Flags int    // flags
	MTU   int    // maximum transmission unit, basically link MTU but may differ between IP address families
	Addr  []byte // address
}

func (ll *Link) fetch(s uintptr) {
	var lifr lifreq
	for i := 0; i < len(ll.Name); i++ {
		lifr.Name[i] = int8(ll.Name[i])
	}
	ioc := int64(sysSIOCGLIFINDEX)
	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
		ll.Index = int(nativeEndian.Uint32(lifr.Lifru[:4]))
	}
	ioc = int64(sysSIOCGLIFFLAGS)
	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
		ll.Flags = int(nativeEndian.Uint64(lifr.Lifru[:8]))
	}
	ioc = int64(sysSIOCGLIFMTU)
	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
		ll.MTU = int(nativeEndian.Uint32(lifr.Lifru[:4]))
	}
	switch ll.Type {
	case sysIFT_IPV4, sysIFT_IPV6, sysIFT_6TO4:
	default:
		ioc = int64(sysSIOCGLIFHWADDR)
		if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
			ll.Addr, _ = parseLinkAddr(lifr.Lifru[4:])
		}
	}
}

// Links returns a list of logical data links.
//
// The provided af must be an address family and name must be a data
// link name. The zero value of af or name means a wildcard.
func Links(af int, name string) ([]Link, error) {
	eps, err := newEndpoints(af)
	if len(eps) == 0 {
		return nil, err
	}
	defer func() {
		for _, ep := range eps {
			ep.close()
		}
	}()
	return links(eps, name)
}

func links(eps []endpoint, name string) ([]Link, error) {
	var lls []Link
	lifn := lifnum{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
	lifc := lifconf{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
	for _, ep := range eps {
		lifn.Family = uint16(ep.af)
		ioc := int64(sysSIOCGLIFNUM)
		if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifn)); err != nil {
			continue
		}
		if lifn.Count == 0 {
			continue
		}
		b := make([]byte, lifn.Count*sizeofLifreq)
		lifc.Family = uint16(ep.af)
		lifc.Len = lifn.Count * sizeofLifreq
		if len(lifc.Lifcu) == 8 {
			nativeEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
		} else {
			nativeEndian.PutUint32(lifc.Lifcu[:], uint32(uintptr(unsafe.Pointer(&b[0]))))
		}
		ioc = int64(sysSIOCGLIFCONF)
		if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifc)); err != nil {
			continue
		}
		nb := make([]byte, 32) // see LIFNAMSIZ in net/if.h
		for i := 0; i < int(lifn.Count); i++ {
			lifr := (*lifreq)(unsafe.Pointer(&b[i*sizeofLifreq]))
			for i := 0; i < 32; i++ {
				if lifr.Name[i] == 0 {
					nb = nb[:i]
					break
				}
				nb[i] = byte(lifr.Name[i])
			}
			llname := string(nb)
			nb = nb[:32]
			if isDupLink(lls, llname) || name != "" && name != llname {
				continue
			}
			ll := Link{Name: llname, Type: int(lifr.Type)}
			ll.fetch(ep.s)
			lls = append(lls, ll)
		}
	}
	return lls, nil
}

func isDupLink(lls []Link, name string) bool {
	for _, ll := range lls {
		if ll.Name == name {
			return true
		}
	}
	return false
}


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 solaris

package lif

import (
	"errors"
	"unsafe"
)

// An Addr represents an address associated with packet routing.
type Addr interface {
	// Family returns an address family.
	Family() int
}

// An Inet4Addr represents an internet address for IPv4.
type Inet4Addr struct {
	IP        [4]byte // IP address
	PrefixLen int     // address prefix length
}

// Family implements the Family method of Addr interface.
func (a *Inet4Addr) Family() int { return sysAF_INET }

// An Inet6Addr represents an internet address for IPv6.
type Inet6Addr struct {
	IP        [16]byte // IP address
	PrefixLen int      // address prefix length
	ZoneID    int      // zone identifier
}

// Family implements the Family method of Addr interface.
func (a *Inet6Addr) Family() int { return sysAF_INET6 }

// Addrs returns a list of interface addresses.
//
// The provided af must be an address family and name must be a data
// link name. The zero value of af or name means a wildcard.
func Addrs(af int, name string) ([]Addr, error) {
	eps, err := newEndpoints(af)
	if len(eps) == 0 {
		return nil, err
	}
	defer func() {
		for _, ep := range eps {
			ep.close()
		}
	}()
	lls, err := links(eps, name)
	if len(lls) == 0 {
		return nil, err
	}
	var as []Addr
	for _, ll := range lls {
		var lifr lifreq
		for i := 0; i < len(ll.Name); i++ {
			lifr.Name[i] = int8(ll.Name[i])
		}
		for _, ep := range eps {
			ioc := int64(sysSIOCGLIFADDR)
			err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifr))
			if err != nil {
				continue
			}
			sa := (*sockaddrStorage)(unsafe.Pointer(&lifr.Lifru[0]))
			l := int(nativeEndian.Uint32(lifr.Lifru1[:4]))
			if l == 0 {
				continue
			}
			switch sa.Family {
			case sysAF_INET:
				a := &Inet4Addr{PrefixLen: l}
				copy(a.IP[:], lifr.Lifru[4:8])
				as = append(as, a)
			case sysAF_INET6:
				a := &Inet6Addr{PrefixLen: l, ZoneID: int(nativeEndian.Uint32(lifr.Lifru[24:28]))}
				copy(a.IP[:], lifr.Lifru[8:24])
				as = append(as, a)
			}
		}
	}
	return as, nil
}

func parseLinkAddr(b []byte) ([]byte, error) {
	nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
	l := 4 + nlen + alen + slen
	if len(b) < l {
		return nil, errors.New("invalid address")
	}
	b = b[4:]
	var addr []byte
	if nlen > 0 {
		b = b[nlen:]
	}
	if alen > 0 {
		addr = make([]byte, alen)
		copy(addr, b[:alen])
	}
	return addr, 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 solaris

package lif

import (
	"fmt"
	"testing"
)

func (ll *Link) String() string {
	return fmt.Sprintf("name=%s index=%d type=%d flags=%#x mtu=%d addr=%v", ll.Name, ll.Index, ll.Type, ll.Flags, ll.MTU, llAddr(ll.Addr))
}

type linkPack struct {
	af  int
	lls []Link
}

func linkPacks() ([]linkPack, error) {
	var lastErr error
	var lps []linkPack
	for _, af := range [...]int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
		lls, err := Links(af, "")
		if err != nil {
			lastErr = err
			continue
		}
		lps = append(lps, linkPack{af: af, lls: lls})
	}
	return lps, lastErr
}

func TestLinks(t *testing.T) {
	lps, err := linkPacks()
	if len(lps) == 0 && err != nil {
		t.Fatal(err)
	}
	for _, lp := range lps {
		n := 0
		for _, sll := range lp.lls {
			lls, err := Links(lp.af, sll.Name)
			if err != nil {
				t.Fatal(lp.af, sll.Name, err)
			}
			for _, ll := range lls {
				if ll.Name != sll.Name || ll.Index != sll.Index {
					t.Errorf("af=%s got %v; want %v", addrFamily(lp.af), &ll, &sll)
					continue
				}
				t.Logf("af=%s name=%s %v", addrFamily(lp.af), sll.Name, &ll)
				n++
			}
		}
		if n != len(lp.lls) {
			t.Errorf("af=%s got %d; want %d", addrFamily(lp.af), n, len(lp.lls))
			continue
		}
	}
}


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 solaris

package lif

import (
	"syscall"
	"unsafe"
)

//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"

//go:linkname procIoctl libc_ioctl

var procIoctl uintptr

func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)

func ioctl(s, ioc uintptr, arg unsafe.Pointer) error {
	_, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procIoctl)), 3, s, ioc, uintptr(arg), 0, 0, 0)
	if errno != 0 {
		return error(errno)
	}
	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.

// +build ignore

// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */

package lif

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

#include <net/if.h>
#include <net/if_types.h>
*/
import "C"

const (
	sysAF_UNSPEC = C.AF_UNSPEC
	sysAF_INET   = C.AF_INET
	sysAF_INET6  = C.AF_INET6

	sysSOCK_DGRAM = C.SOCK_DGRAM
)

type sockaddrStorage C.struct_sockaddr_storage

const (
	sysLIFC_NOXMIT          = C.LIFC_NOXMIT
	sysLIFC_EXTERNAL_SOURCE = C.LIFC_EXTERNAL_SOURCE
	sysLIFC_TEMPORARY       = C.LIFC_TEMPORARY
	sysLIFC_ALLZONES        = C.LIFC_ALLZONES
	sysLIFC_UNDER_IPMP      = C.LIFC_UNDER_IPMP
	sysLIFC_ENABLED         = C.LIFC_ENABLED

	sysSIOCGLIFADDR    = C.SIOCGLIFADDR
	sysSIOCGLIFDSTADDR = C.SIOCGLIFDSTADDR
	sysSIOCGLIFFLAGS   = C.SIOCGLIFFLAGS
	sysSIOCGLIFMTU     = C.SIOCGLIFMTU
	sysSIOCGLIFNETMASK = C.SIOCGLIFNETMASK
	sysSIOCGLIFMETRIC  = C.SIOCGLIFMETRIC
	sysSIOCGLIFNUM     = C.SIOCGLIFNUM
	sysSIOCGLIFINDEX   = C.SIOCGLIFINDEX
	sysSIOCGLIFSUBNET  = C.SIOCGLIFSUBNET
	sysSIOCGLIFLNKINFO = C.SIOCGLIFLNKINFO
	sysSIOCGLIFCONF    = C.SIOCGLIFCONF
	sysSIOCGLIFHWADDR  = C.SIOCGLIFHWADDR
)

const (
	sysIFF_UP          = C.IFF_UP
	sysIFF_BROADCAST   = C.IFF_BROADCAST
	sysIFF_DEBUG       = C.IFF_DEBUG
	sysIFF_LOOPBACK    = C.IFF_LOOPBACK
	sysIFF_POINTOPOINT = C.IFF_POINTOPOINT
	sysIFF_NOTRAILERS  = C.IFF_NOTRAILERS
	sysIFF_RUNNING     = C.IFF_RUNNING
	sysIFF_NOARP       = C.IFF_NOARP
	sysIFF_PROMISC     = C.IFF_PROMISC
	sysIFF_ALLMULTI    = C.IFF_ALLMULTI
	sysIFF_INTELLIGENT = C.IFF_INTELLIGENT
	sysIFF_MULTICAST   = C.IFF_MULTICAST
	sysIFF_MULTI_BCAST = C.IFF_MULTI_BCAST
	sysIFF_UNNUMBERED  = C.IFF_UNNUMBERED
	sysIFF_PRIVATE     = C.IFF_PRIVATE
)

const (
	sizeofLifnum       = C.sizeof_struct_lifnum
	sizeofLifreq       = C.sizeof_struct_lifreq
	sizeofLifconf      = C.sizeof_struct_lifconf
	sizeofLifIfinfoReq = C.sizeof_struct_lif_ifinfo_req
)

type lifnum C.struct_lifnum

type lifreq C.struct_lifreq

type lifconf C.struct_lifconf

type lifIfinfoReq C.struct_lif_ifinfo_req

const (
	sysIFT_IPV4 = C.IFT_IPV4
	sysIFT_IPV6 = C.IFT_IPV6
	sysIFT_6TO4 = C.IFT_6TO4
)


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 solaris

package lif

import "unsafe"

var nativeEndian binaryByteOrder

func init() {
	i := uint32(1)
	b := (*[4]byte)(unsafe.Pointer(&i))
	if b[0] == 1 {
		nativeEndian = littleEndian
	} else {
		nativeEndian = bigEndian
	}
}


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

//go:generate go run gen.go

// This program generates internet protocol constants and tables by
// reading IANA protocol registries.
package main

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"go/format"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"strings"
)

var registries = []struct {
	url   string
	parse func(io.Writer, io.Reader) error
}{
	{
		"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
		parseDSCPRegistry,
	},
	{
		"https://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
		parseTOSTCByte,
	},
	{
		"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
		parseProtocolNumbers,
	},
	{
		"http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
		parseAddrFamilyNumbers,
	},
}

func main() {
	var bb bytes.Buffer
	fmt.Fprintf(&bb, "// go generate gen.go\n")
	fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
	fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
	fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
	for _, r := range registries {
		resp, err := http.Get(r.url)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		defer resp.Body.Close()
		if resp.StatusCode != http.StatusOK {
			fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
			os.Exit(1)
		}
		if err := r.parse(&bb, resp.Body); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		fmt.Fprintf(&bb, "\n")
	}
	b, err := format.Source(bb.Bytes())
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func parseDSCPRegistry(w io.Writer, r io.Reader) error {
	dec := xml.NewDecoder(r)
	var dr dscpRegistry
	if err := dec.Decode(&dr); err != nil {
		return err
	}
	drs := dr.escape()
	fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
	fmt.Fprintf(w, "const (\n")
	for _, dr := range drs {
		fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
		fmt.Fprintf(w, "// %s\n", dr.OrigName)
	}
	fmt.Fprintf(w, ")\n")
	return nil
}

type dscpRegistry struct {
	XMLName     xml.Name `xml:"registry"`
	Title       string   `xml:"title"`
	Updated     string   `xml:"updated"`
	Note        string   `xml:"note"`
	RegTitle    string   `xml:"registry>title"`
	PoolRecords []struct {
		Name  string `xml:"name"`
		Space string `xml:"space"`
	} `xml:"registry>record"`
	Records []struct {
		Name  string `xml:"name"`
		Space string `xml:"space"`
	} `xml:"registry>registry>record"`
}

type canonDSCPRecord struct {
	OrigName string
	Name     string
	Value    int
}

func (drr *dscpRegistry) escape() []canonDSCPRecord {
	drs := make([]canonDSCPRecord, len(drr.Records))
	sr := strings.NewReplacer(
		"+", "",
		"-", "",
		"/", "",
		".", "",
		" ", "",
	)
	for i, dr := range drr.Records {
		s := strings.TrimSpace(dr.Name)
		drs[i].OrigName = s
		drs[i].Name = sr.Replace(s)
		n, err := strconv.ParseUint(dr.Space, 2, 8)
		if err != nil {
			continue
		}
		drs[i].Value = int(n) << 2
	}
	return drs
}

func parseTOSTCByte(w io.Writer, r io.Reader) error {
	dec := xml.NewDecoder(r)
	var ttb tosTCByte
	if err := dec.Decode(&ttb); err != nil {
		return err
	}
	trs := ttb.escape()
	fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
	fmt.Fprintf(w, "const (\n")
	for _, tr := range trs {
		fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
		fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
	}
	fmt.Fprintf(w, ")\n")
	return nil
}

type tosTCByte struct {
	XMLName  xml.Name `xml:"registry"`
	Title    string   `xml:"title"`
	Updated  string   `xml:"updated"`
	Note     string   `xml:"note"`
	RegTitle string   `xml:"registry>title"`
	Records  []struct {
		Binary  string `xml:"binary"`
		Keyword string `xml:"keyword"`
	} `xml:"registry>record"`
}

type canonTOSTCByteRecord struct {
	OrigKeyword string
	Keyword     string
	Value       int
}

func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
	trs := make([]canonTOSTCByteRecord, len(ttb.Records))
	sr := strings.NewReplacer(
		"Capable", "",
		"(", "",
		")", "",
		"+", "",
		"-", "",
		"/", "",
		".", "",
		" ", "",
	)
	for i, tr := range ttb.Records {
		s := strings.TrimSpace(tr.Keyword)
		trs[i].OrigKeyword = s
		ss := strings.Split(s, " ")
		if len(ss) > 1 {
			trs[i].Keyword = strings.Join(ss[1:], " ")
		} else {
			trs[i].Keyword = ss[0]
		}
		trs[i].Keyword = sr.Replace(trs[i].Keyword)
		n, err := strconv.ParseUint(tr.Binary, 2, 8)
		if err != nil {
			continue
		}
		trs[i].Value = int(n)
	}
	return trs
}

func parseProtocolNumbers(w io.Writer, r io.Reader) error {
	dec := xml.NewDecoder(r)
	var pn protocolNumbers
	if err := dec.Decode(&pn); err != nil {
		return err
	}
	prs := pn.escape()
	prs = append([]canonProtocolRecord{{
		Name:  "IP",
		Descr: "IPv4 encapsulation, pseudo protocol number",
		Value: 0,
	}}, prs...)
	fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
	fmt.Fprintf(w, "const (\n")
	for _, pr := range prs {
		if pr.Name == "" {
			continue
		}
		fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
		s := pr.Descr
		if s == "" {
			s = pr.OrigName
		}
		fmt.Fprintf(w, "// %s\n", s)
	}
	fmt.Fprintf(w, ")\n")
	return nil
}

type protocolNumbers struct {
	XMLName  xml.Name `xml:"registry"`
	Title    string   `xml:"title"`
	Updated  string   `xml:"updated"`
	RegTitle string   `xml:"registry>title"`
	Note     string   `xml:"registry>note"`
	Records  []struct {
		Value string `xml:"value"`
		Name  string `xml:"name"`
		Descr string `xml:"description"`
	} `xml:"registry>record"`
}

type canonProtocolRecord struct {
	OrigName string
	Name     string
	Descr    string
	Value    int
}

func (pn *protocolNumbers) escape() []canonProtocolRecord {
	prs := make([]canonProtocolRecord, len(pn.Records))
	sr := strings.NewReplacer(
		"-in-", "in",
		"-within-", "within",
		"-over-", "over",
		"+", "P",
		"-", "",
		"/", "",
		".", "",
		" ", "",
	)
	for i, pr := range pn.Records {
		if strings.Contains(pr.Name, "Deprecated") ||
			strings.Contains(pr.Name, "deprecated") {
			continue
		}
		prs[i].OrigName = pr.Name
		s := strings.TrimSpace(pr.Name)
		switch pr.Name {
		case "ISIS over IPv4":
			prs[i].Name = "ISIS"
		case "manet":
			prs[i].Name = "MANET"
		default:
			prs[i].Name = sr.Replace(s)
		}
		ss := strings.Split(pr.Descr, "\n")
		for i := range ss {
			ss[i] = strings.TrimSpace(ss[i])
		}
		if len(ss) > 1 {
			prs[i].Descr = strings.Join(ss, " ")
		} else {
			prs[i].Descr = ss[0]
		}
		prs[i].Value, _ = strconv.Atoi(pr.Value)
	}
	return prs
}

func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
	dec := xml.NewDecoder(r)
	var afn addrFamilylNumbers
	if err := dec.Decode(&afn); err != nil {
		return err
	}
	afrs := afn.escape()
	fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
	fmt.Fprintf(w, "const (\n")
	for _, afr := range afrs {
		if afr.Name == "" {
			continue
		}
		fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
		fmt.Fprintf(w, "// %s\n", afr.Descr)
	}
	fmt.Fprintf(w, ")\n")
	return nil
}

type addrFamilylNumbers struct {
	XMLName  xml.Name `xml:"registry"`
	Title    string   `xml:"title"`
	Updated  string   `xml:"updated"`
	RegTitle string   `xml:"registry>title"`
	Note     string   `xml:"registry>note"`
	Records  []struct {
		Value string `xml:"value"`
		Descr string `xml:"description"`
	} `xml:"registry>record"`
}

type canonAddrFamilyRecord struct {
	Name  string
	Descr string
	Value int
}

func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
	afrs := make([]canonAddrFamilyRecord, len(afn.Records))
	sr := strings.NewReplacer(
		"IP version 4", "IPv4",
		"IP version 6", "IPv6",
		"Identifier", "ID",
		"-", "",
		"-", "",
		"/", "",
		".", "",
		" ", "",
	)
	for i, afr := range afn.Records {
		if strings.Contains(afr.Descr, "Unassigned") ||
			strings.Contains(afr.Descr, "Reserved") {
			continue
		}
		afrs[i].Descr = afr.Descr
		s := strings.TrimSpace(afr.Descr)
		switch s {
		case "IP (IP version 4)":
			afrs[i].Name = "IPv4"
		case "IP6 (IP version 6)":
			afrs[i].Name = "IPv6"
		case "AFI for L2VPN information":
			afrs[i].Name = "L2VPN"
		case "E.164 with NSAP format subaddress":
			afrs[i].Name = "E164withSubaddress"
		case "MT IP: Multi-Topology IP version 4":
			afrs[i].Name = "MTIPv4"
		case "MAC/24":
			afrs[i].Name = "MACFinal24bits"
		case "MAC/40":
			afrs[i].Name = "MACFinal40bits"
		case "IPv6/64":
			afrs[i].Name = "IPv6Initial64bits"
		default:
			n := strings.Index(s, "(")
			if n > 0 {
				s = s[:n]
			}
			n = strings.Index(s, ":")
			if n > 0 {
				s = s[:n]
			}
			afrs[i].Name = sr.Replace(s)
		}
		afrs[i].Value, _ = strconv.Atoi(afr.Value)
	}
	return afrs
}


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

// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).
package iana // import "golang.org/x/net/internal/iana"

// Differentiated Services Field Codepoints (DSCP), Updated: 2017-05-12
const (
	DiffServCS0        = 0x0  // CS0
	DiffServCS1        = 0x20 // CS1
	DiffServCS2        = 0x40 // CS2
	DiffServCS3        = 0x60 // CS3
	DiffServCS4        = 0x80 // CS4
	DiffServCS5        = 0xa0 // CS5
	DiffServCS6        = 0xc0 // CS6
	DiffServCS7        = 0xe0 // CS7
	DiffServAF11       = 0x28 // AF11
	DiffServAF12       = 0x30 // AF12
	DiffServAF13       = 0x38 // AF13
	DiffServAF21       = 0x48 // AF21
	DiffServAF22       = 0x50 // AF22
	DiffServAF23       = 0x58 // AF23
	DiffServAF31       = 0x68 // AF31
	DiffServAF32       = 0x70 // AF32
	DiffServAF33       = 0x78 // AF33
	DiffServAF41       = 0x88 // AF41
	DiffServAF42       = 0x90 // AF42
	DiffServAF43       = 0x98 // AF43
	DiffServEF         = 0xb8 // EF
	DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
)

// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06
const (
	NotECNTransport       = 0x0 // Not-ECT (Not ECN-Capable Transport)
	ECNTransport1         = 0x1 // ECT(1) (ECN-Capable Transport(1))
	ECNTransport0         = 0x2 // ECT(0) (ECN-Capable Transport(0))
	CongestionExperienced = 0x3 // CE (Congestion Experienced)
)

// Protocol Numbers, Updated: 2017-10-13
const (
	ProtocolIP             = 0   // IPv4 encapsulation, pseudo protocol number
	ProtocolHOPOPT         = 0   // IPv6 Hop-by-Hop Option
	ProtocolICMP           = 1   // Internet Control Message
	ProtocolIGMP           = 2   // Internet Group Management
	ProtocolGGP            = 3   // Gateway-to-Gateway
	ProtocolIPv4           = 4   // IPv4 encapsulation
	ProtocolST             = 5   // Stream
	ProtocolTCP            = 6   // Transmission Control
	ProtocolCBT            = 7   // CBT
	ProtocolEGP            = 8   // Exterior Gateway Protocol
	ProtocolIGP            = 9   // any private interior gateway (used by Cisco for their IGRP)
	ProtocolBBNRCCMON      = 10  // BBN RCC Monitoring
	ProtocolNVPII          = 11  // Network Voice Protocol
	ProtocolPUP            = 12  // PUP
	ProtocolEMCON          = 14  // EMCON
	ProtocolXNET           = 15  // Cross Net Debugger
	ProtocolCHAOS          = 16  // Chaos
	ProtocolUDP            = 17  // User Datagram
	ProtocolMUX            = 18  // Multiplexing
	ProtocolDCNMEAS        = 19  // DCN Measurement Subsystems
	ProtocolHMP            = 20  // Host Monitoring
	ProtocolPRM            = 21  // Packet Radio Measurement
	ProtocolXNSIDP         = 22  // XEROX NS IDP
	ProtocolTRUNK1         = 23  // Trunk-1
	ProtocolTRUNK2         = 24  // Trunk-2
	ProtocolLEAF1          = 25  // Leaf-1
	ProtocolLEAF2          = 26  // Leaf-2
	ProtocolRDP            = 27  // Reliable Data Protocol
	ProtocolIRTP           = 28  // Internet Reliable Transaction
	ProtocolISOTP4         = 29  // ISO Transport Protocol Class 4
	ProtocolNETBLT         = 30  // Bulk Data Transfer Protocol
	ProtocolMFENSP         = 31  // MFE Network Services Protocol
	ProtocolMERITINP       = 32  // MERIT Internodal Protocol
	ProtocolDCCP           = 33  // Datagram Congestion Control Protocol
	Protocol3PC            = 34  // Third Party Connect Protocol
	ProtocolIDPR           = 35  // Inter-Domain Policy Routing Protocol
	ProtocolXTP            = 36  // XTP
	ProtocolDDP            = 37  // Datagram Delivery Protocol
	ProtocolIDPRCMTP       = 38  // IDPR Control Message Transport Proto
	ProtocolTPPP           = 39  // TP++ Transport Protocol
	ProtocolIL             = 40  // IL Transport Protocol
	ProtocolIPv6           = 41  // IPv6 encapsulation
	ProtocolSDRP           = 42  // Source Demand Routing Protocol
	ProtocolIPv6Route      = 43  // Routing Header for IPv6
	ProtocolIPv6Frag       = 44  // Fragment Header for IPv6
	ProtocolIDRP           = 45  // Inter-Domain Routing Protocol
	ProtocolRSVP           = 46  // Reservation Protocol
	ProtocolGRE            = 47  // Generic Routing Encapsulation
	ProtocolDSR            = 48  // Dynamic Source Routing Protocol
	ProtocolBNA            = 49  // BNA
	ProtocolESP            = 50  // Encap Security Payload
	ProtocolAH             = 51  // Authentication Header
	ProtocolINLSP          = 52  // Integrated Net Layer Security  TUBA
	ProtocolNARP           = 54  // NBMA Address Resolution Protocol
	ProtocolMOBILE         = 55  // IP Mobility
	ProtocolTLSP           = 56  // Transport Layer Security Protocol using Kryptonet key management
	ProtocolSKIP           = 57  // SKIP
	ProtocolIPv6ICMP       = 58  // ICMP for IPv6
	ProtocolIPv6NoNxt      = 59  // No Next Header for IPv6
	ProtocolIPv6Opts       = 60  // Destination Options for IPv6
	ProtocolCFTP           = 62  // CFTP
	ProtocolSATEXPAK       = 64  // SATNET and Backroom EXPAK
	ProtocolKRYPTOLAN      = 65  // Kryptolan
	ProtocolRVD            = 66  // MIT Remote Virtual Disk Protocol
	ProtocolIPPC           = 67  // Internet Pluribus Packet Core
	ProtocolSATMON         = 69  // SATNET Monitoring
	ProtocolVISA           = 70  // VISA Protocol
	ProtocolIPCV           = 71  // Internet Packet Core Utility
	ProtocolCPNX           = 72  // Computer Protocol Network Executive
	ProtocolCPHB           = 73  // Computer Protocol Heart Beat
	ProtocolWSN            = 74  // Wang Span Network
	ProtocolPVP            = 75  // Packet Video Protocol
	ProtocolBRSATMON       = 76  // Backroom SATNET Monitoring
	ProtocolSUNND          = 77  // SUN ND PROTOCOL-Temporary
	ProtocolWBMON          = 78  // WIDEBAND Monitoring
	ProtocolWBEXPAK        = 79  // WIDEBAND EXPAK
	ProtocolISOIP          = 80  // ISO Internet Protocol
	ProtocolVMTP           = 81  // VMTP
	ProtocolSECUREVMTP     = 82  // SECURE-VMTP
	ProtocolVINES          = 83  // VINES
	ProtocolTTP            = 84  // Transaction Transport Protocol
	ProtocolIPTM           = 84  // Internet Protocol Traffic Manager
	ProtocolNSFNETIGP      = 85  // NSFNET-IGP
	ProtocolDGP            = 86  // Dissimilar Gateway Protocol
	ProtocolTCF            = 87  // TCF
	ProtocolEIGRP          = 88  // EIGRP
	ProtocolOSPFIGP        = 89  // OSPFIGP
	ProtocolSpriteRPC      = 90  // Sprite RPC Protocol
	ProtocolLARP           = 91  // Locus Address Resolution Protocol
	ProtocolMTP            = 92  // Multicast Transport Protocol
	ProtocolAX25           = 93  // AX.25 Frames
	ProtocolIPIP           = 94  // IP-within-IP Encapsulation Protocol
	ProtocolSCCSP          = 96  // Semaphore Communications Sec. Pro.
	ProtocolETHERIP        = 97  // Ethernet-within-IP Encapsulation
	ProtocolENCAP          = 98  // Encapsulation Header
	ProtocolGMTP           = 100 // GMTP
	ProtocolIFMP           = 101 // Ipsilon Flow Management Protocol
	ProtocolPNNI           = 102 // PNNI over IP
	ProtocolPIM            = 103 // Protocol Independent Multicast
	ProtocolARIS           = 104 // ARIS
	ProtocolSCPS           = 105 // SCPS
	ProtocolQNX            = 106 // QNX
	ProtocolAN             = 107 // Active Networks
	ProtocolIPComp         = 108 // IP Payload Compression Protocol
	ProtocolSNP            = 109 // Sitara Networks Protocol
	ProtocolCompaqPeer     = 110 // Compaq Peer Protocol
	ProtocolIPXinIP        = 111 // IPX in IP
	ProtocolVRRP           = 112 // Virtual Router Redundancy Protocol
	ProtocolPGM            = 113 // PGM Reliable Transport Protocol
	ProtocolL2TP           = 115 // Layer Two Tunneling Protocol
	ProtocolDDX            = 116 // D-II Data Exchange (DDX)
	ProtocolIATP           = 117 // Interactive Agent Transfer Protocol
	ProtocolSTP            = 118 // Schedule Transfer Protocol
	ProtocolSRP            = 119 // SpectraLink Radio Protocol
	ProtocolUTI            = 120 // UTI
	ProtocolSMP            = 121 // Simple Message Protocol
	ProtocolPTP            = 123 // Performance Transparency Protocol
	ProtocolISIS           = 124 // ISIS over IPv4
	ProtocolFIRE           = 125 // FIRE
	ProtocolCRTP           = 126 // Combat Radio Transport Protocol
	ProtocolCRUDP          = 127 // Combat Radio User Datagram
	ProtocolSSCOPMCE       = 128 // SSCOPMCE
	ProtocolIPLT           = 129 // IPLT
	ProtocolSPS            = 130 // Secure Packet Shield
	ProtocolPIPE           = 131 // Private IP Encapsulation within IP
	ProtocolSCTP           = 132 // Stream Control Transmission Protocol
	ProtocolFC             = 133 // Fibre Channel
	ProtocolRSVPE2EIGNORE  = 134 // RSVP-E2E-IGNORE
	ProtocolMobilityHeader = 135 // Mobility Header
	ProtocolUDPLite        = 136 // UDPLite
	ProtocolMPLSinIP       = 137 // MPLS-in-IP
	ProtocolMANET          = 138 // MANET Protocols
	ProtocolHIP            = 139 // Host Identity Protocol
	ProtocolShim6          = 140 // Shim6 Protocol
	ProtocolWESP           = 141 // Wrapped Encapsulating Security Payload
	ProtocolROHC           = 142 // Robust Header Compression
	ProtocolReserved       = 255 // Reserved
)

// Address Family Numbers, Updated: 2016-10-25
const (
	AddrFamilyIPv4                          = 1     // IP (IP version 4)
	AddrFamilyIPv6                          = 2     // IP6 (IP version 6)
	AddrFamilyNSAP                          = 3     // NSAP
	AddrFamilyHDLC                          = 4     // HDLC (8-bit multidrop)
	AddrFamilyBBN1822                       = 5     // BBN 1822
	AddrFamily802                           = 6     // 802 (includes all 802 media plus Ethernet "canonical format")
	AddrFamilyE163                          = 7     // E.163
	AddrFamilyE164                          = 8     // E.164 (SMDS, Frame Relay, ATM)
	AddrFamilyF69                           = 9     // F.69 (Telex)
	AddrFamilyX121                          = 10    // X.121 (X.25, Frame Relay)
	AddrFamilyIPX                           = 11    // IPX
	AddrFamilyAppletalk                     = 12    // Appletalk
	AddrFamilyDecnetIV                      = 13    // Decnet IV
	AddrFamilyBanyanVines                   = 14    // Banyan Vines
	AddrFamilyE164withSubaddress            = 15    // E.164 with NSAP format subaddress
	AddrFamilyDNS                           = 16    // DNS (Domain Name System)
	AddrFamilyDistinguishedName             = 17    // Distinguished Name
	AddrFamilyASNumber                      = 18    // AS Number
	AddrFamilyXTPoverIPv4                   = 19    // XTP over IP version 4
	AddrFamilyXTPoverIPv6                   = 20    // XTP over IP version 6
	AddrFamilyXTPnativemodeXTP              = 21    // XTP native mode XTP
	AddrFamilyFibreChannelWorldWidePortName = 22    // Fibre Channel World-Wide Port Name
	AddrFamilyFibreChannelWorldWideNodeName = 23    // Fibre Channel World-Wide Node Name
	AddrFamilyGWID                          = 24    // GWID
	AddrFamilyL2VPN                         = 25    // AFI for L2VPN information
	AddrFamilyMPLSTPSectionEndpointID       = 26    // MPLS-TP Section Endpoint Identifier
	AddrFamilyMPLSTPLSPEndpointID           = 27    // MPLS-TP LSP Endpoint Identifier
	AddrFamilyMPLSTPPseudowireEndpointID    = 28    // MPLS-TP Pseudowire Endpoint Identifier
	AddrFamilyMTIPv4                        = 29    // MT IP: Multi-Topology IP version 4
	AddrFamilyMTIPv6                        = 30    // MT IPv6: Multi-Topology IP version 6
	AddrFamilyEIGRPCommonServiceFamily      = 16384 // EIGRP Common Service Family
	AddrFamilyEIGRPIPv4ServiceFamily        = 16385 // EIGRP IPv4 Service Family
	AddrFamilyEIGRPIPv6ServiceFamily        = 16386 // EIGRP IPv6 Service Family
	AddrFamilyLISPCanonicalAddressFormat    = 16387 // LISP Canonical Address Format (LCAF)
	AddrFamilyBGPLS                         = 16388 // BGP-LS
	AddrFamily48bitMAC                      = 16389 // 48-bit MAC
	AddrFamily64bitMAC                      = 16390 // 64-bit MAC
	AddrFamilyOUI                           = 16391 // OUI
	AddrFamilyMACFinal24bits                = 16392 // MAC/24
	AddrFamilyMACFinal40bits                = 16393 // MAC/40
	AddrFamilyIPv6Initial64bits             = 16394 // IPv6/64
	AddrFamilyRBridgePortID                 = 16395 // RBridge Port ID
	AddrFamilyTRILLNickname                 = 16396 // TRILL Nickname
)


text:
// Copyright 2015 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 timeseries implements a time series structure for stats collection.
package timeseries // import "golang.org/x/net/internal/timeseries"

import (
	"fmt"
	"log"
	"time"
)

const (
	timeSeriesNumBuckets       = 64
	minuteHourSeriesNumBuckets = 60
)

var timeSeriesResolutions = []time.Duration{
	1 * time.Second,
	10 * time.Second,
	1 * time.Minute,
	10 * time.Minute,
	1 * time.Hour,
	6 * time.Hour,
	24 * time.Hour,          // 1 day
	7 * 24 * time.Hour,      // 1 week
	4 * 7 * 24 * time.Hour,  // 4 weeks
	16 * 7 * 24 * time.Hour, // 16 weeks
}

var minuteHourSeriesResolutions = []time.Duration{
	1 * time.Second,
	1 * time.Minute,
}

// An Observable is a kind of data that can be aggregated in a time series.
type Observable interface {
	Multiply(ratio float64)    // Multiplies the data in self by a given ratio
	Add(other Observable)      // Adds the data from a different observation to self
	Clear()                    // Clears the observation so it can be reused.
	CopyFrom(other Observable) // Copies the contents of a given observation to self
}

// Float attaches the methods of Observable to a float64.
type Float float64

// NewFloat returns a Float.
func NewFloat() Observable {
	f := Float(0)
	return &f
}

// String returns the float as a string.
func (f *Float) String() string { return fmt.Sprintf("%g", f.Value()) }

// Value returns the float's value.
func (f *Float) Value() float64 { return float64(*f) }

func (f *Float) Multiply(ratio float64) { *f *= Float(ratio) }

func (f *Float) Add(other Observable) {
	o := other.(*Float)
	*f += *o
}

func (f *Float) Clear() { *f = 0 }

func (f *Float) CopyFrom(other Observable) {
	o := other.(*Float)
	*f = *o
}

// A Clock tells the current time.
type Clock interface {
	Time() time.Time
}

type defaultClock int

var defaultClockInstance defaultClock

func (defaultClock) Time() time.Time { return time.Now() }

// Information kept per level. Each level consists of a circular list of
// observations. The start of the level may be derived from end and the
// len(buckets) * sizeInMillis.
type tsLevel struct {
	oldest   int               // index to oldest bucketed Observable
	newest   int               // index to newest bucketed Observable
	end      time.Time         // end timestamp for this level
	size     time.Duration     // duration of the bucketed Observable
	buckets  []Observable      // collections of observations
	provider func() Observable // used for creating new Observable
}

func (l *tsLevel) Clear() {
	l.oldest = 0
	l.newest = len(l.buckets) - 1
	l.end = time.Time{}
	for i := range l.buckets {
		if l.buckets[i] != nil {
			l.buckets[i].Clear()
			l.buckets[i] = nil
		}
	}
}

func (l *tsLevel) InitLevel(size time.Duration, numBuckets int, f func() Observable) {
	l.size = size
	l.provider = f
	l.buckets = make([]Observable, numBuckets)
}

// Keeps a sequence of levels. Each level is responsible for storing data at
// a given resolution. For example, the first level stores data at a one
// minute resolution while the second level stores data at a one hour
// resolution.

// Each level is represented by a sequence of buckets. Each bucket spans an
// interval equal to the resolution of the level. New observations are added
// to the last bucket.
type timeSeries struct {
	provider    func() Observable // make more Observable
	numBuckets  int               // number of buckets in each level
	levels      []*tsLevel        // levels of bucketed Observable
	lastAdd     time.Time         // time of last Observable tracked
	total       Observable        // convenient aggregation of all Observable
	clock       Clock             // Clock for getting current time
	pending     Observable        // observations not yet bucketed
	pendingTime time.Time         // what time are we keeping in pending
	dirty       bool              // if there are pending observations
}

// init initializes a level according to the supplied criteria.
func (ts *timeSeries) init(resolutions []time.Duration, f func() Observable, numBuckets int, clock Clock) {
	ts.provider = f
	ts.numBuckets = numBuckets
	ts.clock = clock
	ts.levels = make([]*tsLevel, len(resolutions))

	for i := range resolutions {
		if i > 0 && resolutions[i-1] >= resolutions[i] {
			log.Print("timeseries: resolutions must be monotonically increasing")
			break
		}
		newLevel := new(tsLevel)
		newLevel.InitLevel(resolutions[i], ts.numBuckets, ts.provider)
		ts.levels[i] = newLevel
	}

	ts.Clear()
}

// Clear removes all observations from the time series.
func (ts *timeSeries) Clear() {
	ts.lastAdd = time.Time{}
	ts.total = ts.resetObservation(ts.total)
	ts.pending = ts.resetObservation(ts.pending)
	ts.pendingTime = time.Time{}
	ts.dirty = false

	for i := range ts.levels {
		ts.levels[i].Clear()
	}
}

// Add records an observation at the current time.
func (ts *timeSeries) Add(observation Observable) {
	ts.AddWithTime(observation, ts.clock.Time())
}

// AddWithTime records an observation at the specified time.
func (ts *timeSeries) AddWithTime(observation Observable, t time.Time) {

	smallBucketDuration := ts.levels[0].size

	if t.After(ts.lastAdd) {
		ts.lastAdd = t
	}

	if t.After(ts.pendingTime) {
		ts.advance(t)
		ts.mergePendingUpdates()
		ts.pendingTime = ts.levels[0].end
		ts.pending.CopyFrom(observation)
		ts.dirty = true
	} else if t.After(ts.pendingTime.Add(-1 * smallBucketDuration)) {
		// The observation is close enough to go into the pending bucket.
		// This compensates for clock skewing and small scheduling delays
		// by letting the update stay in the fast path.
		ts.pending.Add(observation)
		ts.dirty = true
	} else {
		ts.mergeValue(observation, t)
	}
}

// mergeValue inserts the observation at the specified time in the past into all levels.
func (ts *timeSeries) mergeValue(observation Observable, t time.Time) {
	for _, level := range ts.levels {
		index := (ts.numBuckets - 1) - int(level.end.Sub(t)/level.size)
		if 0 <= index && index < ts.numBuckets {
			bucketNumber := (level.oldest + index) % ts.numBuckets
			if level.buckets[bucketNumber] == nil {
				level.buckets[bucketNumber] = level.provider()
			}
			level.buckets[bucketNumber].Add(observation)
		}
	}
	ts.total.Add(observation)
}

// mergePendingUpdates applies the pending updates into all levels.
func (ts *timeSeries) mergePendingUpdates() {
	if ts.dirty {
		ts.mergeValue(ts.pending, ts.pendingTime)
		ts.pending = ts.resetObservation(ts.pending)
		ts.dirty = false
	}
}

// advance cycles the buckets at each level until the latest bucket in
// each level can hold the time specified.
func (ts *timeSeries) advance(t time.Time) {
	if !t.After(ts.levels[0].end) {
		return
	}
	for i := 0; i < len(ts.levels); i++ {
		level := ts.levels[i]
		if !level.end.Before(t) {
			break
		}

		// If the time is sufficiently far, just clear the level and advance
		// directly.
		if !t.Before(level.end.Add(level.size * time.Duration(ts.numBuckets))) {
			for _, b := range level.buckets {
				ts.resetObservation(b)
			}
			level.end = time.Unix(0, (t.UnixNano()/level.size.Nanoseconds())*level.size.Nanoseconds())
		}

		for t.After(level.end) {
			level.end = level.end.Add(level.size)
			level.newest = level.oldest
			level.oldest = (level.oldest + 1) % ts.numBuckets
			ts.resetObservation(level.buckets[level.newest])
		}

		t = level.end
	}
}

// Latest returns the sum of the num latest buckets from the level.
func (ts *timeSeries) Latest(level, num int) Observable {
	now := ts.clock.Time()
	if ts.levels[0].end.Before(now) {
		ts.advance(now)
	}

	ts.mergePendingUpdates()

	result := ts.provider()
	l := ts.levels[level]
	index := l.newest

	for i := 0; i < num; i++ {
		if l.buckets[index] != nil {
			result.Add(l.buckets[index])
		}
		if index == 0 {
			index = ts.numBuckets
		}
		index--
	}

	return result
}

// LatestBuckets returns a copy of the num latest buckets from level.
func (ts *timeSeries) LatestBuckets(level, num int) []Observable {
	if level < 0 || level > len(ts.levels) {
		log.Print("timeseries: bad level argument: ", level)
		return nil
	}
	if num < 0 || num >= ts.numBuckets {
		log.Print("timeseries: bad num argument: ", num)
		return nil
	}

	results := make([]Observable, num)
	now := ts.clock.Time()
	if ts.levels[0].end.Before(now) {
		ts.advance(now)
	}

	ts.mergePendingUpdates()

	l := ts.levels[level]
	index := l.newest

	for i := 0; i < num; i++ {
		result := ts.provider()
		results[i] = result
		if l.buckets[index] != nil {
			result.CopyFrom(l.buckets[index])
		}

		if index == 0 {
			index = ts.numBuckets
		}
		index -= 1
	}
	return results
}

// ScaleBy updates observations by scaling by factor.
func (ts *timeSeries) ScaleBy(factor float64) {
	for _, l := range ts.levels {
		for i := 0; i < ts.numBuckets; i++ {
			l.buckets[i].Multiply(factor)
		}
	}

	ts.total.Multiply(factor)
	ts.pending.Multiply(factor)
}

// Range returns the sum of observations added over the specified time range.
// If start or finish times don't fall on bucket boundaries of the same
// level, then return values are approximate answers.
func (ts *timeSeries) Range(start, finish time.Time) Observable {
	return ts.ComputeRange(start, finish, 1)[0]
}

// Recent returns the sum of observations from the last delta.
func (ts *timeSeries) Recent(delta time.Duration) Observable {
	now := ts.clock.Time()
	return ts.Range(now.Add(-delta), now)
}

// Total returns the total of all observations.
func (ts *timeSeries) Total() Observable {
	ts.mergePendingUpdates()
	return ts.total
}

// ComputeRange computes a specified number of values into a slice using
// the observations recorded over the specified time period. The return
// values are approximate if the start or finish times don't fall on the
// bucket boundaries at the same level or if the number of buckets spanning
// the range is not an integral multiple of num.
func (ts *timeSeries) ComputeRange(start, finish time.Time, num int) []Observable {
	if start.After(finish) {
		log.Printf("timeseries: start > finish, %v>%v", start, finish)
		return nil
	}

	if num < 0 {
		log.Printf("timeseries: num < 0, %v", num)
		return nil
	}

	results := make([]Observable, num)

	for _, l := range ts.levels {
		if !start.Before(l.end.Add(-l.size * time.Duration(ts.numBuckets))) {
			ts.extract(l, start, finish, num, results)
			return results
		}
	}

	// Failed to find a level that covers the desired range. So just
	// extract from the last level, even if it doesn't cover the entire
	// desired range.
	ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results)

	return results
}

// RecentList returns the specified number of values in slice over the most
// recent time period of the specified range.
func (ts *timeSeries) RecentList(delta time.Duration, num int) []Observable {
	if delta < 0 {
		return nil
	}
	now := ts.clock.Time()
	return ts.ComputeRange(now.Add(-delta), now, num)
}

// extract returns a slice of specified number of observations from a given
// level over a given range.
func (ts *timeSeries) extract(l *tsLevel, start, finish time.Time, num int, results []Observable) {
	ts.mergePendingUpdates()

	srcInterval := l.size
	dstInterval := finish.Sub(start) / time.Duration(num)
	dstStart := start
	srcStart := l.end.Add(-srcInterval * time.Duration(ts.numBuckets))

	srcIndex := 0

	// Where should scanning start?
	if dstStart.After(srcStart) {
		advance := dstStart.Sub(srcStart) / srcInterval
		srcIndex += int(advance)
		srcStart = srcStart.Add(advance * srcInterval)
	}

	// The i'th value is computed as show below.
	// interval = (finish/start)/num
	// i'th value = sum of observation in range
	//   [ start + i       * interval,
	//     start + (i + 1) * interval )
	for i := 0; i < num; i++ {
		results[i] = ts.resetObservation(results[i])
		dstEnd := dstStart.Add(dstInterval)
		for srcIndex < ts.numBuckets && srcStart.Before(dstEnd) {
			srcEnd := srcStart.Add(srcInterval)
			if srcEnd.After(ts.lastAdd) {
				srcEnd = ts.lastAdd
			}

			if !srcEnd.Before(dstStart) {
				srcValue := l.buckets[(srcIndex+l.oldest)%ts.numBuckets]
				if !srcStart.Before(dstStart) && !srcEnd.After(dstEnd) {
					// dst completely contains src.
					if srcValue != nil {
						results[i].Add(srcValue)
					}
				} else {
					// dst partially overlaps src.
					overlapStart := maxTime(srcStart, dstStart)
					overlapEnd := minTime(srcEnd, dstEnd)
					base := srcEnd.Sub(srcStart)
					fraction := overlapEnd.Sub(overlapStart).Seconds() / base.Seconds()

					used := ts.provider()
					if srcValue != nil {
						used.CopyFrom(srcValue)
					}
					used.Multiply(fraction)
					results[i].Add(used)
				}

				if srcEnd.After(dstEnd) {
					break
				}
			}
			srcIndex++
			srcStart = srcStart.Add(srcInterval)
		}
		dstStart = dstStart.Add(dstInterval)
	}
}

// resetObservation clears the content so the struct may be reused.
func (ts *timeSeries) resetObservation(observation Observable) Observable {
	if observation == nil {
		observation = ts.provider()
	} else {
		observation.Clear()
	}
	return observation
}

// TimeSeries tracks data at granularities from 1 second to 16 weeks.
type TimeSeries struct {
	timeSeries
}

// NewTimeSeries creates a new TimeSeries using the function provided for creating new Observable.
func NewTimeSeries(f func() Observable) *TimeSeries {
	return NewTimeSeriesWithClock(f, defaultClockInstance)
}

// NewTimeSeriesWithClock creates a new TimeSeries using the function provided for creating new Observable and the clock for
// assigning timestamps.
func NewTimeSeriesWithClock(f func() Observable, clock Clock) *TimeSeries {
	ts := new(TimeSeries)
	ts.timeSeries.init(timeSeriesResolutions, f, timeSeriesNumBuckets, clock)
	return ts
}

// MinuteHourSeries tracks data at granularities of 1 minute and 1 hour.
type MinuteHourSeries struct {
	timeSeries
}

// NewMinuteHourSeries creates a new MinuteHourSeries using the function provided for creating new Observable.
func NewMinuteHourSeries(f func() Observable) *MinuteHourSeries {
	return NewMinuteHourSeriesWithClock(f, defaultClockInstance)
}

// NewMinuteHourSeriesWithClock creates a new MinuteHourSeries using the function provided for creating new Observable and the clock for
// assigning timestamps.
func NewMinuteHourSeriesWithClock(f func() Observable, clock Clock) *MinuteHourSeries {
	ts := new(MinuteHourSeries)
	ts.timeSeries.init(minuteHourSeriesResolutions, f,
		minuteHourSeriesNumBuckets, clock)
	return ts
}

func (ts *MinuteHourSeries) Minute() Observable {
	return ts.timeSeries.Latest(0, 60)
}

func (ts *MinuteHourSeries) Hour() Observable {
	return ts.timeSeries.Latest(1, 60)
}

func minTime(a, b time.Time) time.Time {
	if a.Before(b) {
		return a
	}
	return b
}

func maxTime(a, b time.Time) time.Time {
	if a.After(b) {
		return a
	}
	return b
}


text:
// Copyright 2015 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 timeseries

import (
	"math"
	"testing"
	"time"
)

func isNear(x *Float, y float64, tolerance float64) bool {
	return math.Abs(x.Value()-y) < tolerance
}

func isApproximate(x *Float, y float64) bool {
	return isNear(x, y, 1e-2)
}

func checkApproximate(t *testing.T, o Observable, y float64) {
	x := o.(*Float)
	if !isApproximate(x, y) {
		t.Errorf("Wanted %g, got %g", y, x.Value())
	}
}

func checkNear(t *testing.T, o Observable, y, tolerance float64) {
	x := o.(*Float)
	if !isNear(x, y, tolerance) {
		t.Errorf("Wanted %g +- %g, got %g", y, tolerance, x.Value())
	}
}

var baseTime = time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)

func tu(s int64) time.Time {
	return baseTime.Add(time.Duration(s) * time.Second)
}

func tu2(s int64, ns int64) time.Time {
	return baseTime.Add(time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond)
}

func TestBasicTimeSeries(t *testing.T) {
	ts := NewTimeSeries(NewFloat)
	fo := new(Float)
	*fo = Float(10)
	ts.AddWithTime(fo, tu(1))
	ts.AddWithTime(fo, tu(1))
	ts.AddWithTime(fo, tu(1))
	ts.AddWithTime(fo, tu(1))
	checkApproximate(t, ts.Range(tu(0), tu(1)), 40)
	checkApproximate(t, ts.Total(), 40)
	ts.AddWithTime(fo, tu(3))
	ts.AddWithTime(fo, tu(3))
	ts.AddWithTime(fo, tu(3))
	checkApproximate(t, ts.Range(tu(0), tu(2)), 40)
	checkApproximate(t, ts.Range(tu(2), tu(4)), 30)
	checkApproximate(t, ts.Total(), 70)
	ts.AddWithTime(fo, tu(1))
	ts.AddWithTime(fo, tu(1))
	checkApproximate(t, ts.Range(tu(0), tu(2)), 60)
	checkApproximate(t, ts.Range(tu(2), tu(4)), 30)
	checkApproximate(t, ts.Total(), 90)
	*fo = Float(100)
	ts.AddWithTime(fo, tu(100))
	checkApproximate(t, ts.Range(tu(99), tu(100)), 100)
	checkApproximate(t, ts.Range(tu(0), tu(4)), 36)
	checkApproximate(t, ts.Total(), 190)
	*fo = Float(10)
	ts.AddWithTime(fo, tu(1))
	ts.AddWithTime(fo, tu(1))
	checkApproximate(t, ts.Range(tu(0), tu(4)), 44)
	checkApproximate(t, ts.Range(tu(37), tu2(100, 100e6)), 100)
	checkApproximate(t, ts.Range(tu(50), tu2(100, 100e6)), 100)
	checkApproximate(t, ts.Range(tu(99), tu2(100, 100e6)), 100)
	checkApproximate(t, ts.Total(), 210)

	for i, l := range ts.ComputeRange(tu(36), tu(100), 64) {
		if i == 63 {
			checkApproximate(t, l, 100)
		} else {
			checkApproximate(t, l, 0)
		}
	}

	checkApproximate(t, ts.Range(tu(0), tu(100)), 210)
	checkApproximate(t, ts.Range(tu(10), tu(100)), 100)

	for i, l := range ts.ComputeRange(tu(0), tu(100), 100) {
		if i < 10 {
			checkApproximate(t, l, 11)
		} else if i >= 90 {
			checkApproximate(t, l, 10)
		} else {
			checkApproximate(t, l, 0)
		}
	}
}

func TestFloat(t *testing.T) {
	f := Float(1)
	if g, w := f.String(), "1"; g != w {
		t.Errorf("Float(1).String = %q; want %q", g, w)
	}
	f2 := Float(2)
	var o Observable = &f2
	f.Add(o)
	if g, w := f.Value(), 3.0; g != w {
		t.Errorf("Float post-add = %v; want %v", g, w)
	}
	f.Multiply(2)
	if g, w := f.Value(), 6.0; g != w {
		t.Errorf("Float post-multiply = %v; want %v", g, w)
	}
	f.Clear()
	if g, w := f.Value(), 0.0; g != w {
		t.Errorf("Float post-clear = %v; want %v", g, w)
	}
	f.CopyFrom(&f2)
	if g, w := f.Value(), 2.0; g != w {
		t.Errorf("Float post-CopyFrom = %v; want %v", g, w)
	}
}

type mockClock struct {
	time time.Time
}

func (m *mockClock) Time() time.Time { return m.time }
func (m *mockClock) Set(t time.Time) { m.time = t }

const buckets = 6

var testResolutions = []time.Duration{
	10 * time.Second,  // level holds one minute of observations
	100 * time.Second, // level holds ten minutes of observations
	10 * time.Minute,  // level holds one hour of observations
}

// TestTimeSeries uses a small number of buckets to force a higher
// error rate on approximations from the timeseries.
type TestTimeSeries struct {
	timeSeries
}

func TestExpectedErrorRate(t *testing.T) {
	ts := new(TestTimeSeries)
	fake := new(mockClock)
	fake.Set(time.Now())
	ts.timeSeries.init(testResolutions, NewFloat, buckets, fake)
	for i := 1; i <= 61*61; i++ {
		fake.Set(fake.Time().Add(1 * time.Second))
		ob := Float(1)
		ts.AddWithTime(&ob, fake.Time())

		// The results should be accurate within one missing bucket (1/6) of the observations recorded.
		checkNear(t, ts.Latest(0, buckets), min(float64(i), 60), 10)
		checkNear(t, ts.Latest(1, buckets), min(float64(i), 600), 100)
		checkNear(t, ts.Latest(2, buckets), min(float64(i), 3600), 600)
	}
}

func min(a, b float64) float64 {
	if a < b {
		return a
	}
	return b
}


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

package socket

const (
	sysAF_UNSPEC = 0x0
	sysAF_INET   = 0x2
	sysAF_INET6  = 0xa

	sysSOCK_RAW = 0x3
)

type iovec struct {
	Base *byte
	Len  uint32
}

type msghdr struct {
	Name       *byte
	Namelen    uint32
	Iov        *iovec
	Iovlen     uint32
	Control    *byte
	Controllen uint32
	Flags      int32
}

type mmsghdr struct {
	Hdr msghdr
	Len uint32
}

type cmsghdr struct {
	Len   uint32
	Level int32
	Type  int32
}

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

type sockaddrInet6 struct {
	Family   uint16
	Port     uint16
	Flowinfo uint32
	Addr     [16]byte /* in6_addr */
	Scope_id uint32
}

const (
	sizeofIovec   = 0x8
	sizeofMsghdr  = 0x1c
	sizeofMmsghdr = 0x20
	sizeofCmsghdr = 0xc

	sizeofSockaddrInet  = 0x10
	sizeofSockaddrInet6 = 0x1c
)


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

package socket

const (
	sysAF_UNSPEC = 0x0
	sysAF_INET   = 0x2
	sysAF_INET6  = 0x18

	sysSOCK_RAW = 0x3
)

type iovec struct {
	Base *byte
	Len  uint32
}

type msghdr struct {
	Name       *byte
	Namelen    uint32
	Iov        *iovec
	Iovlen     int32
	Control    *byte
	Controllen uint32
	Flags      int32
}

type mmsghdr struct {
	Hdr msghdr
	Len uint32
}

type cmsghdr struct {
	Len   uint32
	Level int32
	Type  int32
}

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

type sockaddrInet6 struct {
	Len      uint8
	Family   uint8
	Port     uint16
	Flowinfo uint32
	Addr     [16]byte /* in6_addr */
	Scope_id uint32
}

const (
	sizeofIovec   = 0x8
	sizeofMsghdr  = 0x1c
	sizeofMmsghdr = 0x20
	sizeofCmsghdr = 0xc

	sizeofSockaddrInet  = 0x10
	sizeofSockaddrInet6 = 0x1c
)


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.

#include "textflag.h"

TEXT	·socketcall(SB),NOSPLIT,$0-72
	JMP	syscall·socketcall(SB)

TEXT	·rawsocketcall(SB),NOSPLIT,$0-72
	JMP	syscall·rawsocketcall(SB)