Browse Source

go.net/ipv6: add ancillary data socket option binding tables

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/164540044
Mikio Hara 11 years ago
parent
commit
77024ba92f
6 changed files with 56 additions and 6 deletions
  1. 21 1
      ipv6/control.go
  2. 7 0
      ipv6/sys_bsd.go
  3. 18 5
      ipv6/sys_darwin.go
  4. 6 0
      ipv6/sys_linux.go
  5. 2 0
      ipv6/sys_stub.go
  6. 2 0
      ipv6/sys_windows.go

+ 21 - 1
ipv6/control.go

@@ -34,7 +34,7 @@ var (
 // 2292 and RFC 3542 for some practical reasons.
 
 type rawOpt struct {
-	sync.Mutex
+	sync.RWMutex
 	cflags ControlFlags
 }
 
@@ -55,6 +55,8 @@ const (
 	FlagPathMTU                               // pass the path MTU on the received packet path
 )
 
+const flagPacketInfo = FlagDst | FlagInterface
+
 // A ControlMessage represents per packet basis IP-level socket
 // options.
 type ControlMessage struct {
@@ -81,3 +83,21 @@ func (cm *ControlMessage) String() string {
 	}
 	return fmt.Sprintf("tclass: %#x, hoplim: %v, src: %v, dst: %v, ifindex: %v, nexthop: %v, mtu: %v", cm.TrafficClass, cm.HopLimit, cm.Src, cm.Dst, cm.IfIndex, cm.NextHop, cm.MTU)
 }
+
+// Ancillary data socket options
+const (
+	ctlTrafficClass = iota // header field
+	ctlHopLimit            // header field
+	ctlPacketInfo          // inbound or outbound packet path
+	ctlNextHop             // nexthop
+	ctlPathMTU             // path mtu
+	ctlMax
+)
+
+// A ctlOpt represents a binding for ancillary data socket option.
+type ctlOpt struct {
+	name    int // option name, must be equal or greater than 1
+	length  int // option length
+	marshal func([]byte, *ControlMessage) []byte
+	parse   func(*ControlMessage, []byte)
+}

+ 7 - 0
ipv6/sys_bsd.go

@@ -14,6 +14,13 @@ import (
 type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{
+		ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
+		ctlHopLimit:     {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
+		ctlPacketInfo:   {sysIPV6_PKTINFO, sysSizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
+		ctlNextHop:      {sysIPV6_NEXTHOP, sysSizeofSockaddrInet6, marshalNextHop, parseNextHop},
+	}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoTrafficClass:        {ianaProtocolIPv6, sysIPV6_TCLASS, ssoTypeInt},
 		ssoHopLimit:            {ianaProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},

+ 18 - 5
ipv6/sys_darwin.go

@@ -12,6 +12,11 @@ import (
 type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{
+		ctlHopLimit:   {sysIPV6_2292HOPLIMIT, 4, marshal2292HopLimit, parseHopLimit},
+		ctlPacketInfo: {sysIPV6_2292PKTINFO, sysSizeofInet6Pktinfo, marshal2292PacketInfo, parsePacketInfo},
+	}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoTrafficClass:       {ianaProtocolIPv6, sysIPV6_TCLASS, ssoTypeInt},
 		ssoHopLimit:           {ianaProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
@@ -44,14 +49,22 @@ func init() {
 	// introduced in OS X 10.7 (Darwin 11.0.0).
 	// See http://support.apple.com/kb/HT1633.
 	if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '1' {
+		ctlOpts[ctlTrafficClass].name = sysIPV6_TCLASS
+		ctlOpts[ctlTrafficClass].length = 4
+		ctlOpts[ctlTrafficClass].marshal = marshalTrafficClass
+		ctlOpts[ctlTrafficClass].parse = parseTrafficClass
+		ctlOpts[ctlHopLimit].name = sysIPV6_HOPLIMIT
+		ctlOpts[ctlHopLimit].marshal = marshalHopLimit
+		ctlOpts[ctlPacketInfo].name = sysIPV6_PKTINFO
+		ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
+		sockOpts[ssoReceiveTrafficClass].level = ianaProtocolIPv6
+		sockOpts[ssoReceiveTrafficClass].name = sysIPV6_RECVTCLASS
+		sockOpts[ssoReceiveTrafficClass].typ = ssoTypeInt
+		sockOpts[ssoReceiveHopLimit].name = sysIPV6_RECVHOPLIMIT
+		sockOpts[ssoReceivePacketInfo].name = sysIPV6_RECVPKTINFO
 		sockOpts[ssoReceivePathMTU].level = ianaProtocolIPv6
 		sockOpts[ssoReceivePathMTU].name = sysIPV6_RECVPATHMTU
 		sockOpts[ssoReceivePathMTU].typ = ssoTypeInt
-		// Please be informed that IPV6_PATHMTU option will be
-		// a cause of kernel crash on 10.9 and earlier.
-		//sockOpts[ssoPathMTU].level = ianaProtocolIPv6
-		//sockOpts[ssoPathMTU].name = sysIPV6_PATHMTU
-		//sockOpts[ssoPathMTU].typ = ssoTypeMTUInfo
 	}
 }
 

+ 6 - 0
ipv6/sys_linux.go

@@ -12,6 +12,12 @@ import (
 type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{
+		ctlTrafficClass: {sysIPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass},
+		ctlHopLimit:     {sysIPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit},
+		ctlPacketInfo:   {sysIPV6_PKTINFO, sysSizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo},
+	}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoTrafficClass:        {ianaProtocolIPv6, sysIPV6_TCLASS, ssoTypeInt},
 		ssoHopLimit:            {ianaProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},

+ 2 - 0
ipv6/sys_stub.go

@@ -9,5 +9,7 @@ package ipv6
 type sysSockoptLen int32
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{}
+
 	sockOpts = [ssoMax]sockOpt{}
 )

+ 2 - 0
ipv6/sys_windows.go

@@ -38,6 +38,8 @@ type sysIPv6Mreq struct {
 }
 
 var (
+	ctlOpts = [ctlMax]ctlOpt{}
+
 	sockOpts = [ssoMax]sockOpt{
 		ssoHopLimit:           {ianaProtocolIPv6, sysIPV6_UNICAST_HOPS, ssoTypeInt},
 		ssoMulticastInterface: {ianaProtocolIPv6, sysIPV6_MULTICAST_IF, ssoTypeInterface},