瀏覽代碼

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

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/173100043
Mikio Hara 11 年之前
父節點
當前提交
153a6a6152
共有 8 個文件被更改,包括 153 次插入4 次删除
  1. 6 0
      ipv4/sockopt.go
  2. 17 0
      ipv4/sockopt_ssmreq_stub.go
  3. 33 0
      ipv4/sockopt_ssmreq_unix.go
  4. 9 0
      ipv4/sockopt_unix.go
  5. 5 0
      ipv4/sockopt_windows.go
  6. 31 0
      ipv4/sys_darwin.go
  7. 25 2
      ipv4/sys_freebsd.go
  8. 27 2
      ipv4/sys_linux.go

+ 6 - 0
ipv4/sockopt.go

@@ -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 - 0
ipv4/sockopt_ssmreq_stub.go

@@ -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 - 0
ipv4/sockopt_ssmreq_unix.go

@@ -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))
+}

+ 9 - 0
ipv4/sockopt_unix.go

@@ -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)
+}

+ 5 - 0
ipv4/sockopt_windows.go

@@ -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
+}

+ 31 - 0
ipv4/sys_darwin.go

@@ -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)
+}

+ 25 - 2
ipv4/sys_freebsd.go

@@ -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)
+}

+ 27 - 2
ipv4/sys_linux.go

@@ -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)
+}