Commit 153a6a61 authored by Mikio Hara's avatar Mikio Hara

x/net/ipv4: add sticky source-specific multicast socket options

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/173100043
parent 15ecf1c9
...@@ -18,6 +18,10 @@ const ( ...@@ -18,6 +18,10 @@ const (
ssoHeaderPrepend // ipv4 header ssoHeaderPrepend // ipv4 header
ssoJoinGroup // any-source multicast ssoJoinGroup // any-source multicast
ssoLeaveGroup // 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 ssoMax
) )
...@@ -28,6 +32,8 @@ const ( ...@@ -28,6 +32,8 @@ const (
ssoTypeInterface ssoTypeInterface
ssoTypeIPMreq ssoTypeIPMreq
ssoTypeIPMreqn ssoTypeIPMreqn
ssoTypeGroupReq
ssoTypeGroupSourceReq
) )
// A sockOpt represents a binding for sticky socket option. // A sockOpt represents a binding for sticky socket option.
......
// 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
}
// 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 { ...@@ -88,7 +88,16 @@ func setGroup(fd int, opt *sockOpt, ifi *net.Interface, grp net.IP) error {
return setsockoptIPMreq(fd, opt.name, ifi, grp) return setsockoptIPMreq(fd, opt.name, ifi, grp)
case ssoTypeIPMreqn: case ssoTypeIPMreqn:
return setsockoptIPMreqn(fd, opt.name, ifi, grp) return setsockoptIPMreqn(fd, opt.name, ifi, grp)
case ssoTypeGroupReq:
return setsockoptGroupReq(fd, opt.name, ifi, grp)
default: default:
return errOpNoSupport 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 ...@@ -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) 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 ...@@ -7,6 +7,7 @@ package ipv4
import ( import (
"net" "net"
"syscall" "syscall"
"unsafe"
) )
type sysSockoptLen int32 type sysSockoptLen int32
...@@ -56,9 +57,39 @@ func init() { ...@@ -56,9 +57,39 @@ func init() {
sockOpts[ssoPacketInfo].name = sysIP_RECVPKTINFO sockOpts[ssoPacketInfo].name = sysIP_RECVPKTINFO
sockOpts[ssoPacketInfo].typ = ssoTypeInt sockOpts[ssoPacketInfo].typ = ssoTypeInt
sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn 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) { func (pi *sysInetPktinfo) setIfindex(i int) {
pi.Ifindex = uint32(i) 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 ...@@ -7,6 +7,7 @@ package ipv4
import ( import (
"net" "net"
"syscall" "syscall"
"unsafe"
) )
type sysSockoptLen int32 type sysSockoptLen int32
...@@ -28,8 +29,12 @@ var ( ...@@ -28,8 +29,12 @@ var (
ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt}, ssoReceiveDst: {sysIP_RECVDSTADDR, ssoTypeInt},
ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt}, ssoReceiveInterface: {sysIP_RECVIF, ssoTypeInt},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt}, ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq}, ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq}, 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() { ...@@ -39,3 +44,21 @@ func init() {
sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn 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 @@ ...@@ -4,6 +4,12 @@
package ipv4 package ipv4
import (
"net"
"syscall"
"unsafe"
)
type sysSockoptLen int32 type sysSockoptLen int32
var ( var (
...@@ -21,11 +27,30 @@ var ( ...@@ -21,11 +27,30 @@ var (
ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt}, ssoReceiveTTL: {sysIP_RECVTTL, ssoTypeInt},
ssoPacketInfo: {sysIP_PKTINFO, ssoTypeInt}, ssoPacketInfo: {sysIP_PKTINFO, ssoTypeInt},
ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt}, ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreqn}, ssoJoinGroup: {sysMCAST_JOIN_GROUP, ssoTypeGroupReq},
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreqn}, 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) { func (pi *sysInetPktinfo) setIfindex(i int) {
pi.Ifindex = int32(i) 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)
}
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