mirror of
https://github.com/golang/net.git
synced 2026-03-31 18:37:08 +09:00
x/net/ipv4: add sticky source-specific multicast socket options
LGTM=iant R=iant CC=golang-codereviews https://golang.org/cl/173100043
This commit is contained in:
@@ -18,6 +18,10 @@ const (
|
||||
ssoHeaderPrepend // ipv4 header
|
||||
ssoJoinGroup // any-source multicast
|
||||
ssoLeaveGroup // any-source multicast
|
||||
ssoJoinSourceGroup // source-specific multicast
|
||||
ssoLeaveSourceGroup // source-specific multicast
|
||||
ssoBlockSourceGroup // any-source or source-specific multicast
|
||||
ssoUnblockSourceGroup // any-source or source-specific multicast
|
||||
ssoMax
|
||||
)
|
||||
|
||||
@@ -28,6 +32,8 @@ const (
|
||||
ssoTypeInterface
|
||||
ssoTypeIPMreq
|
||||
ssoTypeIPMreqn
|
||||
ssoTypeGroupReq
|
||||
ssoTypeGroupSourceReq
|
||||
)
|
||||
|
||||
// A sockOpt represents a binding for sticky socket option.
|
||||
|
||||
17
ipv4/sockopt_ssmreq_stub.go
Normal file
17
ipv4/sockopt_ssmreq_stub.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !darwin,!freebsd,!linux
|
||||
|
||||
package ipv4
|
||||
|
||||
import "net"
|
||||
|
||||
func setsockoptGroupReq(fd, name int, ifi *net.Interface, grp net.IP) error {
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
func setsockoptGroupSourceReq(fd, name int, ifi *net.Interface, grp, src net.IP) error {
|
||||
return errOpNoSupport
|
||||
}
|
||||
33
ipv4/sockopt_ssmreq_unix.go
Normal file
33
ipv4/sockopt_ssmreq_unix.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
)
|
||||
|
||||
func setsockoptGroupReq(fd, name int, ifi *net.Interface, grp net.IP) error {
|
||||
var gr sysGroupReq
|
||||
if ifi != nil {
|
||||
gr.Interface = uint32(ifi.Index)
|
||||
}
|
||||
gr.setGroup(grp)
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&gr), sysSizeofGroupReq))
|
||||
}
|
||||
|
||||
func setsockoptGroupSourceReq(fd, name int, ifi *net.Interface, grp, src net.IP) error {
|
||||
var gsr sysGroupSourceReq
|
||||
if ifi != nil {
|
||||
gsr.Interface = uint32(ifi.Index)
|
||||
}
|
||||
gsr.setSourceGroup(grp, src)
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, iana.ProtocolIP, name, unsafe.Pointer(&gsr), sysSizeofGroupSourceReq))
|
||||
}
|
||||
@@ -88,7 +88,16 @@ func setGroup(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
|
||||
return setsockoptIPMreq(fd, opt.name, ifi, grp)
|
||||
case ssoTypeIPMreqn:
|
||||
return setsockoptIPMreqn(fd, opt.name, ifi, grp)
|
||||
case ssoTypeGroupReq:
|
||||
return setsockoptGroupReq(fd, opt.name, ifi, grp)
|
||||
default:
|
||||
return errOpNoSupport
|
||||
}
|
||||
}
|
||||
|
||||
func setSourceGroup(fd int, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||
if opt.name < 1 || opt.typ != ssoTypeGroupSourceReq {
|
||||
return errOpNoSupport
|
||||
}
|
||||
return setsockoptGroupSourceReq(fd, opt.name, ifi, grp, src)
|
||||
}
|
||||
|
||||
@@ -53,3 +53,8 @@ func setGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp net.IP) e
|
||||
}
|
||||
return setsockoptIPMreq(fd, opt.name, ifi, grp)
|
||||
}
|
||||
|
||||
func setSourceGroup(fd syscall.Handle, opt *sockOpt, ifi *net.Interface, grp, src net.IP) error {
|
||||
// TODO(mikio): implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package ipv4
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type sysSockoptLen int32
|
||||
@@ -56,9 +57,39 @@ func init() {
|
||||
sockOpts[ssoPacketInfo].name = sysIP_RECVPKTINFO
|
||||
sockOpts[ssoPacketInfo].typ = ssoTypeInt
|
||||
sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn
|
||||
sockOpts[ssoJoinGroup].name = sysMCAST_JOIN_GROUP
|
||||
sockOpts[ssoJoinGroup].typ = ssoTypeGroupReq
|
||||
sockOpts[ssoLeaveGroup].name = sysMCAST_LEAVE_GROUP
|
||||
sockOpts[ssoLeaveGroup].typ = ssoTypeGroupReq
|
||||
sockOpts[ssoJoinSourceGroup].name = sysMCAST_JOIN_SOURCE_GROUP
|
||||
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 *sysInetPktinfo) setIfindex(i int) {
|
||||
pi.Ifindex = uint32(i)
|
||||
}
|
||||
|
||||
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||
sa := (*sysSockaddrInet)(unsafe.Pointer(&gr.Pad_cgo_0[0]))
|
||||
sa.Len = sysSizeofSockaddrInet
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], grp)
|
||||
}
|
||||
|
||||
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||
sa := (*sysSockaddrInet)(unsafe.Pointer(&gsr.Pad_cgo_0[0]))
|
||||
sa.Len = sysSizeofSockaddrInet
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], grp)
|
||||
sa = (*sysSockaddrInet)(unsafe.Pointer(&gsr.Pad_cgo_1[0]))
|
||||
sa.Len = sysSizeofSockaddrInet
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], src)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package ipv4
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type sysSockoptLen int32
|
||||
@@ -28,8 +29,12 @@ var (
|
||||
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt},
|
||||
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt},
|
||||
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
|
||||
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq},
|
||||
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq},
|
||||
ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
|
||||
ssoLeaveGroup: {sysMCAST_LEAVE_GROUP, ssoTypeGroupReq},
|
||||
ssoJoinSourceGroup: {sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||
ssoLeaveSourceGroup: {sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||
ssoBlockSourceGroup: {sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||
ssoUnblockSourceGroup: {sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -39,3 +44,21 @@ func init() {
|
||||
sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn
|
||||
}
|
||||
}
|
||||
|
||||
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||
sa := (*sysSockaddrInet)(unsafe.Pointer(&gr.Group))
|
||||
sa.Len = sysSizeofSockaddrInet
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], grp)
|
||||
}
|
||||
|
||||
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||
sa := (*sysSockaddrInet)(unsafe.Pointer(&gsr.Group))
|
||||
sa.Len = sysSizeofSockaddrInet
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], grp)
|
||||
sa = (*sysSockaddrInet)(unsafe.Pointer(&gsr.Source))
|
||||
sa.Len = sysSizeofSockaddrInet
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], src)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
|
||||
package ipv4
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type sysSockoptLen int32
|
||||
|
||||
var (
|
||||
@@ -21,11 +27,30 @@ var (
|
||||
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
|
||||
ssoPacketInfo: {sysIP_PKTINFO, ssoTypeInt},
|
||||
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
|
||||
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreqn},
|
||||
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreqn},
|
||||
ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
|
||||
ssoLeaveGroup: {sysMCAST_LEAVE_GROUP, ssoTypeGroupReq},
|
||||
ssoJoinSourceGroup: {sysMCAST_JOIN_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||
ssoLeaveSourceGroup: {sysMCAST_LEAVE_SOURCE_GROUP, ssoTypeGroupSourceReq},
|
||||
ssoBlockSourceGroup: {sysMCAST_BLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||
ssoUnblockSourceGroup: {sysMCAST_UNBLOCK_SOURCE, ssoTypeGroupSourceReq},
|
||||
}
|
||||
)
|
||||
|
||||
func (pi *sysInetPktinfo) setIfindex(i int) {
|
||||
pi.Ifindex = int32(i)
|
||||
}
|
||||
|
||||
func (gr *sysGroupReq) setGroup(grp net.IP) {
|
||||
sa := (*sysSockaddrInet)(unsafe.Pointer(&gr.Group))
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], grp)
|
||||
}
|
||||
|
||||
func (gsr *sysGroupSourceReq) setSourceGroup(grp, src net.IP) {
|
||||
sa := (*sysSockaddrInet)(unsafe.Pointer(&gsr.Group))
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], grp)
|
||||
sa = (*sysSockaddrInet)(unsafe.Pointer(&gsr.Source))
|
||||
sa.Family = syscall.AF_INET
|
||||
copy(sa.Addr[:], src)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user