mirror of
https://github.com/golang/net.git
synced 2026-03-31 10:27:08 +09:00
go.net/ipv4: add support for dragonfly, enable IP_PKTINFO on darwin
This CL adds support for dragonfly and IP_PKTINFO support for darwin with less dependency on syscall package. Update golang/go#7175 Fixes golang/go#7172. LGTM=iant R=golang-codereviews, gobot, iant CC=golang-codereviews https://golang.org/cl/97800043
This commit is contained in:
@@ -2,13 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -26,62 +25,92 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||
opt.clear(FlagTTL)
|
||||
}
|
||||
}
|
||||
if cf&FlagDst != 0 {
|
||||
if err := setIPv4ReceiveDestinationAddress(fd, on); err != nil {
|
||||
return err
|
||||
if supportsPacketInfo {
|
||||
if cf&(FlagSrc|FlagDst|FlagInterface) != 0 {
|
||||
if err := setIPv4PacketInfo(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(cf & (FlagSrc | FlagDst | FlagInterface))
|
||||
} else {
|
||||
opt.clear(cf & (FlagSrc | FlagDst | FlagInterface))
|
||||
|
||||
}
|
||||
}
|
||||
if on {
|
||||
opt.set(FlagDst)
|
||||
} else {
|
||||
opt.clear(FlagDst)
|
||||
} else {
|
||||
if cf&FlagDst != 0 {
|
||||
if err := setIPv4ReceiveDestinationAddress(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(FlagDst)
|
||||
} else {
|
||||
opt.clear(FlagDst)
|
||||
}
|
||||
}
|
||||
}
|
||||
if cf&FlagInterface != 0 {
|
||||
if err := setIPv4ReceiveInterface(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(FlagInterface)
|
||||
} else {
|
||||
opt.clear(FlagInterface)
|
||||
if cf&FlagInterface != 0 {
|
||||
if err := setIPv4ReceiveInterface(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(FlagInterface)
|
||||
} else {
|
||||
opt.clear(FlagInterface)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||
opt.Lock()
|
||||
defer opt.Unlock()
|
||||
l, off := 0, 0
|
||||
func (opt *rawOpt) oobLen() (l int) {
|
||||
if opt.isset(FlagTTL) {
|
||||
l += syscall.CmsgSpace(1)
|
||||
}
|
||||
if opt.isset(FlagDst) {
|
||||
l += syscall.CmsgSpace(net.IPv4len)
|
||||
if supportsPacketInfo {
|
||||
if opt.isset(FlagSrc | FlagDst | FlagInterface) {
|
||||
l += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
} else {
|
||||
if opt.isset(FlagDst) {
|
||||
l += syscall.CmsgSpace(net.IPv4len)
|
||||
}
|
||||
if opt.isset(FlagInterface) {
|
||||
l += syscall.CmsgSpace(syscall.SizeofSockaddrDatalink)
|
||||
}
|
||||
}
|
||||
if opt.isset(FlagInterface) {
|
||||
l += syscall.CmsgSpace(syscall.SizeofSockaddrDatalink)
|
||||
return
|
||||
}
|
||||
|
||||
func (opt *rawOpt) marshalControlMessage() (oob []byte) {
|
||||
var off int
|
||||
oob = make([]byte, opt.oobLen())
|
||||
if opt.isset(FlagTTL) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = sysSockoptReceiveTTL
|
||||
m.SetLen(syscall.CmsgLen(1))
|
||||
off += syscall.CmsgSpace(1)
|
||||
}
|
||||
if l > 0 {
|
||||
oob = make([]byte, l)
|
||||
if opt.isset(FlagTTL) {
|
||||
if supportsPacketInfo {
|
||||
if opt.isset(FlagSrc | FlagDst | FlagInterface) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = syscall.IP_RECVTTL
|
||||
m.SetLen(syscall.CmsgLen(1))
|
||||
off += syscall.CmsgSpace(1)
|
||||
m.Type = sysSockoptPacketInfo
|
||||
m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
|
||||
off += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
} else {
|
||||
if opt.isset(FlagDst) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = syscall.IP_RECVDSTADDR
|
||||
m.Type = sysSockoptReceiveDst
|
||||
m.SetLen(syscall.CmsgLen(net.IPv4len))
|
||||
off += syscall.CmsgSpace(net.IPv4len)
|
||||
}
|
||||
if opt.isset(FlagInterface) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = syscall.IP_RECVIF
|
||||
m.Type = sysSockoptReceiveInterface
|
||||
m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrDatalink))
|
||||
off += syscall.CmsgSpace(syscall.SizeofSockaddrDatalink)
|
||||
}
|
||||
@@ -89,33 +118,25 @@ func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||
return
|
||||
}
|
||||
|
||||
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
func (cm *ControlMessage) oobLen() (l int) {
|
||||
if supportsPacketInfo && (cm.Src.To4() != nil || cm.IfIndex != 0) {
|
||||
l += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
cmsgs, err := syscall.ParseSocketControlMessage(b)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("parse socket control message", err)
|
||||
}
|
||||
cm := &ControlMessage{}
|
||||
for _, m := range cmsgs {
|
||||
if m.Header.Level != ianaProtocolIP {
|
||||
continue
|
||||
}
|
||||
switch m.Header.Type {
|
||||
case syscall.IP_RECVTTL:
|
||||
cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
|
||||
case syscall.IP_RECVDSTADDR:
|
||||
cm.Dst = m.Data[:net.IPv4len]
|
||||
case syscall.IP_RECVIF:
|
||||
sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&m.Data[0]))
|
||||
cm.IfIndex = int(sadl.Index)
|
||||
}
|
||||
}
|
||||
return cm, nil
|
||||
return
|
||||
}
|
||||
|
||||
func marshalControlMessage(cm *ControlMessage) []byte {
|
||||
// TODO(mikio): Implement IP_PKTINFO stuff when OS X 10.8 comes
|
||||
return nil
|
||||
func (cm *ControlMessage) parseControlMessage(m *syscall.SocketControlMessage) {
|
||||
switch m.Header.Type {
|
||||
case sysSockoptReceiveTTL:
|
||||
cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
|
||||
case sysSockoptReceiveDst:
|
||||
cm.Dst = m.Data[:net.IPv4len]
|
||||
case sysSockoptReceiveInterface:
|
||||
sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&m.Data[0]))
|
||||
cm.IfIndex = int(sadl.Index)
|
||||
case sysSockoptPacketInfo:
|
||||
pi := (*sysPacketInfo)(unsafe.Pointer(&m.Data[0]))
|
||||
cm.IfIndex = int(pi.IfIndex)
|
||||
cm.Dst = pi.IP[:]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,10 @@
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Linux provides a convenient path control option IP_PKTINFO that
|
||||
// contains IP_SENDSRCADDR, IP_RECVDSTADDR, IP_RECVIF and IP_SENDIF.
|
||||
const pktinfo = FlagSrc | FlagDst | FlagInterface
|
||||
|
||||
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||
opt.Lock()
|
||||
defer opt.Unlock()
|
||||
@@ -27,100 +22,63 @@ func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||
opt.clear(FlagTTL)
|
||||
}
|
||||
}
|
||||
if cf&pktinfo != 0 {
|
||||
if cf&(FlagSrc|FlagDst|FlagInterface) != 0 {
|
||||
if err := setIPv4PacketInfo(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(cf & pktinfo)
|
||||
opt.set(cf & (FlagSrc | FlagDst | FlagInterface))
|
||||
} else {
|
||||
opt.clear(cf & pktinfo)
|
||||
opt.clear(cf & (FlagSrc | FlagDst | FlagInterface))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||
opt.Lock()
|
||||
defer opt.Unlock()
|
||||
l, off := 0, 0
|
||||
func (opt *rawOpt) oobLen() (l int) {
|
||||
if opt.isset(FlagTTL) {
|
||||
l += syscall.CmsgSpace(1)
|
||||
}
|
||||
if opt.isset(pktinfo) {
|
||||
l += syscall.CmsgSpace(syscall.SizeofInet4Pktinfo)
|
||||
}
|
||||
if l > 0 {
|
||||
oob = make([]byte, l)
|
||||
if opt.isset(FlagTTL) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = syscall.IP_RECVTTL
|
||||
m.SetLen(syscall.CmsgLen(1))
|
||||
off += syscall.CmsgSpace(1)
|
||||
}
|
||||
if opt.isset(pktinfo) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = syscall.IP_PKTINFO
|
||||
m.SetLen(syscall.CmsgLen(syscall.SizeofInet4Pktinfo))
|
||||
off += syscall.CmsgSpace(syscall.SizeofInet4Pktinfo)
|
||||
}
|
||||
if opt.isset(FlagSrc | FlagDst | FlagInterface) {
|
||||
l += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
func (opt *rawOpt) marshalControlMessage() (oob []byte) {
|
||||
var off int
|
||||
oob = make([]byte, opt.oobLen())
|
||||
if opt.isset(FlagTTL) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = sysSockoptReceiveTTL
|
||||
m.SetLen(syscall.CmsgLen(1))
|
||||
off += syscall.CmsgSpace(1)
|
||||
}
|
||||
cmsgs, err := syscall.ParseSocketControlMessage(b)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("parse socket control message", err)
|
||||
if opt.isset(FlagSrc | FlagDst | FlagInterface) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[0]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = sysSockoptPacketInfo
|
||||
m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
|
||||
off += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
cm := &ControlMessage{}
|
||||
for _, m := range cmsgs {
|
||||
if m.Header.Level != ianaProtocolIP {
|
||||
continue
|
||||
}
|
||||
switch m.Header.Type {
|
||||
case syscall.IP_TTL:
|
||||
cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
|
||||
case syscall.IP_PKTINFO:
|
||||
pi := (*syscall.Inet4Pktinfo)(unsafe.Pointer(&m.Data[0]))
|
||||
cm.IfIndex = int(pi.Ifindex)
|
||||
cm.Dst = pi.Addr[:]
|
||||
}
|
||||
}
|
||||
return cm, nil
|
||||
return
|
||||
}
|
||||
|
||||
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||
if cm == nil {
|
||||
return
|
||||
}
|
||||
l, off := 0, 0
|
||||
pion := false
|
||||
func (cm *ControlMessage) oobLen() (l int) {
|
||||
if cm.Src.To4() != nil || cm.IfIndex != 0 {
|
||||
pion = true
|
||||
l += syscall.CmsgSpace(syscall.SizeofInet4Pktinfo)
|
||||
}
|
||||
if l > 0 {
|
||||
oob = make([]byte, l)
|
||||
if pion {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = syscall.IP_PKTINFO
|
||||
m.SetLen(syscall.CmsgLen(syscall.SizeofInet4Pktinfo))
|
||||
pi := (*syscall.Inet4Pktinfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
|
||||
if ip := cm.Src.To4(); ip != nil {
|
||||
copy(pi.Addr[:], ip)
|
||||
}
|
||||
if cm.IfIndex != 0 {
|
||||
pi.Ifindex = int32(cm.IfIndex)
|
||||
}
|
||||
off += syscall.CmsgSpace(syscall.SizeofInet4Pktinfo)
|
||||
}
|
||||
l += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (cm *ControlMessage) parseControlMessage(m *syscall.SocketControlMessage) {
|
||||
switch m.Header.Type {
|
||||
case sysSockoptTTL:
|
||||
cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
|
||||
case sysSockoptPacketInfo:
|
||||
pi := (*sysPacketInfo)(unsafe.Pointer(&m.Data[0]))
|
||||
cm.IfIndex = int(pi.IfIndex)
|
||||
cm.Dst = pi.IP[:]
|
||||
}
|
||||
}
|
||||
|
||||
11
ipv4/control_nonpktinfo.go
Normal file
11
ipv4/control_nonpktinfo.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// 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,!linux
|
||||
|
||||
package ipv4
|
||||
|
||||
func (cm *ControlMessage) marshalPacketInfo() (oob []byte) {
|
||||
return nil
|
||||
}
|
||||
30
ipv4/control_pktinfo.go
Normal file
30
ipv4/control_pktinfo.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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 linux
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (cm *ControlMessage) marshalPacketInfo() (oob []byte) {
|
||||
if l := cm.oobLen(); l > 0 {
|
||||
oob = make([]byte, l)
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[0]))
|
||||
m.Level = ianaProtocolIP
|
||||
m.Type = sysSockoptPacketInfo
|
||||
m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
|
||||
pi := (*sysPacketInfo)(unsafe.Pointer(&oob[syscall.CmsgLen(0)]))
|
||||
if ip := cm.Src.To4(); ip != nil {
|
||||
copy(pi.IP[:], ip)
|
||||
}
|
||||
if cm.IfIndex != 0 {
|
||||
pi.IfIndex = int32(cm.IfIndex)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
// +build plan9 solaris
|
||||
|
||||
package ipv4
|
||||
|
||||
|
||||
43
ipv4/control_unix.go
Normal file
43
ipv4/control_unix.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||
opt.Lock()
|
||||
defer opt.Unlock()
|
||||
return opt.marshalControlMessage()
|
||||
}
|
||||
|
||||
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
cmsgs, err := syscall.ParseSocketControlMessage(b)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("parse socket control message", err)
|
||||
}
|
||||
cm := &ControlMessage{}
|
||||
for _, m := range cmsgs {
|
||||
if m.Header.Level != ianaProtocolIP {
|
||||
continue
|
||||
}
|
||||
cm.parseControlMessage(&m)
|
||||
}
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||
if cm == nil {
|
||||
return nil
|
||||
}
|
||||
return cm.marshalPacketInfo()
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd windows
|
||||
|
||||
package ipv4
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
// +build plan9 solaris
|
||||
|
||||
package ipv4
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd windows
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd windows
|
||||
|
||||
package ipv4
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
// +build plan9 solaris
|
||||
|
||||
package ipv4
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd windows
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func setSyscallIPMreq(mreq *syscall.IPMreq, ifi *net.Interface) error {
|
||||
if ifi == nil {
|
||||
return nil
|
||||
}
|
||||
ifat, err := ifi.Addrs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, ifa := range ifat {
|
||||
switch v := ifa.(type) {
|
||||
case *net.IPAddr:
|
||||
if a := v.IP.To4(); a != nil {
|
||||
copy(mreq.Interface[:], a)
|
||||
goto done
|
||||
}
|
||||
case *net.IPNet:
|
||||
if a := v.IP.To4(); a != nil {
|
||||
copy(mreq.Interface[:], a)
|
||||
goto done
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
if bytes.Equal(mreq.Multiaddr[:], net.IPv4zero.To4()) {
|
||||
return errNoSuchMulticastInterface
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
// +build plan9 solaris
|
||||
|
||||
package ipv4
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package ipv4
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ func slicePacket(b []byte) (h, p []byte, err error) {
|
||||
// WriteTo writes an IPv4 datagram through the endpoint c, copying the
|
||||
// datagram from the IPv4 header h and the payload p. The control
|
||||
// message cm allows the datagram path and the outgoing interface to be
|
||||
// specified. Currently only Linux supports this. The cm may be nil
|
||||
// if control of the outgoing datagram is not required.
|
||||
// specified. Currently only Darwin and Linux support this. The cm
|
||||
// may be nil if control of the outgoing datagram is not required.
|
||||
//
|
||||
// The IPv4 header h must contain appropriate fields that include:
|
||||
//
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
import "net"
|
||||
|
||||
// A payloadHandler represents the IPv4 datagram payload handler.
|
||||
type payloadHandler struct {
|
||||
@@ -16,66 +13,3 @@ type payloadHandler struct {
|
||||
}
|
||||
|
||||
func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil }
|
||||
|
||||
// ReadFrom reads a payload of the received IPv4 datagram, from the
|
||||
// endpoint c, copying the payload into b. It returns the number of
|
||||
// bytes copied into b, the control message cm and the source address
|
||||
// src of the received datagram.
|
||||
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||
if !c.ok() {
|
||||
return 0, nil, nil, syscall.EINVAL
|
||||
}
|
||||
oob := newControlMessage(&c.rawOpt)
|
||||
var oobn int
|
||||
switch c := c.PacketConn.(type) {
|
||||
case *net.UDPConn:
|
||||
if n, oobn, _, src, err = c.ReadMsgUDP(b, oob); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
case *net.IPConn:
|
||||
nb := make([]byte, maxHeaderLen+len(b))
|
||||
if n, oobn, _, src, err = c.ReadMsgIP(nb, oob); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
hdrlen := int(nb[0]&0x0f) << 2
|
||||
copy(b, nb[hdrlen:])
|
||||
n -= hdrlen
|
||||
default:
|
||||
return 0, nil, nil, errInvalidConnType
|
||||
}
|
||||
if cm, err = parseControlMessage(oob[:oobn]); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
if cm != nil {
|
||||
cm.Src = netAddrToIP4(src)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// WriteTo writes a payload of the IPv4 datagram, to the destination
|
||||
// address dst through the endpoint c, copying the payload from b. It
|
||||
// returns the number of bytes written. The control message cm allows
|
||||
// the datagram path and the outgoing interface to be specified.
|
||||
// Currently only Linux supports this. The cm may be nil if control
|
||||
// of the outgoing datagram is not required.
|
||||
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
|
||||
if !c.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
oob := marshalControlMessage(cm)
|
||||
if dst == nil {
|
||||
return 0, errMissingAddress
|
||||
}
|
||||
switch c := c.PacketConn.(type) {
|
||||
case *net.UDPConn:
|
||||
n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
|
||||
case *net.IPConn:
|
||||
n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
|
||||
default:
|
||||
return 0, errInvalidConnType
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
75
ipv4/payload_cmsg.go
Normal file
75
ipv4/payload_cmsg.go
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !plan9,!solaris,!windows
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ReadFrom reads a payload of the received IPv4 datagram, from the
|
||||
// endpoint c, copying the payload into b. It returns the number of
|
||||
// bytes copied into b, the control message cm and the source address
|
||||
// src of the received datagram.
|
||||
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||
if !c.ok() {
|
||||
return 0, nil, nil, syscall.EINVAL
|
||||
}
|
||||
oob := newControlMessage(&c.rawOpt)
|
||||
var oobn int
|
||||
switch c := c.PacketConn.(type) {
|
||||
case *net.UDPConn:
|
||||
if n, oobn, _, src, err = c.ReadMsgUDP(b, oob); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
case *net.IPConn:
|
||||
nb := make([]byte, maxHeaderLen+len(b))
|
||||
if n, oobn, _, src, err = c.ReadMsgIP(nb, oob); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
hdrlen := int(nb[0]&0x0f) << 2
|
||||
copy(b, nb[hdrlen:])
|
||||
n -= hdrlen
|
||||
default:
|
||||
return 0, nil, nil, errInvalidConnType
|
||||
}
|
||||
if cm, err = parseControlMessage(oob[:oobn]); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
if cm != nil {
|
||||
cm.Src = netAddrToIP4(src)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// WriteTo writes a payload of the IPv4 datagram, to the destination
|
||||
// address dst through the endpoint c, copying the payload from b. It
|
||||
// returns the number of bytes written. The control message cm allows
|
||||
// the datagram path and the outgoing interface to be specified.
|
||||
// Currently only Darwin and Darwin support this. The cm may be nil if
|
||||
// control of the outgoing datagram is not required.
|
||||
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
|
||||
if !c.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
oob := marshalControlMessage(cm)
|
||||
if dst == nil {
|
||||
return 0, errMissingAddress
|
||||
}
|
||||
switch c := c.PacketConn.(type) {
|
||||
case *net.UDPConn:
|
||||
n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
|
||||
case *net.IPConn:
|
||||
n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
|
||||
default:
|
||||
return 0, errInvalidConnType
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
42
ipv4/payload_noncmsg.go
Normal file
42
ipv4/payload_noncmsg.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build plan9 solaris windows
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ReadFrom reads a payload of the received IPv4 datagram, from the
|
||||
// endpoint c, copying the payload into b. It returns the number of
|
||||
// bytes copied into b, the control message cm and the source address
|
||||
// src of the received datagram.
|
||||
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||
if !c.ok() {
|
||||
return 0, nil, nil, syscall.EINVAL
|
||||
}
|
||||
if n, src, err = c.PacketConn.ReadFrom(b); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// WriteTo writes a payload of the IPv4 datagram, to the destination
|
||||
// address dst through the endpoint c, copying the payload from b. It
|
||||
// returns the number of bytes written. The control message cm allows
|
||||
// the datagram path and the outgoing interface to be specified.
|
||||
// Currently only Darwin and Linux support this. The cm may be nil if
|
||||
// control of the outgoing datagram is not required.
|
||||
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
|
||||
if !c.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
if dst == nil {
|
||||
return 0, errMissingAddress
|
||||
}
|
||||
return c.PacketConn.WriteTo(b, dst)
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
package ipv4
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func ipv4MulticastTTL(fd int) (int, error) {
|
||||
v, err := syscall.GetsockoptByte(fd, ianaProtocolIP, syscall.IP_MULTICAST_TTL)
|
||||
v, err := syscall.GetsockoptByte(fd, ianaProtocolIP, sysSockoptMulticastTTL)
|
||||
if err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -21,11 +21,11 @@ func ipv4MulticastTTL(fd int) (int, error) {
|
||||
}
|
||||
|
||||
func setIPv4MulticastTTL(fd int, v int) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptByte(fd, ianaProtocolIP, syscall.IP_MULTICAST_TTL, byte(v)))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptByte(fd, ianaProtocolIP, sysSockoptMulticastTTL, byte(v)))
|
||||
}
|
||||
|
||||
func ipv4ReceiveDestinationAddress(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_RECVDSTADDR)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveDst)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -33,11 +33,11 @@ func ipv4ReceiveDestinationAddress(fd int) (bool, error) {
|
||||
}
|
||||
|
||||
func setIPv4ReceiveDestinationAddress(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_RECVDSTADDR, boolint(v)))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveDst, boolint(v)))
|
||||
}
|
||||
|
||||
func ipv4ReceiveInterface(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_RECVIF)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveInterface)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -45,11 +45,11 @@ func ipv4ReceiveInterface(fd int) (bool, error) {
|
||||
}
|
||||
|
||||
func setIPv4ReceiveInterface(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_RECVIF, boolint(v)))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveInterface, boolint(v)))
|
||||
}
|
||||
|
||||
func ipv4MulticastInterface(fd int) (*net.Interface, error) {
|
||||
v, err := syscall.GetsockoptInet4Addr(fd, ianaProtocolIP, syscall.IP_MULTICAST_IF)
|
||||
v, err := syscall.GetsockoptInet4Addr(fd, ianaProtocolIP, sysSockoptMulticastInterface)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -63,11 +63,11 @@ func setIPv4MulticastInterface(fd int, ifi *net.Interface) error {
|
||||
}
|
||||
var v [4]byte
|
||||
copy(v[:], ip.To4())
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInet4Addr(fd, ianaProtocolIP, syscall.IP_MULTICAST_IF, v))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInet4Addr(fd, ianaProtocolIP, sysSockoptMulticastInterface, v))
|
||||
}
|
||||
|
||||
func ipv4MulticastLoopback(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptByte(fd, ianaProtocolIP, syscall.IP_MULTICAST_LOOP)
|
||||
v, err := syscall.GetsockoptByte(fd, ianaProtocolIP, sysSockoptMulticastLoopback)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -75,21 +75,5 @@ func ipv4MulticastLoopback(fd int) (bool, error) {
|
||||
}
|
||||
|
||||
func setIPv4MulticastLoopback(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptByte(fd, ianaProtocolIP, syscall.IP_MULTICAST_LOOP, byte(boolint(v))))
|
||||
}
|
||||
|
||||
func joinIPv4Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := syscall.IPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if err := setSyscallIPMreq(&mreq, ifi); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd, ianaProtocolIP, syscall.IP_ADD_MEMBERSHIP, &mreq))
|
||||
}
|
||||
|
||||
func leaveIPv4Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := syscall.IPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if err := setSyscallIPMreq(&mreq, ifi); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd, ianaProtocolIP, syscall.IP_DROP_MEMBERSHIP, &mreq))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptByte(fd, ianaProtocolIP, sysSockoptMulticastLoopback, byte(boolint(v))))
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
func ipv4ReceiveTOS(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_RECVTOS)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveTOS)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -19,11 +19,11 @@ func ipv4ReceiveTOS(fd int) (bool, error) {
|
||||
}
|
||||
|
||||
func setIPv4ReceiveTOS(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_RECVTOS, boolint(v)))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveTOS, boolint(v)))
|
||||
}
|
||||
|
||||
func ipv4MulticastTTL(fd int) (int, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_MULTICAST_TTL)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptMulticastTTL)
|
||||
if err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -31,42 +31,30 @@ func ipv4MulticastTTL(fd int) (int, error) {
|
||||
}
|
||||
|
||||
func setIPv4MulticastTTL(fd int, v int) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_MULTICAST_TTL, v))
|
||||
}
|
||||
|
||||
func ipv4PacketInfo(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_PKTINFO)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv4PacketInfo(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_PKTINFO, boolint(v)))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptMulticastTTL, v))
|
||||
}
|
||||
|
||||
func ipv4MulticastInterface(fd int) (*net.Interface, error) {
|
||||
mreqn, err := syscall.GetsockoptIPMreqn(fd, ianaProtocolIP, syscall.IP_MULTICAST_IF)
|
||||
mreqn, err := syscall.GetsockoptIPMreqn(fd, ianaProtocolIP, sysSockoptMulticastInterface)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
if int(mreqn.Ifindex) == 0 {
|
||||
if mreqn.Ifindex == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return net.InterfaceByIndex(int(mreqn.Ifindex))
|
||||
}
|
||||
|
||||
func setIPv4MulticastInterface(fd int, ifi *net.Interface) error {
|
||||
mreqn := syscall.IPMreqn{}
|
||||
var mreqn syscall.IPMreqn
|
||||
if ifi != nil {
|
||||
mreqn.Ifindex = int32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd, ianaProtocolIP, syscall.IP_MULTICAST_IF, &mreqn))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd, ianaProtocolIP, sysSockoptMulticastInterface, &mreqn))
|
||||
}
|
||||
|
||||
func ipv4MulticastLoopback(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_MULTICAST_LOOP)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptMulticastLoopback)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -74,21 +62,5 @@ func ipv4MulticastLoopback(fd int) (bool, error) {
|
||||
}
|
||||
|
||||
func setIPv4MulticastLoopback(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_MULTICAST_LOOP, boolint(v)))
|
||||
}
|
||||
|
||||
func joinIPv4Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreqn := syscall.IPMreqn{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if ifi != nil {
|
||||
mreqn.Ifindex = int32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd, ianaProtocolIP, syscall.IP_ADD_MEMBERSHIP, &mreqn))
|
||||
}
|
||||
|
||||
func leaveIPv4Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreqn := syscall.IPMreqn{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if ifi != nil {
|
||||
mreqn.Ifindex = int32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd, ianaProtocolIP, syscall.IP_DROP_MEMBERSHIP, &mreqn))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptMulticastLoopback, boolint(v)))
|
||||
}
|
||||
|
||||
29
ipv4/sockopt_mreq.go
Normal file
29
ipv4/sockopt_mreq.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin dragonfly netbsd openbsd
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func joinIPv4Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := syscall.IPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if err := setSysIPMreqInterface(&mreq, ifi); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd, ianaProtocolIP, sysSockoptJoinGroup, &mreq))
|
||||
}
|
||||
|
||||
func leaveIPv4Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := syscall.IPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if err := setSysIPMreqInterface(&mreq, ifi); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd, ianaProtocolIP, sysSockoptLeaveGroup, &mreq))
|
||||
}
|
||||
29
ipv4/sockopt_mreqn.go
Normal file
29
ipv4/sockopt_mreqn.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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 freebsd linux
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func joinIPv4Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreqn := syscall.IPMreqn{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if ifi != nil {
|
||||
mreqn.Ifindex = int32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd, ianaProtocolIP, sysSockoptJoinGroup, &mreqn))
|
||||
}
|
||||
|
||||
func leaveIPv4Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreqn := syscall.IPMreqn{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if ifi != nil {
|
||||
mreqn.Ifindex = int32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd, ianaProtocolIP, sysSockoptLeaveGroup, &mreqn))
|
||||
}
|
||||
15
ipv4/sockopt_nonpktinfo.go
Normal file
15
ipv4/sockopt_nonpktinfo.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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,!linux
|
||||
|
||||
package ipv4
|
||||
|
||||
func ipv4PacketInfo(fd int) (bool, error) {
|
||||
return false, errOpNoSupport
|
||||
}
|
||||
|
||||
func setIPv4PacketInfo(fd int, v bool) error {
|
||||
return errOpNoSupport
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// 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 linux
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
@@ -9,14 +11,14 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func ipv4SendSourceAddress(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_SENDSRCADDR)
|
||||
func ipv4PacketInfo(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptPacketInfo)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv4SendSourceAddress(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_SENDSRCADDR, boolint(v)))
|
||||
func setIPv4PacketInfo(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptPacketInfo, boolint(v)))
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
// +build plan9 solaris
|
||||
|
||||
package ipv4
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package ipv4
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func ipv4TOS(fd int) (int, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_TOS)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptTOS)
|
||||
if err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -20,11 +20,11 @@ func ipv4TOS(fd int) (int, error) {
|
||||
}
|
||||
|
||||
func setIPv4TOS(fd int, v int) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_TOS, v))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptTOS, v))
|
||||
}
|
||||
|
||||
func ipv4TTL(fd int) (int, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_TTL)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptTTL)
|
||||
if err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -32,11 +32,11 @@ func ipv4TTL(fd int) (int, error) {
|
||||
}
|
||||
|
||||
func setIPv4TTL(fd int, v int) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_TTL, v))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptTTL, v))
|
||||
}
|
||||
|
||||
func ipv4ReceiveTTL(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_RECVTTL)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveTTL)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -44,11 +44,11 @@ func ipv4ReceiveTTL(fd int) (bool, error) {
|
||||
}
|
||||
|
||||
func setIPv4ReceiveTTL(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_RECVTTL, boolint(v)))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptReceiveTTL, boolint(v)))
|
||||
}
|
||||
|
||||
func ipv4HeaderPrepend(fd int) (bool, error) {
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, syscall.IP_HDRINCL)
|
||||
v, err := syscall.GetsockoptInt(fd, ianaProtocolIP, sysSockoptHeaderPrepend)
|
||||
if err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
@@ -56,5 +56,5 @@ func ipv4HeaderPrepend(fd int) (bool, error) {
|
||||
}
|
||||
|
||||
func setIPv4HeaderPrepend(fd int, v bool) error {
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, syscall.IP_HDRINCL, boolint(v)))
|
||||
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, ianaProtocolIP, sysSockoptHeaderPrepend, boolint(v)))
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
func ipv4TOS(fd syscall.Handle) (int, error) {
|
||||
var v int32
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, syscall.IP_TOS, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, sysSockoptTOS, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v), nil
|
||||
@@ -25,13 +25,13 @@ func ipv4TOS(fd syscall.Handle) (int, error) {
|
||||
|
||||
func setIPv4TOS(fd syscall.Handle, v int) error {
|
||||
vv := int32(v)
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_TOS, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, sysSockoptTOS, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv4TTL(fd syscall.Handle) (int, error) {
|
||||
var v int32
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, syscall.IP_TTL, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, sysSockoptTTL, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v), nil
|
||||
@@ -39,13 +39,13 @@ func ipv4TTL(fd syscall.Handle) (int, error) {
|
||||
|
||||
func setIPv4TTL(fd syscall.Handle, v int) error {
|
||||
vv := int32(v)
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_TTL, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, sysSockoptTTL, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv4MulticastTTL(fd syscall.Handle) (int, error) {
|
||||
var v int32
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_TTL, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, sysSockoptMulticastTTL, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v), nil
|
||||
@@ -53,7 +53,7 @@ func ipv4MulticastTTL(fd syscall.Handle) (int, error) {
|
||||
|
||||
func setIPv4MulticastTTL(fd syscall.Handle, v int) error {
|
||||
vv := int32(v)
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_TTL, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, sysSockoptMulticastTTL, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv4ReceiveTTL(fd syscall.Handle) (bool, error) {
|
||||
@@ -99,7 +99,7 @@ func setIPv4ReceiveInterface(fd syscall.Handle, v bool) error {
|
||||
func ipv4MulticastInterface(fd syscall.Handle) (*net.Interface, error) {
|
||||
var v [4]byte
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_IF, (*byte)(unsafe.Pointer(&v[0])), &l); err != nil {
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, sysSockoptMulticastInterface, (*byte)(unsafe.Pointer(&v[0])), &l); err != nil {
|
||||
return nil, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return netIP4ToInterface(net.IPv4(v[0], v[1], v[2], v[3]))
|
||||
@@ -112,13 +112,13 @@ func setIPv4MulticastInterface(fd syscall.Handle, ifi *net.Interface) error {
|
||||
}
|
||||
var v [4]byte
|
||||
copy(v[:], ip.To4())
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_IF, (*byte)(unsafe.Pointer(&v[0])), 4))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, sysSockoptMulticastInterface, (*byte)(unsafe.Pointer(&v[0])), 4))
|
||||
}
|
||||
|
||||
func ipv4MulticastLoopback(fd syscall.Handle) (bool, error) {
|
||||
var v int32
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_LOOP, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIP, sysSockoptMulticastLoopback, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
@@ -126,21 +126,21 @@ func ipv4MulticastLoopback(fd syscall.Handle) (bool, error) {
|
||||
|
||||
func setIPv4MulticastLoopback(fd syscall.Handle, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_MULTICAST_LOOP, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, sysSockoptMulticastLoopback, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func joinIPv4Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := syscall.IPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if err := setSyscallIPMreq(&mreq, ifi); err != nil {
|
||||
if err := setSysIPMreqInterface(&mreq, ifi); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_ADD_MEMBERSHIP, (*byte)(unsafe.Pointer(&mreq)), int32(unsafe.Sizeof(mreq))))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, sysSockoptJoinGroup, (*byte)(unsafe.Pointer(&mreq)), int32(unsafe.Sizeof(mreq))))
|
||||
}
|
||||
|
||||
func leaveIPv4Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := syscall.IPMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
|
||||
if err := setSyscallIPMreq(&mreq, ifi); err != nil {
|
||||
if err := setSysIPMreqInterface(&mreq, ifi); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, syscall.IP_DROP_MEMBERSHIP, (*byte)(unsafe.Pointer(&mreq)), int32(unsafe.Sizeof(mreq))))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIP, sysSockoptLeaveGroup, (*byte)(unsafe.Pointer(&mreq)), int32(unsafe.Sizeof(mreq))))
|
||||
}
|
||||
|
||||
9
ipv4/sys.go
Normal file
9
ipv4/sys.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4
|
||||
|
||||
// supportsPacketInfo reports whether the platform supports
|
||||
// IP_PKTINFO.
|
||||
var supportsPacketInfo bool
|
||||
37
ipv4/sys_bsd.go
Normal file
37
ipv4/sys_bsd.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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 netbsd openbsd
|
||||
|
||||
package ipv4
|
||||
|
||||
import "syscall"
|
||||
|
||||
const (
|
||||
// See /usr/include/netinet/in.h.
|
||||
sysSockoptHeaderPrepend = syscall.IP_HDRINCL
|
||||
sysSockoptTOS = syscall.IP_TOS
|
||||
sysSockoptTTL = syscall.IP_TTL
|
||||
sysSockoptMulticastTTL = syscall.IP_MULTICAST_TTL
|
||||
sysSockoptMulticastInterface = syscall.IP_MULTICAST_IF
|
||||
sysSockoptMulticastLoopback = syscall.IP_MULTICAST_LOOP
|
||||
sysSockoptJoinGroup = syscall.IP_ADD_MEMBERSHIP
|
||||
sysSockoptLeaveGroup = syscall.IP_DROP_MEMBERSHIP
|
||||
)
|
||||
|
||||
const (
|
||||
// See /usr/include/netinet/in.h.
|
||||
sysSockoptReceiveTTL = syscall.IP_RECVTTL
|
||||
sysSockoptReceiveDst = syscall.IP_RECVDSTADDR
|
||||
sysSockoptReceiveInterface = syscall.IP_RECVIF
|
||||
sysSockoptPacketInfo = 0x1a // only darwin supports this option for now
|
||||
)
|
||||
|
||||
const sysSizeofPacketInfo = 0xc
|
||||
|
||||
type sysPacketInfo struct {
|
||||
IfIndex int32
|
||||
RoutedIP [4]byte
|
||||
IP [4]byte
|
||||
}
|
||||
27
ipv4/sys_darwin.go
Normal file
27
ipv4/sys_darwin.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4
|
||||
|
||||
import "syscall"
|
||||
|
||||
func init() {
|
||||
// Seems like kern.osreldate is veiled on latest OS X. We use
|
||||
// kern.osrelease instead.
|
||||
osver, err := syscall.Sysctl("kern.osrelease")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var i int
|
||||
for i = range osver {
|
||||
if osver[i] != '.' {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// The IP_PKTINFO was introduced in OS X 10.7 (Darwin
|
||||
// 11.0.0). See http://support.apple.com/kb/HT1633.
|
||||
if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '1' {
|
||||
supportsPacketInfo = true
|
||||
}
|
||||
}
|
||||
47
ipv4/sys_linux.go
Normal file
47
ipv4/sys_linux.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4
|
||||
|
||||
import "syscall"
|
||||
|
||||
const (
|
||||
// See /usr/include/linux/in.h.
|
||||
sysSockoptHeaderPrepend = syscall.IP_HDRINCL
|
||||
sysSockoptTOS = syscall.IP_TOS
|
||||
sysSockoptTTL = syscall.IP_TTL
|
||||
sysSockoptMulticastTTL = syscall.IP_MULTICAST_TTL
|
||||
sysSockoptMulticastInterface = syscall.IP_MULTICAST_IF
|
||||
sysSockoptMulticastLoopback = syscall.IP_MULTICAST_LOOP
|
||||
sysSockoptJoinGroup = syscall.IP_ADD_MEMBERSHIP
|
||||
sysSockoptLeaveGroup = syscall.IP_DROP_MEMBERSHIP
|
||||
)
|
||||
|
||||
const (
|
||||
// See /usr/include/linux/in.h.
|
||||
sysSockoptReceiveTOS = syscall.IP_RECVTOS
|
||||
sysSockoptReceiveTTL = syscall.IP_RECVTTL
|
||||
sysSockoptPacketInfo = syscall.IP_PKTINFO
|
||||
)
|
||||
|
||||
const (
|
||||
sysSizeofNewMulticastReq = 0xc
|
||||
sysSizeofPacketInfo = 0xc
|
||||
)
|
||||
|
||||
type sysNewMulticastReq struct {
|
||||
IP [4]byte
|
||||
Interface [4]byte
|
||||
IfIndex int32
|
||||
}
|
||||
|
||||
type sysPacketInfo struct {
|
||||
IfIndex int32
|
||||
RoutedIP [4]byte
|
||||
IP [4]byte
|
||||
}
|
||||
|
||||
func init() {
|
||||
supportsPacketInfo = true
|
||||
}
|
||||
37
ipv4/sys_mreq.go
Normal file
37
ipv4/sys_mreq.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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 netbsd openbsd windows
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func setSysIPMreqInterface(mreq *syscall.IPMreq, ifi *net.Interface) error {
|
||||
if ifi == nil {
|
||||
return nil
|
||||
}
|
||||
ifat, err := ifi.Addrs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, ifa := range ifat {
|
||||
switch v := ifa.(type) {
|
||||
case *net.IPAddr:
|
||||
if ip := v.IP.To4(); ip != nil {
|
||||
copy(mreq.Interface[:], ip)
|
||||
return nil
|
||||
}
|
||||
case *net.IPNet:
|
||||
if ip := v.IP.To4(); ip != nil {
|
||||
copy(mreq.Interface[:], ip)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return errNoSuchInterface
|
||||
}
|
||||
31
ipv4/sys_windows.go
Normal file
31
ipv4/sys_windows.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv4
|
||||
|
||||
import "syscall"
|
||||
|
||||
const (
|
||||
// See ws2tcpip.h.
|
||||
sysSockoptHeaderPrepend = 0x2
|
||||
sysSockoptTOS = syscall.IP_TOS
|
||||
sysSockoptTTL = syscall.IP_TTL
|
||||
sysSockoptMulticastTTL = syscall.IP_MULTICAST_TTL
|
||||
sysSockoptMulticastInterface = syscall.IP_MULTICAST_IF
|
||||
sysSockoptMulticastLoopback = syscall.IP_MULTICAST_LOOP
|
||||
sysSockoptJoinGroup = syscall.IP_ADD_MEMBERSHIP
|
||||
sysSockoptLeaveGroup = syscall.IP_DROP_MEMBERSHIP
|
||||
)
|
||||
|
||||
const (
|
||||
// See ws2tcpip.h.
|
||||
sysSockoptPacketInfo = 0x13
|
||||
)
|
||||
|
||||
const sysSizeofPacketInfo = 0x8
|
||||
|
||||
type sysPacketInfo struct {
|
||||
IP [4]byte
|
||||
IfIndex int32
|
||||
}
|
||||
Reference in New Issue
Block a user