summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/miekg/dns/internal/socket
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/miekg/dns/internal/socket')
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr.go7
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go20
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go20
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go13
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/controlmessage.go118
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go103
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/socket.go4
-rw-r--r--vendor/github.com/miekg/dns/internal/socket/sys.go14
8 files changed, 299 insertions, 0 deletions
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr.go
new file mode 100644
index 000000000..62f2d2f74
--- /dev/null
+++ b/vendor/github.com/miekg/dns/internal/socket/cmsghdr.go
@@ -0,0 +1,7 @@
+// +build linux
+
+package socket
+
+func (h *cmsghdr) len() int { return int(h.Len) }
+func (h *cmsghdr) lvl() int { return int(h.Level) }
+func (h *cmsghdr) typ() int { return int(h.Type) }
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go
new file mode 100644
index 000000000..e92e85800
--- /dev/null
+++ b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go
@@ -0,0 +1,20 @@
+// +build arm mips mipsle 386
+// +build linux
+
+package socket
+
+type cmsghdr struct {
+ Len uint32
+ Level int32
+ Type int32
+}
+
+const (
+ sizeofCmsghdr = 0xc
+)
+
+func (h *cmsghdr) set(l, lvl, typ int) {
+ h.Len = uint32(l)
+ h.Level = int32(lvl)
+ h.Type = int32(typ)
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go
new file mode 100644
index 000000000..ddfc9e09a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go
@@ -0,0 +1,20 @@
+// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
+// +build linux
+
+package socket
+
+type cmsghdr struct {
+ Len uint64
+ Level int32
+ Type int32
+}
+
+const (
+ sizeofCmsghdr = 0x10
+)
+
+func (h *cmsghdr) set(l, lvl, typ int) {
+ h.Len = uint64(l)
+ h.Level = int32(lvl)
+ h.Type = int32(typ)
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go
new file mode 100644
index 000000000..8078487c8
--- /dev/null
+++ b/vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go
@@ -0,0 +1,13 @@
+// +build !linux
+
+package socket
+
+type cmsghdr struct{}
+
+const sizeofCmsghdr = 0
+
+func (h *cmsghdr) len() int { return 0 }
+func (h *cmsghdr) lvl() int { return 0 }
+func (h *cmsghdr) typ() int { return 0 }
+
+func (h *cmsghdr) set(l, lvl, typ int) {}
diff --git a/vendor/github.com/miekg/dns/internal/socket/controlmessage.go b/vendor/github.com/miekg/dns/internal/socket/controlmessage.go
new file mode 100644
index 000000000..3176e9602
--- /dev/null
+++ b/vendor/github.com/miekg/dns/internal/socket/controlmessage.go
@@ -0,0 +1,118 @@
+package socket
+
+import (
+ "errors"
+ "unsafe"
+)
+
+func controlHeaderLen() int {
+ return roundup(sizeofCmsghdr)
+}
+
+func controlMessageLen(dataLen int) int {
+ return roundup(sizeofCmsghdr) + dataLen
+}
+
+// returns the whole length of control message.
+func ControlMessageSpace(dataLen int) int {
+ return roundup(sizeofCmsghdr) + roundup(dataLen)
+}
+
+// A ControlMessage represents the head message in a stream of control
+// messages.
+//
+// A control message comprises of a header, data and a few padding
+// fields to conform to the interface to the kernel.
+//
+// See RFC 3542 for further information.
+type ControlMessage []byte
+
+// Data returns the data field of the control message at the head.
+func (m ControlMessage) Data(dataLen int) []byte {
+ l := controlHeaderLen()
+ if len(m) < l || len(m) < l+dataLen {
+ return nil
+ }
+ return m[l : l+dataLen]
+}
+
+// ParseHeader parses and returns the header fields of the control
+// message at the head.
+func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
+ l := controlHeaderLen()
+ if len(m) < l {
+ return 0, 0, 0, errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
+}
+
+// Next returns the control message at the next.
+func (m ControlMessage) Next(dataLen int) ControlMessage {
+ l := ControlMessageSpace(dataLen)
+ if len(m) < l {
+ return nil
+ }
+ return m[l:]
+}
+
+// MarshalHeader marshals the header fields of the control message at
+// the head.
+func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
+ if len(m) < controlHeaderLen() {
+ return errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ h.set(controlMessageLen(dataLen), lvl, typ)
+ return nil
+}
+
+// Marshal marshals the control message at the head, and returns the next
+// control message.
+func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
+ l := len(data)
+ if len(m) < ControlMessageSpace(l) {
+ return nil, errors.New("short message")
+ }
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ h.set(controlMessageLen(l), lvl, typ)
+ if l > 0 {
+ copy(m.Data(l), data)
+ }
+ return m.Next(l), nil
+}
+
+// Parse parses as a single or multiple control messages.
+func (m ControlMessage) Parse() ([]ControlMessage, error) {
+ var ms []ControlMessage
+ for len(m) >= controlHeaderLen() {
+ h := (*cmsghdr)(unsafe.Pointer(&m[0]))
+ l := h.len()
+ if l <= 0 {
+ return nil, errors.New("invalid header length")
+ }
+ if uint64(l) < uint64(controlHeaderLen()) {
+ return nil, errors.New("invalid message length")
+ }
+ if uint64(l) > uint64(len(m)) {
+ return nil, errors.New("short buffer")
+ }
+ ms = append(ms, ControlMessage(m[:l]))
+ ll := l - controlHeaderLen()
+ if len(m) >= ControlMessageSpace(ll) {
+ m = m[ControlMessageSpace(ll):]
+ } else {
+ m = m[controlMessageLen(ll):]
+ }
+ }
+ return ms, nil
+}
+
+// NewControlMessage returns a new stream of control messages.
+func NewControlMessage(dataLen []int) ControlMessage {
+ var l int
+ for i := range dataLen {
+ l += ControlMessageSpace(dataLen[i])
+ }
+ return make([]byte, l)
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go b/vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go
new file mode 100644
index 000000000..e9fff4d45
--- /dev/null
+++ b/vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go
@@ -0,0 +1,103 @@
+// +build linux
+
+package socket
+
+import (
+ "bytes"
+ "testing"
+)
+
+type mockControl struct {
+ Level int
+ Type int
+ Data []byte
+}
+
+func TestControlMessage(t *testing.T) {
+ for _, tt := range []struct {
+ cs []mockControl
+ }{
+ {
+ []mockControl{
+ {Level: 1, Type: 1},
+ },
+ },
+ {
+ []mockControl{
+ {Level: 2, Type: 2, Data: []byte{0xfe}},
+ },
+ },
+ {
+ []mockControl{
+ {Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
+ },
+ },
+ {
+ []mockControl{
+ {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
+ },
+ },
+ {
+ []mockControl{
+ {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
+ {Level: 2, Type: 2, Data: []byte{0xfe}},
+ },
+ },
+ } {
+ var w []byte
+ var tailPadLen int
+ mm := NewControlMessage([]int{0})
+ for i, c := range tt.cs {
+ m := NewControlMessage([]int{len(c.Data)})
+ l := len(m) - len(mm)
+ if i == len(tt.cs)-1 && l > len(c.Data) {
+ tailPadLen = l - len(c.Data)
+ }
+ w = append(w, m...)
+ }
+
+ var err error
+ ww := make([]byte, len(w))
+ copy(ww, w)
+ m := ControlMessage(ww)
+ for _, c := range tt.cs {
+ if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
+ t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
+ }
+ copy(m.Data(len(c.Data)), c.Data)
+ m = m.Next(len(c.Data))
+ }
+ m = ControlMessage(w)
+ for _, c := range tt.cs {
+ m, err = m.Marshal(c.Level, c.Type, c.Data)
+ if err != nil {
+ t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
+ }
+ }
+ if !bytes.Equal(ww, w) {
+ t.Fatalf("got %#v; want %#v", ww, w)
+ }
+
+ ws := [][]byte{w}
+ if tailPadLen > 0 {
+ // Test a message with no tail padding.
+ nopad := w[:len(w)-tailPadLen]
+ ws = append(ws, [][]byte{nopad}...)
+ }
+ for _, w := range ws {
+ ms, err := ControlMessage(w).Parse()
+ if err != nil {
+ t.Fatalf("(%v).Parse() = %v", tt.cs, err)
+ }
+ for i, m := range ms {
+ lvl, typ, dataLen, err := m.ParseHeader()
+ if err != nil {
+ t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
+ }
+ if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
+ t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/miekg/dns/internal/socket/socket.go b/vendor/github.com/miekg/dns/internal/socket/socket.go
new file mode 100644
index 000000000..edb58e29a
--- /dev/null
+++ b/vendor/github.com/miekg/dns/internal/socket/socket.go
@@ -0,0 +1,4 @@
+// Package socket contains ControlMessage parsing code from
+// golang.org/x/net/internal/socket. Instead of supporting all possible
+// architectures, we're only supporting linux 32/64 bit.
+package socket
diff --git a/vendor/github.com/miekg/dns/internal/socket/sys.go b/vendor/github.com/miekg/dns/internal/socket/sys.go
new file mode 100644
index 000000000..2f3f5cfed
--- /dev/null
+++ b/vendor/github.com/miekg/dns/internal/socket/sys.go
@@ -0,0 +1,14 @@
+package socket
+
+import "unsafe"
+
+var (
+ kernelAlign = func() int {
+ var p uintptr
+ return int(unsafe.Sizeof(p))
+ }()
+)
+
+func roundup(l int) int {
+ return (l + kernelAlign - 1) & ^(kernelAlign - 1)
+}