Commit c4fa6e0d authored by Mikio Hara's avatar Mikio Hara

ipv4: plumb in the standard library of Go 1.9 by using internal/socket package

This change uses the internal/socket package to ensure that the ipv4
package works with all supported versions of the Go standard library.

Fixes golang/go#19051.

Change-Id: If0256007c749c319970533823a10afdc1ffbce31
Reviewed-on: https://go-review.googlesource.com/37036Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 50e760fb
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv4
import (
"os"
"unsafe"
"golang.org/x/net/bpf"
"golang.org/x/net/internal/netreflect"
)
// SetBPF attaches a BPF program to the connection.
//
// Only supported on Linux.
func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
s, err := netreflect.PacketSocketOf(c.PacketConn)
if err != nil {
return err
}
prog := sockFProg{
Len: uint16(len(filter)),
Filter: (*sockFilter)(unsafe.Pointer(&filter[0])),
}
return os.NewSyscallError("setsockopt", setsockopt(s, sysSOL_SOCKET, sysSO_ATTACH_FILTER, unsafe.Pointer(&prog), uint32(unsafe.Sizeof(prog))))
}
...@@ -2,11 +2,13 @@ ...@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build nacl plan9 // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package ipv4 package ipv4
func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error { import "golang.org/x/net/internal/socket"
func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
return errOpNoSupport return errOpNoSupport
} }
......
...@@ -12,13 +12,14 @@ import ( ...@@ -12,13 +12,14 @@ import (
"unsafe" "unsafe"
"golang.org/x/net/internal/iana" "golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
) )
func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error { func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
opt.Lock() opt.Lock()
defer opt.Unlock() defer opt.Unlock()
if cf&FlagTTL != 0 && sockOpts[ssoReceiveTTL].name > 0 { if so, ok := sockOpts[ssoReceiveTTL]; ok && cf&FlagTTL != 0 {
if err := setInt(s, &sockOpts[ssoReceiveTTL], boolint(on)); err != nil { if err := so.SetInt(c, boolint(on)); err != nil {
return err return err
} }
if on { if on {
...@@ -27,9 +28,9 @@ func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error { ...@@ -27,9 +28,9 @@ func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
opt.clear(FlagTTL) opt.clear(FlagTTL)
} }
} }
if sockOpts[ssoPacketInfo].name > 0 { if so, ok := sockOpts[ssoPacketInfo]; ok {
if cf&(FlagSrc|FlagDst|FlagInterface) != 0 { if cf&(FlagSrc|FlagDst|FlagInterface) != 0 {
if err := setInt(s, &sockOpts[ssoPacketInfo], boolint(on)); err != nil { if err := so.SetInt(c, boolint(on)); err != nil {
return err return err
} }
if on { if on {
...@@ -39,8 +40,8 @@ func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error { ...@@ -39,8 +40,8 @@ func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
} }
} }
} else { } else {
if cf&FlagDst != 0 && sockOpts[ssoReceiveDst].name > 0 { if so, ok := sockOpts[ssoReceiveDst]; ok && cf&FlagDst != 0 {
if err := setInt(s, &sockOpts[ssoReceiveDst], boolint(on)); err != nil { if err := so.SetInt(c, boolint(on)); err != nil {
return err return err
} }
if on { if on {
...@@ -49,8 +50,8 @@ func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error { ...@@ -49,8 +50,8 @@ func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error {
opt.clear(FlagDst) opt.clear(FlagDst)
} }
} }
if cf&FlagInterface != 0 && sockOpts[ssoReceiveInterface].name > 0 { if so, ok := sockOpts[ssoReceiveInterface]; ok && cf&FlagInterface != 0 {
if err := setInt(s, &sockOpts[ssoReceiveInterface], boolint(on)); err != nil { if err := so.SetInt(c, boolint(on)); err != nil {
return err return err
} }
if on { if on {
......
...@@ -4,9 +4,13 @@ ...@@ -4,9 +4,13 @@
package ipv4 package ipv4
import "syscall" import (
"syscall"
func setControlMessage(s uintptr, opt *rawOpt, cf ControlFlags, on bool) error { "golang.org/x/net/internal/socket"
)
func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
// TODO(mikio): implement this // TODO(mikio): implement this
return syscall.EWINDOWS return syscall.EWINDOWS
} }
......
...@@ -93,6 +93,8 @@ const ( ...@@ -93,6 +93,8 @@ const (
sizeofGroupSourceReq = C.sizeof_struct_group_source_req sizeofGroupSourceReq = C.sizeof_struct_group_source_req
sizeofICMPFilter = C.sizeof_struct_icmp_filter sizeofICMPFilter = C.sizeof_struct_icmp_filter
sizeofSockFprog = C.sizeof_struct_sock_fprog
) )
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
......
...@@ -2,15 +2,13 @@ ...@@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package ipv4 package ipv4
import ( import (
"net" "net"
"syscall" "syscall"
"golang.org/x/net/internal/netreflect" "golang.org/x/net/bpf"
) )
// MulticastTTL returns the time-to-live field value for outgoing // MulticastTTL returns the time-to-live field value for outgoing
...@@ -19,11 +17,11 @@ func (c *dgramOpt) MulticastTTL() (int, error) { ...@@ -19,11 +17,11 @@ func (c *dgramOpt) MulticastTTL() (int, error) {
if !c.ok() { if !c.ok() {
return 0, syscall.EINVAL return 0, syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoMulticastTTL]
if err != nil { if !ok {
return 0, err return 0, errOpNoSupport
} }
return getInt(s, &sockOpts[ssoMulticastTTL]) return so.GetInt(c.Conn)
} }
// SetMulticastTTL sets the time-to-live field value for future // SetMulticastTTL sets the time-to-live field value for future
...@@ -32,11 +30,11 @@ func (c *dgramOpt) SetMulticastTTL(ttl int) error { ...@@ -32,11 +30,11 @@ func (c *dgramOpt) SetMulticastTTL(ttl int) error {
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoMulticastTTL]
if err != nil { if !ok {
return err return errOpNoSupport
} }
return setInt(s, &sockOpts[ssoMulticastTTL], ttl) return so.SetInt(c.Conn, ttl)
} }
// MulticastInterface returns the default interface for multicast // MulticastInterface returns the default interface for multicast
...@@ -45,11 +43,11 @@ func (c *dgramOpt) MulticastInterface() (*net.Interface, error) { ...@@ -45,11 +43,11 @@ func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
if !c.ok() { if !c.ok() {
return nil, syscall.EINVAL return nil, syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoMulticastInterface]
if err != nil { if !ok {
return nil, err return nil, errOpNoSupport
} }
return getInterface(s, &sockOpts[ssoMulticastInterface]) return so.getMulticastInterface(c.Conn)
} }
// SetMulticastInterface sets the default interface for future // SetMulticastInterface sets the default interface for future
...@@ -58,11 +56,11 @@ func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error { ...@@ -58,11 +56,11 @@ func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoMulticastInterface]
if err != nil { if !ok {
return err return errOpNoSupport
} }
return setInterface(s, &sockOpts[ssoMulticastInterface], ifi) return so.setMulticastInterface(c.Conn, ifi)
} }
// MulticastLoopback reports whether transmitted multicast packets // MulticastLoopback reports whether transmitted multicast packets
...@@ -71,11 +69,11 @@ func (c *dgramOpt) MulticastLoopback() (bool, error) { ...@@ -71,11 +69,11 @@ func (c *dgramOpt) MulticastLoopback() (bool, error) {
if !c.ok() { if !c.ok() {
return false, syscall.EINVAL return false, syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoMulticastLoopback]
if err != nil { if !ok {
return false, err return false, errOpNoSupport
} }
on, err := getInt(s, &sockOpts[ssoMulticastLoopback]) on, err := so.GetInt(c.Conn)
if err != nil { if err != nil {
return false, err return false, err
} }
...@@ -88,11 +86,11 @@ func (c *dgramOpt) SetMulticastLoopback(on bool) error { ...@@ -88,11 +86,11 @@ func (c *dgramOpt) SetMulticastLoopback(on bool) error {
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoMulticastLoopback]
if err != nil { if !ok {
return err return errOpNoSupport
} }
return setInt(s, &sockOpts[ssoMulticastLoopback], boolint(on)) return so.SetInt(c.Conn, boolint(on))
} }
// JoinGroup joins the group address group on the interface ifi. // JoinGroup joins the group address group on the interface ifi.
...@@ -108,15 +106,15 @@ func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error { ...@@ -108,15 +106,15 @@ func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoJoinGroup]
if err != nil { if !ok {
return err return errOpNoSupport
} }
grp := netAddrToIP4(group) grp := netAddrToIP4(group)
if grp == nil { if grp == nil {
return errMissingAddress return errMissingAddress
} }
return setGroup(s, &sockOpts[ssoJoinGroup], ifi, grp) return so.setGroup(c.Conn, ifi, grp)
} }
// LeaveGroup leaves the group address group on the interface ifi // LeaveGroup leaves the group address group on the interface ifi
...@@ -126,15 +124,15 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error { ...@@ -126,15 +124,15 @@ func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoLeaveGroup]
if err != nil { if !ok {
return err return errOpNoSupport
} }
grp := netAddrToIP4(group) grp := netAddrToIP4(group)
if grp == nil { if grp == nil {
return errMissingAddress return errMissingAddress
} }
return setGroup(s, &sockOpts[ssoLeaveGroup], ifi, grp) return so.setGroup(c.Conn, ifi, grp)
} }
// JoinSourceSpecificGroup joins the source-specific group comprising // JoinSourceSpecificGroup joins the source-specific group comprising
...@@ -147,9 +145,9 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net ...@@ -147,9 +145,9 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoJoinSourceGroup]
if err != nil { if !ok {
return err return errOpNoSupport
} }
grp := netAddrToIP4(group) grp := netAddrToIP4(group)
if grp == nil { if grp == nil {
...@@ -159,7 +157,7 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net ...@@ -159,7 +157,7 @@ func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net
if src == nil { if src == nil {
return errMissingAddress return errMissingAddress
} }
return setSourceGroup(s, &sockOpts[ssoJoinSourceGroup], ifi, grp, src) return so.setSourceGroup(c.Conn, ifi, grp, src)
} }
// LeaveSourceSpecificGroup leaves the source-specific group on the // LeaveSourceSpecificGroup leaves the source-specific group on the
...@@ -168,9 +166,9 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne ...@@ -168,9 +166,9 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoLeaveSourceGroup]
if err != nil { if !ok {
return err return errOpNoSupport
} }
grp := netAddrToIP4(group) grp := netAddrToIP4(group)
if grp == nil { if grp == nil {
...@@ -180,7 +178,7 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne ...@@ -180,7 +178,7 @@ func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source ne
if src == nil { if src == nil {
return errMissingAddress return errMissingAddress
} }
return setSourceGroup(s, &sockOpts[ssoLeaveSourceGroup], ifi, grp, src) return so.setSourceGroup(c.Conn, ifi, grp, src)
} }
// ExcludeSourceSpecificGroup excludes the source-specific group from // ExcludeSourceSpecificGroup excludes the source-specific group from
...@@ -190,9 +188,9 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source ...@@ -190,9 +188,9 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoBlockSourceGroup]
if err != nil { if !ok {
return err return errOpNoSupport
} }
grp := netAddrToIP4(group) grp := netAddrToIP4(group)
if grp == nil { if grp == nil {
...@@ -202,7 +200,7 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source ...@@ -202,7 +200,7 @@ func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source
if src == nil { if src == nil {
return errMissingAddress return errMissingAddress
} }
return setSourceGroup(s, &sockOpts[ssoBlockSourceGroup], ifi, grp, src) return so.setSourceGroup(c.Conn, ifi, grp, src)
} }
// IncludeSourceSpecificGroup includes the excluded source-specific // IncludeSourceSpecificGroup includes the excluded source-specific
...@@ -211,9 +209,9 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source ...@@ -211,9 +209,9 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoUnblockSourceGroup]
if err != nil { if !ok {
return err return errOpNoSupport
} }
grp := netAddrToIP4(group) grp := netAddrToIP4(group)
if grp == nil { if grp == nil {
...@@ -223,7 +221,7 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source ...@@ -223,7 +221,7 @@ func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source
if src == nil { if src == nil {
return errMissingAddress return errMissingAddress
} }
return setSourceGroup(s, &sockOpts[ssoUnblockSourceGroup], ifi, grp, src) return so.setSourceGroup(c.Conn, ifi, grp, src)
} }
// ICMPFilter returns an ICMP filter. // ICMPFilter returns an ICMP filter.
...@@ -232,11 +230,11 @@ func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) { ...@@ -232,11 +230,11 @@ func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
if !c.ok() { if !c.ok() {
return nil, syscall.EINVAL return nil, syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoICMPFilter]
if err != nil { if !ok {
return nil, err return nil, errOpNoSupport
} }
return getICMPFilter(s, &sockOpts[ssoICMPFilter]) return so.getICMPFilter(c.Conn)
} }
// SetICMPFilter deploys the ICMP filter. // SetICMPFilter deploys the ICMP filter.
...@@ -245,9 +243,23 @@ func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error { ...@@ -245,9 +243,23 @@ func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.PacketConn) so, ok := sockOpts[ssoICMPFilter]
if err != nil { if !ok {
return err return errOpNoSupport
}
return so.setICMPFilter(c.Conn, f)
}
// SetBPF attaches a BPF program to the connection.
//
// Only supported on Linux.
func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
if !c.ok() {
return syscall.EINVAL
}
so, ok := sockOpts[ssoAttachFilter]
if !ok {
return errOpNoSupport
} }
return setICMPFilter(s, &sockOpts[ssoICMPFilter], f) return so.setBPF(c.Conn, filter)
} }
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl plan9
package ipv4
import "net"
// MulticastTTL returns the time-to-live field value for outgoing
// multicast packets.
func (c *dgramOpt) MulticastTTL() (int, error) {
return 0, errOpNoSupport
}
// SetMulticastTTL sets the time-to-live field value for future
// outgoing multicast packets.
func (c *dgramOpt) SetMulticastTTL(ttl int) error {
return errOpNoSupport
}
// MulticastInterface returns the default interface for multicast
// packet transmissions.
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
return nil, errOpNoSupport
}
// SetMulticastInterface sets the default interface for future
// multicast packet transmissions.
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
return errOpNoSupport
}
// MulticastLoopback reports whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) MulticastLoopback() (bool, error) {
return false, errOpNoSupport
}
// SetMulticastLoopback sets whether transmitted multicast packets
// should be copied and send back to the originator.
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
return errOpNoSupport
}
// JoinGroup joins the group address group on the interface ifi.
// By default all sources that can cast data to group are accepted.
// It's possible to mute and unmute data transmission from a specific
// source by using ExcludeSourceSpecificGroup and
// IncludeSourceSpecificGroup.
// JoinGroup uses the system assigned multicast interface when ifi is
// nil, although this is not recommended because the assignment
// depends on platforms and sometimes it might require routing
// configuration.
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
return errOpNoSupport
}
// LeaveGroup leaves the group address group on the interface ifi
// regardless of whether the group is any-source group or
// source-specific group.
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
return errOpNoSupport
}
// JoinSourceSpecificGroup joins the source-specific group comprising
// group and source on the interface ifi.
// JoinSourceSpecificGroup uses the system assigned multicast
// interface when ifi is nil, although this is not recommended because
// the assignment depends on platforms and sometimes it might require
// routing configuration.
func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
return errOpNoSupport
}
// LeaveSourceSpecificGroup leaves the source-specific group on the
// interface ifi.
func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
return errOpNoSupport
}
// ExcludeSourceSpecificGroup excludes the source-specific group from
// the already joined any-source groups by JoinGroup on the interface
// ifi.
func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
return errOpNoSupport
}
// IncludeSourceSpecificGroup includes the excluded source-specific
// group by ExcludeSourceSpecificGroup again on the interface ifi.
func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error {
return errOpNoSupport
}
// ICMPFilter returns an ICMP filter.
// Currently only Linux supports this.
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
return nil, errOpNoSupport
}
// SetICMPFilter deploys the ICMP filter.
// Currently only Linux supports this.
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
return errOpNoSupport
}
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"syscall" "syscall"
"time" "time"
"golang.org/x/net/internal/netreflect" "golang.org/x/net/internal/socket"
) )
// BUG(mikio): On Windows, the JoinSourceSpecificGroup, // BUG(mikio): On Windows, the JoinSourceSpecificGroup,
...@@ -25,15 +25,16 @@ type Conn struct { ...@@ -25,15 +25,16 @@ type Conn struct {
} }
type genericOpt struct { type genericOpt struct {
net.Conn *socket.Conn
} }
func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil } func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil }
// NewConn returns a new Conn. // NewConn returns a new Conn.
func NewConn(c net.Conn) *Conn { func NewConn(c net.Conn) *Conn {
cc, _ := socket.NewConn(c)
return &Conn{ return &Conn{
genericOpt: genericOpt{Conn: c}, genericOpt: genericOpt{Conn: cc},
} }
} }
...@@ -49,21 +50,17 @@ type PacketConn struct { ...@@ -49,21 +50,17 @@ type PacketConn struct {
} }
type dgramOpt struct { type dgramOpt struct {
net.PacketConn *socket.Conn
} }
func (c *dgramOpt) ok() bool { return c != nil && c.PacketConn != nil } func (c *dgramOpt) ok() bool { return c != nil && c.Conn != nil }
// SetControlMessage sets the per packet IP-level socket options. // SetControlMessage sets the per packet IP-level socket options.
func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error { func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error {
if !c.payloadHandler.ok() { if !c.payloadHandler.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.dgramOpt.PacketConn) return setControlMessage(c.dgramOpt.Conn, &c.payloadHandler.rawOpt, cf, on)
if err != nil {
return err
}
return setControlMessage(s, &c.payloadHandler.rawOpt, cf, on)
} }
// SetDeadline sets the read and write deadlines associated with the // SetDeadline sets the read and write deadlines associated with the
...@@ -104,14 +101,15 @@ func (c *PacketConn) Close() error { ...@@ -104,14 +101,15 @@ func (c *PacketConn) Close() error {
// NewPacketConn returns a new PacketConn using c as its underlying // NewPacketConn returns a new PacketConn using c as its underlying
// transport. // transport.
func NewPacketConn(c net.PacketConn) *PacketConn { func NewPacketConn(c net.PacketConn) *PacketConn {
cc, _ := socket.NewConn(c.(net.Conn))
p := &PacketConn{ p := &PacketConn{
genericOpt: genericOpt{Conn: c.(net.Conn)}, genericOpt: genericOpt{Conn: cc},
dgramOpt: dgramOpt{PacketConn: c}, dgramOpt: dgramOpt{Conn: cc},
payloadHandler: payloadHandler{PacketConn: c}, payloadHandler: payloadHandler{PacketConn: c},
} }
if _, ok := c.(*net.IPConn); ok && sockOpts[ssoStripHeader].name > 0 { if _, ok := c.(*net.IPConn); ok {
if s, err := netreflect.PacketSocketOf(c); err == nil { if so, ok := sockOpts[ssoStripHeader]; ok {
setInt(s, &sockOpts[ssoStripHeader], boolint(true)) so.SetInt(p.dgramOpt.Conn, boolint(true))
} }
} }
return p return p
...@@ -133,11 +131,7 @@ func (c *RawConn) SetControlMessage(cf ControlFlags, on bool) error { ...@@ -133,11 +131,7 @@ func (c *RawConn) SetControlMessage(cf ControlFlags, on bool) error {
if !c.packetHandler.ok() { if !c.packetHandler.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.PacketSocketOf(c.dgramOpt.PacketConn) return setControlMessage(c.dgramOpt.Conn, &c.packetHandler.rawOpt, cf, on)
if err != nil {
return err
}
return setControlMessage(s, &c.packetHandler.rawOpt, cf, on)
} }
// SetDeadline sets the read and write deadlines associated with the // SetDeadline sets the read and write deadlines associated with the
...@@ -178,16 +172,20 @@ func (c *RawConn) Close() error { ...@@ -178,16 +172,20 @@ func (c *RawConn) Close() error {
// NewRawConn returns a new RawConn using c as its underlying // NewRawConn returns a new RawConn using c as its underlying
// transport. // transport.
func NewRawConn(c net.PacketConn) (*RawConn, error) { func NewRawConn(c net.PacketConn) (*RawConn, error) {
cc, err := socket.NewConn(c.(net.Conn))
if err != nil {
return nil, err
}
r := &RawConn{ r := &RawConn{
genericOpt: genericOpt{Conn: c.(net.Conn)}, genericOpt: genericOpt{Conn: cc},
dgramOpt: dgramOpt{PacketConn: c}, dgramOpt: dgramOpt{Conn: cc},
packetHandler: packetHandler{c: c.(*net.IPConn)}, packetHandler: packetHandler{c: c.(*net.IPConn)},
} }
s, err := netreflect.PacketSocketOf(c) so, ok := sockOpts[ssoHeaderPrepend]
if err != nil { if !ok {
return nil, err return nil, errOpNoSupport
} }
if err := setInt(s, &sockOpts[ssoHeaderPrepend], boolint(true)); err != nil { if err := so.SetInt(r.dgramOpt.Conn, boolint(true)); err != nil {
return nil, err return nil, err
} }
return r, nil return r, nil
......
...@@ -2,26 +2,20 @@ ...@@ -2,26 +2,20 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package ipv4 package ipv4
import ( import "syscall"
"syscall"
"golang.org/x/net/internal/netreflect"
)
// TOS returns the type-of-service field value for outgoing packets. // TOS returns the type-of-service field value for outgoing packets.
func (c *genericOpt) TOS() (int, error) { func (c *genericOpt) TOS() (int, error) {
if !c.ok() { if !c.ok() {
return 0, syscall.EINVAL return 0, syscall.EINVAL
} }
s, err := netreflect.SocketOf(c.Conn) so, ok := sockOpts[ssoTOS]
if err != nil { if !ok {
return 0, err return 0, errOpNoSupport
} }
return getInt(s, &sockOpts[ssoTOS]) return so.GetInt(c.Conn)
} }
// SetTOS sets the type-of-service field value for future outgoing // SetTOS sets the type-of-service field value for future outgoing
...@@ -30,11 +24,11 @@ func (c *genericOpt) SetTOS(tos int) error { ...@@ -30,11 +24,11 @@ func (c *genericOpt) SetTOS(tos int) error {
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.SocketOf(c.Conn) so, ok := sockOpts[ssoTOS]
if err != nil { if !ok {
return err return errOpNoSupport
} }
return setInt(s, &sockOpts[ssoTOS], tos) return so.SetInt(c.Conn, tos)
} }
// TTL returns the time-to-live field value for outgoing packets. // TTL returns the time-to-live field value for outgoing packets.
...@@ -42,11 +36,11 @@ func (c *genericOpt) TTL() (int, error) { ...@@ -42,11 +36,11 @@ func (c *genericOpt) TTL() (int, error) {
if !c.ok() { if !c.ok() {
return 0, syscall.EINVAL return 0, syscall.EINVAL
} }
s, err := netreflect.SocketOf(c.Conn) so, ok := sockOpts[ssoTTL]
if err != nil { if !ok {
return 0, err return 0, errOpNoSupport
} }
return getInt(s, &sockOpts[ssoTTL]) return so.GetInt(c.Conn)
} }
// SetTTL sets the time-to-live field value for future outgoing // SetTTL sets the time-to-live field value for future outgoing
...@@ -55,9 +49,9 @@ func (c *genericOpt) SetTTL(ttl int) error { ...@@ -55,9 +49,9 @@ func (c *genericOpt) SetTTL(ttl int) error {
if !c.ok() { if !c.ok() {
return syscall.EINVAL return syscall.EINVAL
} }
s, err := netreflect.SocketOf(c.Conn) so, ok := sockOpts[ssoTTL]
if err != nil { if !ok {
return err return errOpNoSupport
} }
return setInt(s, &sockOpts[ssoTTL], ttl) return so.SetInt(c.Conn, ttl)
} }
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl plan9
package ipv4
// TOS returns the type-of-service field value for outgoing packets.
func (c *genericOpt) TOS() (int, error) {
return 0, errOpNoSupport
}
// SetTOS sets the type-of-service field value for future outgoing
// packets.
func (c *genericOpt) SetTOS(tos int) error {
return errOpNoSupport
}
// TTL returns the time-to-live field value for outgoing packets.
func (c *genericOpt) TTL() (int, error) {
return 0, errOpNoSupport
}
// SetTTL sets the time-to-live field value for future outgoing
// packets.
func (c *genericOpt) SetTTL(ttl int) error {
return errOpNoSupport
}
...@@ -10,6 +10,8 @@ import ( ...@@ -10,6 +10,8 @@ import (
"net" "net"
"runtime" "runtime"
"syscall" "syscall"
"golang.org/x/net/internal/socket"
) )
const ( const (
...@@ -64,12 +66,12 @@ func (h *Header) Marshal() ([]byte, error) { ...@@ -64,12 +66,12 @@ func (h *Header) Marshal() ([]byte, error) {
flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13) flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13)
switch runtime.GOOS { switch runtime.GOOS {
case "darwin", "dragonfly", "netbsd": case "darwin", "dragonfly", "netbsd":
nativeEndian.PutUint16(b[2:4], uint16(h.TotalLen)) socket.NativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
nativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff)) socket.NativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
case "freebsd": case "freebsd":
if freebsdVersion < 1100000 { if freebsdVersion < 1100000 {
nativeEndian.PutUint16(b[2:4], uint16(h.TotalLen)) socket.NativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
nativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff)) socket.NativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
} else { } else {
binary.BigEndian.PutUint16(b[2:4], uint16(h.TotalLen)) binary.BigEndian.PutUint16(b[2:4], uint16(h.TotalLen))
binary.BigEndian.PutUint16(b[6:8], uint16(flagsAndFragOff)) binary.BigEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
...@@ -118,15 +120,15 @@ func ParseHeader(b []byte) (*Header, error) { ...@@ -118,15 +120,15 @@ func ParseHeader(b []byte) (*Header, error) {
} }
switch runtime.GOOS { switch runtime.GOOS {
case "darwin", "dragonfly", "netbsd": case "darwin", "dragonfly", "netbsd":
h.TotalLen = int(nativeEndian.Uint16(b[2:4])) + hdrlen h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4])) + hdrlen
h.FragOff = int(nativeEndian.Uint16(b[6:8])) h.FragOff = int(socket.NativeEndian.Uint16(b[6:8]))
case "freebsd": case "freebsd":
if freebsdVersion < 1100000 { if freebsdVersion < 1100000 {
h.TotalLen = int(nativeEndian.Uint16(b[2:4])) h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
if freebsdVersion < 1000000 { if freebsdVersion < 1000000 {
h.TotalLen += hdrlen h.TotalLen += hdrlen
} }
h.FragOff = int(nativeEndian.Uint16(b[6:8])) h.FragOff = int(socket.NativeEndian.Uint16(b[6:8]))
} else { } else {
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4])) h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
h.FragOff = int(binary.BigEndian.Uint16(b[6:8])) h.FragOff = int(binary.BigEndian.Uint16(b[6:8]))
......
...@@ -12,6 +12,8 @@ import ( ...@@ -12,6 +12,8 @@ import (
"runtime" "runtime"
"strings" "strings"
"testing" "testing"
"golang.org/x/net/internal/socket"
) )
type headerTest struct { type headerTest struct {
...@@ -87,7 +89,7 @@ var headerLittleEndianTest = headerTest{ ...@@ -87,7 +89,7 @@ var headerLittleEndianTest = headerTest{
func TestMarshalHeader(t *testing.T) { func TestMarshalHeader(t *testing.T) {
tt := &headerLittleEndianTest tt := &headerLittleEndianTest
if nativeEndian != binary.LittleEndian { if socket.NativeEndian != binary.LittleEndian {
t.Skip("no test for non-little endian machine yet") t.Skip("no test for non-little endian machine yet")
} }
...@@ -118,7 +120,7 @@ func TestMarshalHeader(t *testing.T) { ...@@ -118,7 +120,7 @@ func TestMarshalHeader(t *testing.T) {
func TestParseHeader(t *testing.T) { func TestParseHeader(t *testing.T) {
tt := &headerLittleEndianTest tt := &headerLittleEndianTest
if nativeEndian != binary.LittleEndian { if socket.NativeEndian != binary.LittleEndian {
t.Skip("no test for big endian machine yet") t.Skip("no test for big endian machine yet")
} }
......
...@@ -5,10 +5,8 @@ ...@@ -5,10 +5,8 @@
package ipv4 package ipv4
import ( import (
"encoding/binary"
"errors" "errors"
"net" "net"
"unsafe"
) )
var ( var (
...@@ -23,20 +21,8 @@ var ( ...@@ -23,20 +21,8 @@ var (
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html. // See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
freebsdVersion uint32 freebsdVersion uint32
nativeEndian binary.ByteOrder
) )
func init() {
i := uint32(1)
b := (*[4]byte)(unsafe.Pointer(&i))
if b[0] == 1 {
nativeEndian = binary.LittleEndian
} else {
nativeEndian = binary.BigEndian
}
}
func boolint(b bool) int { func boolint(b bool) int {
if b { if b {
return 1 return 1
......
...@@ -27,7 +27,7 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net. ...@@ -27,7 +27,7 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.
return 0, nil, nil, err return 0, nil, nil, err
} }
case *net.IPConn: case *net.IPConn:
if sockOpts[ssoStripHeader].name > 0 { if _, ok := sockOpts[ssoStripHeader]; ok {
if n, oobn, _, src, err = c.ReadMsgIP(b, oob); err != nil { if n, oobn, _, src, err = c.ReadMsgIP(b, oob); err != nil {
return 0, nil, nil, err return 0, nil, nil, err
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package ipv4 package ipv4
import "golang.org/x/net/internal/socket"
// Sticky socket options // Sticky socket options
const ( const (
ssoTOS = iota // header field for unicast packet ssoTOS = iota // header field for unicast packet
...@@ -24,16 +26,12 @@ const ( ...@@ -24,16 +26,12 @@ const (
ssoLeaveSourceGroup // source-specific multicast ssoLeaveSourceGroup // source-specific multicast
ssoBlockSourceGroup // any-source or source-specific multicast ssoBlockSourceGroup // any-source or source-specific multicast
ssoUnblockSourceGroup // any-source or source-specific multicast ssoUnblockSourceGroup // any-source or source-specific multicast
ssoMax ssoAttachFilter // attach BPF for filtering inbound traffic
) )
// Sticky socket option value types // Sticky socket option value types
const ( const (
ssoTypeByte = iota + 1 ssoTypeIPMreq = iota + 1
ssoTypeInt
ssoTypeInterface
ssoTypeICMPFilter
ssoTypeIPMreq
ssoTypeIPMreqn ssoTypeIPMreqn
ssoTypeGroupReq ssoTypeGroupReq
ssoTypeGroupSourceReq ssoTypeGroupSourceReq
...@@ -41,6 +39,6 @@ const ( ...@@ -41,6 +39,6 @@ const (
// A sockOpt represents a binding for sticky socket option. // A sockOpt represents a binding for sticky socket option.
type sockOpt struct { type sockOpt struct {
name int // option name, must be equal or greater than 1 socket.Option
typ int // option value type, must be equal or greater than 1 typ int // hint for option value type; optional
} }
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd openbsd solaris windows
package ipv4
import (
"net"
"os"
"unsafe"
"golang.org/x/net/internal/iana"
)
func setsockoptIPMreq(s uintptr, name int, ifi *net.Interface, grp net.IP) error {
mreq := ipMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
if err := setIPMreqInterface(&mreq, ifi); err != nil {
return err
}
return os.NewSyscallError("setsockopt", setsockopt(s, iana.ProtocolIP, name, unsafe.Pointer(&mreq), sizeofIPMreq))
}
func getsockoptInterface(s uintptr, name int) (*net.Interface, error) {
var b [4]byte
l := uint32(4)
if err := getsockopt(s, iana.ProtocolIP, name, unsafe.Pointer(&b[0]), &l); err != nil {
return nil, os.NewSyscallError("getsockopt", err)
}
ifi, err := netIP4ToInterface(net.IPv4(b[0], b[1], b[2], b[3]))
if err != nil {
return nil, err
}
return ifi, nil
}
func setsockoptInterface(s uintptr, name int, ifi *net.Interface) error {
ip, err := netInterfaceToIP4(ifi)
if err != nil {
return err
}
var b [4]byte
copy(b[:], ip)
return os.NewSyscallError("setsockopt", setsockopt(s, iana.ProtocolIP, name, unsafe.Pointer(&b[0]), uint32(4)))
}
...@@ -8,115 +8,64 @@ package ipv4 ...@@ -8,115 +8,64 @@ package ipv4
import ( import (
"net" "net"
"os"
"unsafe" "unsafe"
"golang.org/x/net/internal/iana" "golang.org/x/net/bpf"
"golang.org/x/net/internal/socket"
) )
func getInt(s uintptr, opt *sockOpt) (int, error) { func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) {
if opt.name < 1 || (opt.typ != ssoTypeByte && opt.typ != ssoTypeInt) { switch so.typ {
return 0, errOpNoSupport
}
var i int32
var b byte
p := unsafe.Pointer(&i)
l := uint32(4)
if opt.typ == ssoTypeByte {
p = unsafe.Pointer(&b)
l = 1
}
if err := getsockopt(s, iana.ProtocolIP, opt.name, p, &l); err != nil {
return 0, os.NewSyscallError("getsockopt", err)
}
if opt.typ == ssoTypeByte {
return int(b), nil
}
return int(i), nil
}
func setInt(s uintptr, opt *sockOpt, v int) error {
if opt.name < 1 || (opt.typ != ssoTypeByte && opt.typ != ssoTypeInt) {
return errOpNoSupport
}
i := int32(v)
var b byte
p := unsafe.Pointer(&i)
l := uint32(4)
if opt.typ == ssoTypeByte {
b = byte(v)
p = unsafe.Pointer(&b)
l = 1
}
return os.NewSyscallError("setsockopt", setsockopt(s, iana.ProtocolIP, opt.name, p, l))
}
func getInterface(s uintptr, opt *sockOpt) (*net.Interface, error) {
if opt.name < 1 {
return nil, errOpNoSupport
}
switch opt.typ {
case ssoTypeInterface:
return getsockoptInterface(s, opt.name)
case ssoTypeIPMreqn: case ssoTypeIPMreqn:
return getsockoptIPMreqn(s, opt.name) return so.getIPMreqn(c)
default: default:
return nil, errOpNoSupport return so.getMulticastIf(c)
} }
} }
func setInterface(s uintptr, opt *sockOpt, ifi *net.Interface) error { func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error {
if opt.name < 1 { switch so.typ {
return errOpNoSupport
}
switch opt.typ {
case ssoTypeInterface:
return setsockoptInterface(s, opt.name, ifi)
case ssoTypeIPMreqn: case ssoTypeIPMreqn:
return setsockoptIPMreqn(s, opt.name, ifi, nil) return so.setIPMreqn(c, ifi, nil)
default: default:
return errOpNoSupport return so.setMulticastIf(c, ifi)
} }
} }
func getICMPFilter(s uintptr, opt *sockOpt) (*ICMPFilter, error) { func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) {
if opt.name < 1 || opt.typ != ssoTypeICMPFilter { b := make([]byte, so.Len)
return nil, errOpNoSupport n, err := so.Get(c, b)
if err != nil {
return nil, err
} }
var f ICMPFilter if n != sizeofICMPFilter {
l := uint32(sizeofICMPFilter) return nil, errOpNoSupport
if err := getsockopt(s, iana.ProtocolReserved, opt.name, unsafe.Pointer(&f.icmpFilter), &l); err != nil {
return nil, os.NewSyscallError("getsockopt", err)
} }
return &f, nil return (*ICMPFilter)(unsafe.Pointer(&b[0])), nil
} }
func setICMPFilter(s uintptr, opt *sockOpt, f *ICMPFilter) error { func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error {
if opt.name < 1 || opt.typ != ssoTypeICMPFilter { b := (*[sizeofICMPFilter]byte)(unsafe.Pointer(f))[:sizeofICMPFilter]
return errOpNoSupport return so.Set(c, b)
}
return os.NewSyscallError("setsockopt", setsockopt(s, iana.ProtocolReserved, opt.name, unsafe.Pointer(&f.icmpFilter), sizeofICMPFilter))
} }
func setGroup(s uintptr, opt *sockOpt, ifi *net.Interface, grp net.IP) error { func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
if opt.name < 1 { switch so.typ {
return errOpNoSupport
}
switch opt.typ {
case ssoTypeIPMreq: case ssoTypeIPMreq:
return setsockoptIPMreq(s, opt.name, ifi, grp) return so.setIPMreq(c, ifi, grp)
case ssoTypeIPMreqn: case ssoTypeIPMreqn:
return setsockoptIPMreqn(s, opt.name, ifi, grp) return so.setIPMreqn(c, ifi, grp)
case ssoTypeGroupReq: case ssoTypeGroupReq:
return setsockoptGroupReq(s, opt.name, ifi, grp) return so.setGroupReq(c, ifi, grp)
default: default:
return errOpNoSupport return errOpNoSupport
} }
} }
func setSourceGroup(s uintptr, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error { func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
if opt.name < 1 || opt.typ != ssoTypeGroupSourceReq { return so.setGroupSourceReq(c, ifi, grp, src)
return errOpNoSupport }
}
return setsockoptGroupSourceReq(s, opt.name, ifi, grp, src) func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error {
return so.setAttachFilter(c, f)
} }
...@@ -2,10 +2,41 @@ ...@@ -2,10 +2,41 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build nacl plan9 // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package ipv4 package ipv4
func setInt(s uintptr, opt *sockOpt, v int) error { import (
"net"
"golang.org/x/net/bpf"
"golang.org/x/net/internal/socket"
)
func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) {
return nil, errOpNoSupport
}
func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error {
return errOpNoSupport
}
func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) {
return nil, errOpNoSupport
}
func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error {
return errOpNoSupport
}
func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
return errOpNoSupport
}
func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
return errOpNoSupport
}
func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error {
return errOpNoSupport return errOpNoSupport
} }
...@@ -6,7 +6,43 @@ ...@@ -6,7 +6,43 @@
package ipv4 package ipv4
import "net" import (
"net"
"unsafe"
"golang.org/x/net/internal/socket"
)
func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
mreq := ipMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
if err := setIPMreqInterface(&mreq, ifi); err != nil {
return err
}
b := (*[sizeofIPMreq]byte)(unsafe.Pointer(&mreq))[:sizeofIPMreq]
return so.Set(c, b)
}
func (so *sockOpt) getMulticastIf(c *socket.Conn) (*net.Interface, error) {
var b [4]byte
if _, err := so.Get(c, b[:]); err != nil {
return nil, err
}
ifi, err := netIP4ToInterface(net.IPv4(b[0], b[1], b[2], b[3]))
if err != nil {
return nil, err
}
return ifi, nil
}
func (so *sockOpt) setMulticastIf(c *socket.Conn, ifi *net.Interface) error {
ip, err := netInterfaceToIP4(ifi)
if err != nil {
return err
}
var b [4]byte
copy(b[:], ip)
return so.Set(c, b[:])
}
func setIPMreqInterface(mreq *ipMreq, ifi *net.Interface) error { func setIPMreqInterface(mreq *ipMreq, ifi *net.Interface) error {
if ifi == nil { if ifi == nil {
......
// Copyright 2012 The Go Authors. All rights reserved. // Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
...@@ -6,16 +6,20 @@ ...@@ -6,16 +6,20 @@
package ipv4 package ipv4
import "net" import (
"net"
func setsockoptIPMreq(s uintptr, name int, ifi *net.Interface, grp net.IP) error { "golang.org/x/net/internal/socket"
)
func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
return errOpNoSupport return errOpNoSupport
} }
func getsockoptInterface(s uintptr, name int) (*net.Interface, error) { func (so *sockOpt) getMulticastIf(c *socket.Conn) (*net.Interface, error) {
return nil, errOpNoSupport return nil, errOpNoSupport
} }
func setsockoptInterface(s uintptr, name int, ifi *net.Interface) error { func (so *sockOpt) setMulticastIf(c *socket.Conn, ifi *net.Interface) error {
return errOpNoSupport return errOpNoSupport
} }
...@@ -8,18 +8,17 @@ package ipv4 ...@@ -8,18 +8,17 @@ package ipv4
import ( import (
"net" "net"
"os"
"unsafe" "unsafe"
"golang.org/x/net/internal/iana" "golang.org/x/net/internal/socket"
) )
func getsockoptIPMreqn(s uintptr, name int) (*net.Interface, error) { func (so *sockOpt) getIPMreqn(c *socket.Conn) (*net.Interface, error) {
var mreqn ipMreqn b := make([]byte, so.Len)
l := uint32(sizeofIPMreqn) if _, err := so.Get(c, b); err != nil {
if err := getsockopt(s, iana.ProtocolIP, name, unsafe.Pointer(&mreqn), &l); err != nil { return nil, err
return nil, os.NewSyscallError("getsockopt", err)
} }
mreqn := (*ipMreqn)(unsafe.Pointer(&b[0]))
if mreqn.Ifindex == 0 { if mreqn.Ifindex == 0 {
return nil, nil return nil, nil
} }
...@@ -30,7 +29,7 @@ func getsockoptIPMreqn(s uintptr, name int) (*net.Interface, error) { ...@@ -30,7 +29,7 @@ func getsockoptIPMreqn(s uintptr, name int) (*net.Interface, error) {
return ifi, nil return ifi, nil
} }
func setsockoptIPMreqn(s uintptr, name int, ifi *net.Interface, grp net.IP) error { func (so *sockOpt) setIPMreqn(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
var mreqn ipMreqn var mreqn ipMreqn
if ifi != nil { if ifi != nil {
mreqn.Ifindex = int32(ifi.Index) mreqn.Ifindex = int32(ifi.Index)
...@@ -38,5 +37,6 @@ func setsockoptIPMreqn(s uintptr, name int, ifi *net.Interface, grp net.IP) erro ...@@ -38,5 +37,6 @@ func setsockoptIPMreqn(s uintptr, name int, ifi *net.Interface, grp net.IP) erro
if grp != nil { if grp != nil {
mreqn.Multiaddr = [4]byte{grp[0], grp[1], grp[2], grp[3]} mreqn.Multiaddr = [4]byte{grp[0], grp[1], grp[2], grp[3]}
} }
return os.NewSyscallError("setsockopt", setsockopt(s, iana.ProtocolIP, name, unsafe.Pointer(&mreqn), sizeofIPMreqn)) b := (*[sizeofIPMreqn]byte)(unsafe.Pointer(&mreqn))[:sizeofIPMreqn]
return so.Set(c, b)
} }
...@@ -6,12 +6,16 @@ ...@@ -6,12 +6,16 @@
package ipv4 package ipv4
import "net" import (
"net"
func getsockoptIPMreqn(s uintptr, name int) (*net.Interface, error) { "golang.org/x/net/internal/socket"
)
func (so *sockOpt) getIPMreqn(c *socket.Conn) (*net.Interface, error) {
return nil, errOpNoSupport return nil, errOpNoSupport
} }
func setsockoptIPMreqn(s uintptr, name int, ifi *net.Interface, grp net.IP) error { func (so *sockOpt) setIPMreqn(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
return errOpNoSupport return errOpNoSupport
} }
// 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 linux
package ipv4
import (
"unsafe"
"golang.org/x/net/bpf"
"golang.org/x/net/internal/socket"
)
func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
prog := sockFProg{
Len: uint16(len(f)),
Filter: (*sockFilter)(unsafe.Pointer(&f[0])),
}
b := (*[sizeofSockFprog]byte)(unsafe.Pointer(&prog))[:sizeofSockFprog]
return so.Set(c, b)
}
// Copyright 2016 The Go Authors. All rights reserved. // Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
package ipv4 package ipv4
import "golang.org/x/net/bpf" import (
"golang.org/x/net/bpf"
"golang.org/x/net/internal/socket"
)
// SetBPF attaches a BPF program to the connection. func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error {
//
// Only supported on Linux.
func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error {
return errOpNoSupport return errOpNoSupport
} }
...@@ -2,13 +2,16 @@ ...@@ -2,13 +2,16 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build dragonfly netbsd // +build netbsd openbsd
package ipv4 package ipv4
import ( import (
"net" "net"
"syscall" "syscall"
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
) )
var ( var (
...@@ -18,17 +21,17 @@ var ( ...@@ -18,17 +21,17 @@ var (
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface}, ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
} }
sockOpts = [ssoMax]sockOpt{ sockOpts = map[int]*sockOpt{
ssoTOS: {sysIP_TOS, ssoTypeInt}, ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
ssoTTL: {sysIP_TTL, ssoTypeInt}, ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte}, ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface}, ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt}, ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 1}},
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt}, ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt}, ssoReceiveDst: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt}, ssoReceiveInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt}, ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq}, ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq}, ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
} }
) )
...@@ -10,6 +10,9 @@ import ( ...@@ -10,6 +10,9 @@ import (
"strings" "strings"
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
) )
var ( var (
...@@ -19,19 +22,19 @@ var ( ...@@ -19,19 +22,19 @@ var (
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface}, ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
} }
sockOpts = [ssoMax]sockOpt{ sockOpts = map[int]*sockOpt{
ssoTOS: {sysIP_TOS, ssoTypeInt}, ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
ssoTTL: {sysIP_TTL, ssoTypeInt}, ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte}, ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface}, ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt}, ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt}, ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt}, ssoReceiveDst: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt}, ssoReceiveInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt}, ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
ssoStripHeader: {sysIP_STRIPHDR, ssoTypeInt}, ssoStripHeader: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_STRIPHDR, Len: 4}},
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq}, ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq}, ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
} }
) )
...@@ -57,21 +60,14 @@ func init() { ...@@ -57,21 +60,14 @@ func init() {
ctlOpts[ctlPacketInfo].length = sizeofInetPktinfo ctlOpts[ctlPacketInfo].length = sizeofInetPktinfo
ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
ctlOpts[ctlPacketInfo].parse = parsePacketInfo ctlOpts[ctlPacketInfo].parse = parsePacketInfo
sockOpts[ssoPacketInfo].name = sysIP_RECVPKTINFO sockOpts[ssoPacketInfo] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVPKTINFO, Len: 4}}
sockOpts[ssoPacketInfo].typ = ssoTypeInt sockOpts[ssoMulticastInterface] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: sizeofIPMreqn}, typ: ssoTypeIPMreqn}
sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn sockOpts[ssoJoinGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}
sockOpts[ssoJoinGroup].name = sysMCAST_JOIN_GROUP sockOpts[ssoLeaveGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}
sockOpts[ssoJoinGroup].typ = ssoTypeGroupReq sockOpts[ssoJoinSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
sockOpts[ssoLeaveGroup].name = sysMCAST_LEAVE_GROUP sockOpts[ssoLeaveSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
sockOpts[ssoLeaveGroup].typ = ssoTypeGroupReq sockOpts[ssoBlockSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
sockOpts[ssoJoinSourceGroup].name = sysMCAST_JOIN_SOURCE_GROUP sockOpts[ssoUnblockSourceGroup] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}
sockOpts[ssoJoinSourceGroup].typ = ssoTypeGroupSourceReq
sockOpts[ssoLeaveSourceGroup].name = sysMCAST_LEAVE_SOURCE_GROUP
sockOpts[ssoLeaveSourceGroup].typ = ssoTypeGroupSourceReq
sockOpts[ssoBlockSourceGroup].name = sysMCAST_BLOCK_SOURCE
sockOpts[ssoBlockSourceGroup].typ = ssoTypeGroupSourceReq
sockOpts[ssoUnblockSourceGroup].name = sysMCAST_UNBLOCK_SOURCE
sockOpts[ssoUnblockSourceGroup].typ = ssoTypeGroupSourceReq
} }
func (pi *inetPktinfo) setIfindex(i int) { func (pi *inetPktinfo) setIfindex(i int) {
......
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv4
import (
"net"
"syscall"
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
)
var (
ctlOpts = [ctlMax]ctlOpt{
ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
}
sockOpts = map[int]*sockOpt{
ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
ssoReceiveDst: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
ssoReceiveInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
}
)
...@@ -10,6 +10,9 @@ import ( ...@@ -10,6 +10,9 @@ import (
"strings" "strings"
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
) )
var ( var (
...@@ -19,29 +22,29 @@ var ( ...@@ -19,29 +22,29 @@ var (
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface}, ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
} }
sockOpts = [ssoMax]sockOpt{ sockOpts = map[int]*sockOpt{
ssoTOS: {sysIP_TOS, ssoTypeInt}, ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
ssoTTL: {sysIP_TTL, ssoTypeInt}, ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte}, ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface}, ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt}, ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt}, ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt}, ssoReceiveDst: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVDSTADDR, Len: 4}},
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt}, ssoReceiveInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVIF, Len: 4}},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt}, ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq}, ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
ssoLeaveGroup: {sysMCAST_LEAVE_GROUP, ssoTypeGroupReq}, ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
ssoJoinSourceGroup: {sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq}, ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoLeaveSourceGroup: {sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq}, ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoBlockSourceGroup: {sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq}, ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoUnblockSourceGroup: {sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq}, ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
} }
) )
func init() { func init() {
freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate") freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
if freebsdVersion >= 1000000 { if freebsdVersion >= 1000000 {
sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn sockOpts[ssoMulticastInterface] = &sockOpt{Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: sizeofIPMreqn}, typ: ssoTypeIPMreqn}
} }
if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" { if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
archs, _ := syscall.Sysctl("kern.supported_archs") archs, _ := syscall.Sysctl("kern.supported_archs")
......
...@@ -8,6 +8,9 @@ import ( ...@@ -8,6 +8,9 @@ import (
"net" "net"
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
) )
var ( var (
...@@ -16,22 +19,23 @@ var ( ...@@ -16,22 +19,23 @@ var (
ctlPacketInfo: {sysIP_PKTINFO, sizeofInetPktinfo, marshalPacketInfo, parsePacketInfo}, ctlPacketInfo: {sysIP_PKTINFO, sizeofInetPktinfo, marshalPacketInfo, parsePacketInfo},
} }
sockOpts = [ssoMax]sockOpt{ sockOpts = map[int]*sockOpt{
ssoTOS: {sysIP_TOS, ssoTypeInt}, ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
ssoTTL: {sysIP_TTL, ssoTypeInt}, ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeInt}, ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 4}},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeIPMreqn}, ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: sizeofIPMreqn}, typ: ssoTypeIPMreqn},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt}, ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt}, ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
ssoPacketInfo: {sysIP_PKTINFO, ssoTypeInt}, ssoPacketInfo: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_PKTINFO, Len: 4}},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt}, ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
ssoICMPFilter: {sysICMP_FILTER, ssoTypeICMPFilter}, ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolReserved, Name: sysICMP_FILTER, Len: sizeofICMPFilter}},
ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq}, ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
ssoLeaveGroup: {sysMCAST_LEAVE_GROUP, ssoTypeGroupReq}, ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
ssoJoinSourceGroup: {sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq}, ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoLeaveSourceGroup: {sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq}, ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoBlockSourceGroup: {sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq}, ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoUnblockSourceGroup: {sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq}, ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoAttachFilter: {Option: socket.Option{Level: sysSOL_SOCKET, Name: sysSO_ATTACH_FILTER, Len: sizeofSockFprog}},
} }
) )
......
// 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.
#include "textflag.h"
TEXT ·socketcall(SB),NOSPLIT,$0-36
JMP syscall·socketcall(SB)
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv4
import (
"net"
"syscall"
)
var (
ctlOpts = [ctlMax]ctlOpt{
ctlTTL: {sysIP_RECVTTL, 1, marshalTTL, parseTTL},
ctlDst: {sysIP_RECVDSTADDR, net.IPv4len, marshalDst, parseDst},
ctlInterface: {sysIP_RECVIF, syscall.SizeofSockaddrDatalink, marshalInterface, parseInterface},
}
sockOpts = [ssoMax]sockOpt{
ssoTOS: {sysIP_TOS, ssoTypeInt},
ssoTTL: {sysIP_TTL, ssoTypeInt},
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeByte},
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt},
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq},
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq},
}
)
...@@ -8,6 +8,9 @@ import ( ...@@ -8,6 +8,9 @@ import (
"net" "net"
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
) )
var ( var (
...@@ -16,21 +19,21 @@ var ( ...@@ -16,21 +19,21 @@ var (
ctlPacketInfo: {sysIP_PKTINFO, sizeofInetPktinfo, marshalPacketInfo, parsePacketInfo}, ctlPacketInfo: {sysIP_PKTINFO, sizeofInetPktinfo, marshalPacketInfo, parsePacketInfo},
} }
sockOpts = [ssoMax]sockOpt{ sockOpts = map[int]sockOpt{
ssoTOS: {sysIP_TOS, ssoTypeInt}, ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
ssoTTL: {sysIP_TTL, ssoTypeInt}, ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeByte}, ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 1}},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface}, ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeByte}, ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 1}},
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt}, ssoReceiveTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVTTL, Len: 4}},
ssoPacketInfo: {sysIP_RECVPKTINFO, ssoTypeInt}, ssoPacketInfo: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_RECVPKTINFO, Len: 4}},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt}, ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq}, ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
ssoLeaveGroup: {sysMCAST_LEAVE_GROUP, ssoTypeGroupReq}, ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq},
ssoJoinSourceGroup: {sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq}, ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoLeaveSourceGroup: {sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq}, ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoBlockSourceGroup: {sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq}, ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
ssoUnblockSourceGroup: {sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq}, ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysMCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq},
} }
) )
......
// 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)
...@@ -8,54 +8,47 @@ package ipv4 ...@@ -8,54 +8,47 @@ package ipv4
import ( import (
"net" "net"
"os"
"unsafe" "unsafe"
"golang.org/x/net/internal/iana" "golang.org/x/net/internal/socket"
) )
var freebsd32o64 bool var freebsd32o64 bool
func setsockoptGroupReq(s uintptr, name int, ifi *net.Interface, grp net.IP) error { func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
var gr groupReq var gr groupReq
if ifi != nil { if ifi != nil {
gr.Interface = uint32(ifi.Index) gr.Interface = uint32(ifi.Index)
} }
gr.setGroup(grp) gr.setGroup(grp)
var p unsafe.Pointer var b []byte
var l uint32
if freebsd32o64 { if freebsd32o64 {
var d [sizeofGroupReq + 4]byte var d [sizeofGroupReq + 4]byte
s := (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr)) s := (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr))
copy(d[:4], s[:4]) copy(d[:4], s[:4])
copy(d[8:], s[4:]) copy(d[8:], s[4:])
p = unsafe.Pointer(&d[0]) b = d[:]
l = sizeofGroupReq + 4
} else { } else {
p = unsafe.Pointer(&gr) b = (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr))[:sizeofGroupReq]
l = sizeofGroupReq
} }
return os.NewSyscallError("setsockopt", setsockopt(s, iana.ProtocolIP, name, p, l)) return so.Set(c, b)
} }
func setsockoptGroupSourceReq(s uintptr, name int, ifi *net.Interface, grp, src net.IP) error { func (so *sockOpt) setGroupSourceReq(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
var gsr groupSourceReq var gsr groupSourceReq
if ifi != nil { if ifi != nil {
gsr.Interface = uint32(ifi.Index) gsr.Interface = uint32(ifi.Index)
} }
gsr.setSourceGroup(grp, src) gsr.setSourceGroup(grp, src)
var p unsafe.Pointer var b []byte
var l uint32
if freebsd32o64 { if freebsd32o64 {
var d [sizeofGroupSourceReq + 4]byte var d [sizeofGroupSourceReq + 4]byte
s := (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr)) s := (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))
copy(d[:4], s[:4]) copy(d[:4], s[:4])
copy(d[8:], s[4:]) copy(d[8:], s[4:])
p = unsafe.Pointer(&d[0]) b = d[:]
l = sizeofGroupSourceReq + 4
} else { } else {
p = unsafe.Pointer(&gsr) b = (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))[:sizeofGroupSourceReq]
l = sizeofGroupSourceReq
} }
return os.NewSyscallError("setsockopt", setsockopt(s, iana.ProtocolIP, name, p, l)) return so.Set(c, b)
} }
...@@ -6,12 +6,16 @@ ...@@ -6,12 +6,16 @@
package ipv4 package ipv4
import "net" import (
"net"
func setsockoptGroupReq(s uintptr, name int, ifi *net.Interface, grp net.IP) error { "golang.org/x/net/internal/socket"
)
func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
return errOpNoSupport return errOpNoSupport
} }
func setsockoptGroupSourceReq(s uintptr, name int, ifi *net.Interface, grp, src net.IP) error { func (so *sockOpt) setGroupSourceReq(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error {
return errOpNoSupport return errOpNoSupport
} }
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build nacl plan9 // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package ipv4 package ipv4
var ( var (
ctlOpts = [ctlMax]ctlOpt{} ctlOpts = [ctlMax]ctlOpt{}
sockOpts = [ssoMax]sockOpt{} sockOpts = map[int]*sockOpt{}
) )
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
package ipv4 package ipv4
import (
"golang.org/x/net/internal/iana"
"golang.org/x/net/internal/socket"
)
const ( const (
// See ws2tcpip.h. // See ws2tcpip.h.
sysIP_OPTIONS = 0x1 sysIP_OPTIONS = 0x1
...@@ -45,15 +50,15 @@ type ipMreqSource struct { ...@@ -45,15 +50,15 @@ type ipMreqSource struct {
var ( var (
ctlOpts = [ctlMax]ctlOpt{} ctlOpts = [ctlMax]ctlOpt{}
sockOpts = [ssoMax]sockOpt{ sockOpts = map[int]*sockOpt{
ssoTOS: {sysIP_TOS, ssoTypeInt}, ssoTOS: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TOS, Len: 4}},
ssoTTL: {sysIP_TTL, ssoTypeInt}, ssoTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_TTL, Len: 4}},
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeInt}, ssoMulticastTTL: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_TTL, Len: 4}},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface}, ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_IF, Len: 4}},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt}, ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_MULTICAST_LOOP, Len: 4}},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt}, ssoHeaderPrepend: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_HDRINCL, Len: 4}},
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq}, ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_ADD_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq}, ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIP, Name: sysIP_DROP_MEMBERSHIP, Len: sizeofIPMreq}, typ: ssoTypeIPMreq},
} }
) )
......
// 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"
"unsafe"
)
const (
sysGETSOCKOPT = 0xf
sysSETSOCKOPT = 0xe
)
func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
if _, errno := socketcall(sysGETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
return error(errno)
}
return nil
}
func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
if _, errno := socketcall(sysSETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
return error(errno)
}
return nil
}
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv4
import (
"syscall"
"unsafe"
)
//go:cgo_import_dynamic libc___xnet_getsockopt __xnet_getsockopt "libsocket.so"
//go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so"
//go:linkname procGetsockopt libc___xnet_getsockopt
//go:linkname procSetsockopt libc_setsockopt
var (
procGetsockopt uintptr
procSetsockopt uintptr
)
func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)
func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
_, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procGetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0)
if errno != 0 {
return error(errno)
}
return nil
}
func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
if _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procSetsockopt)), 5, s, uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
return error(errno)
}
return nil
}
// 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,!386 netbsd openbsd
package ipv4
import (
"syscall"
"unsafe"
)
func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
return error(errno)
}
return nil
}
func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
return error(errno)
}
return nil
}
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv4
import (
"syscall"
"unsafe"
)
func getsockopt(s uintptr, level, name int, v unsafe.Pointer, l *uint32) error {
return syscall.Getsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(v), (*int32)(unsafe.Pointer(l)))
}
func setsockopt(s uintptr, level, name int, v unsafe.Pointer, l uint32) error {
return syscall.Setsockopt(syscall.Handle(s), int32(level), int32(name), (*byte)(v), int32(l))
}
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x104 sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x108 sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x104 sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x108 sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x104 sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x108 sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x108 sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x104 sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x104 sizeofGroupSourceReq = 0x104
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x8
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x108 sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x108 sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
...@@ -70,6 +70,8 @@ const ( ...@@ -70,6 +70,8 @@ const (
sizeofGroupSourceReq = 0x108 sizeofGroupSourceReq = 0x108
sizeofICMPFilter = 0x4 sizeofICMPFilter = 0x4
sizeofSockFprog = 0x10
) )
type kernelSockaddrStorage struct { type kernelSockaddrStorage struct {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment