summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-09-19 20:19:42 +0000
committergVisor bot <gvisor-bot@google.com>2021-09-19 20:19:42 +0000
commit453feae0e363ce6f8de82f1c2af107a001c37709 (patch)
tree6330eaf5295aae5c39a3c68a0d5670e20a59c2c1 /pkg
parentd5c50f7005285605bf5fbc4b2fa604fd295cb957 (diff)
parent89a0011c100d778cd8a0cc5e1b14996461c66629 (diff)
Merge release-20210906.0-46-g89a0011c1 (automated)
Diffstat (limited to 'pkg')
-rw-r--r--pkg/abi/linux/linux_abi_autogen_unsafe.go130
-rw-r--r--pkg/abi/linux/linux_state_autogen.go29
-rw-r--r--pkg/abi/linux/socket.go13
-rw-r--r--pkg/sentry/socket/control/control.go19
-rw-r--r--pkg/sentry/socket/netstack/netstack.go20
-rw-r--r--pkg/sentry/socket/socket.go26
-rw-r--r--pkg/sentry/socket/socket_state_autogen.go14
-rw-r--r--pkg/tcpip/socketops.go18
-rw-r--r--pkg/tcpip/tcpip.go14
-rw-r--r--pkg/tcpip/tcpip_state_autogen.go98
-rw-r--r--pkg/tcpip/transport/udp/endpoint.go18
11 files changed, 357 insertions, 42 deletions
diff --git a/pkg/abi/linux/linux_abi_autogen_unsafe.go b/pkg/abi/linux/linux_abi_autogen_unsafe.go
index 11cf350d2..0468da303 100644
--- a/pkg/abi/linux/linux_abi_autogen_unsafe.go
+++ b/pkg/abi/linux/linux_abi_autogen_unsafe.go
@@ -20,6 +20,7 @@ var _ marshal.Marshallable = (*ClockT)(nil)
var _ marshal.Marshallable = (*ControlMessageCredentials)(nil)
var _ marshal.Marshallable = (*ControlMessageHeader)(nil)
var _ marshal.Marshallable = (*ControlMessageIPPacketInfo)(nil)
+var _ marshal.Marshallable = (*ControlMessageIPv6PacketInfo)(nil)
var _ marshal.Marshallable = (*DigestMetadata)(nil)
var _ marshal.Marshallable = (*ElfHeader64)(nil)
var _ marshal.Marshallable = (*ElfProg64)(nil)
@@ -12146,6 +12147,135 @@ func (c *ControlMessageIPPacketInfo) WriteTo(writer io.Writer) (int64, error) {
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (c *ControlMessageIPv6PacketInfo) SizeBytes() int {
+ return 4 +
+ (*Inet6Addr)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (c *ControlMessageIPv6PacketInfo) MarshalBytes(dst []byte) {
+ c.Addr.MarshalBytes(dst[:c.Addr.SizeBytes()])
+ dst = dst[c.Addr.SizeBytes():]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(c.NIC))
+ dst = dst[4:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (c *ControlMessageIPv6PacketInfo) UnmarshalBytes(src []byte) {
+ c.Addr.UnmarshalBytes(src[:c.Addr.SizeBytes()])
+ src = src[c.Addr.SizeBytes():]
+ c.NIC = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (c *ControlMessageIPv6PacketInfo) Packed() bool {
+ return c.Addr.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (c *ControlMessageIPv6PacketInfo) MarshalUnsafe(dst []byte) {
+ if c.Addr.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(c), uintptr(c.SizeBytes()))
+ } else {
+ // Type ControlMessageIPv6PacketInfo doesn't have a packed layout in memory, fallback to MarshalBytes.
+ c.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (c *ControlMessageIPv6PacketInfo) UnmarshalUnsafe(src []byte) {
+ if c.Addr.Packed() {
+ gohacks.Memmove(unsafe.Pointer(c), unsafe.Pointer(&src[0]), uintptr(c.SizeBytes()))
+ } else {
+ // Type ControlMessageIPv6PacketInfo doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ c.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (c *ControlMessageIPv6PacketInfo) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !c.Addr.Packed() {
+ // Type ControlMessageIPv6PacketInfo doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(c.SizeBytes()) // escapes: okay.
+ c.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (c *ControlMessageIPv6PacketInfo) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return c.CopyOutN(cc, addr, c.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (c *ControlMessageIPv6PacketInfo) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !c.Addr.Packed() {
+ // Type ControlMessageIPv6PacketInfo doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(c.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ c.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (c *ControlMessageIPv6PacketInfo) WriteTo(writer io.Writer) (int64, error) {
+ if !c.Addr.Packed() {
+ // Type ControlMessageIPv6PacketInfo doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, c.SizeBytes())
+ c.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
//go:nosplit
func (i *Inet6Addr) SizeBytes() int {
return 1 * 16
diff --git a/pkg/abi/linux/linux_state_autogen.go b/pkg/abi/linux/linux_state_autogen.go
index e2043be15..6bd7d3f0c 100644
--- a/pkg/abi/linux/linux_state_autogen.go
+++ b/pkg/abi/linux/linux_state_autogen.go
@@ -204,6 +204,34 @@ func (c *ControlMessageIPPacketInfo) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(2, &c.DestinationAddr)
}
+func (c *ControlMessageIPv6PacketInfo) StateTypeName() string {
+ return "pkg/abi/linux.ControlMessageIPv6PacketInfo"
+}
+
+func (c *ControlMessageIPv6PacketInfo) StateFields() []string {
+ return []string{
+ "Addr",
+ "NIC",
+ }
+}
+
+func (c *ControlMessageIPv6PacketInfo) beforeSave() {}
+
+// +checklocksignore
+func (c *ControlMessageIPv6PacketInfo) StateSave(stateSinkObject state.Sink) {
+ c.beforeSave()
+ stateSinkObject.Save(0, &c.Addr)
+ stateSinkObject.Save(1, &c.NIC)
+}
+
+func (c *ControlMessageIPv6PacketInfo) afterLoad() {}
+
+// +checklocksignore
+func (c *ControlMessageIPv6PacketInfo) StateLoad(stateSourceObject state.Source) {
+ stateSourceObject.Load(0, &c.Addr)
+ stateSourceObject.Load(1, &c.NIC)
+}
+
func (t *KernelTermios) StateTypeName() string {
return "pkg/abi/linux.KernelTermios"
}
@@ -285,6 +313,7 @@ func init() {
state.Register((*SignalStack)(nil))
state.Register((*SignalInfo)(nil))
state.Register((*ControlMessageIPPacketInfo)(nil))
+ state.Register((*ControlMessageIPv6PacketInfo)(nil))
state.Register((*KernelTermios)(nil))
state.Register((*WindowSize)(nil))
}
diff --git a/pkg/abi/linux/socket.go b/pkg/abi/linux/socket.go
index 95871b8a5..f60e42997 100644
--- a/pkg/abi/linux/socket.go
+++ b/pkg/abi/linux/socket.go
@@ -542,6 +542,15 @@ type ControlMessageIPPacketInfo struct {
DestinationAddr InetAddr
}
+// ControlMessageIPv6PacketInfo represents struct in6_pktinfo from linux/ipv6.h.
+//
+// +marshal
+// +stateify savable
+type ControlMessageIPv6PacketInfo struct {
+ Addr Inet6Addr
+ NIC uint32
+}
+
// SizeOfControlMessageCredentials is the binary size of a
// ControlMessageCredentials struct.
var SizeOfControlMessageCredentials = (*ControlMessageCredentials)(nil).SizeBytes()
@@ -566,6 +575,10 @@ const SizeOfControlMessageTClass = 4
// control message.
const SizeOfControlMessageIPPacketInfo = 12
+// SizeOfControlMessageIPv6PacketInfo is the size of a
+// ControlMessageIPv6PacketInfo.
+const SizeOfControlMessageIPv6PacketInfo = 20
+
// SCM_MAX_FD is the maximum number of FDs accepted in a single sendmsg call.
// From net/scm.h.
const SCM_MAX_FD = 253
diff --git a/pkg/sentry/socket/control/control.go b/pkg/sentry/socket/control/control.go
index 00a5e729a..f9a5b0df1 100644
--- a/pkg/sentry/socket/control/control.go
+++ b/pkg/sentry/socket/control/control.go
@@ -355,6 +355,17 @@ func PackIPPacketInfo(t *kernel.Task, packetInfo *linux.ControlMessageIPPacketIn
)
}
+// PackIPv6PacketInfo packs an IPV6_PKTINFO socket control message.
+func PackIPv6PacketInfo(t *kernel.Task, packetInfo *linux.ControlMessageIPv6PacketInfo, buf []byte) []byte {
+ return putCmsgStruct(
+ buf,
+ linux.SOL_IPV6,
+ linux.IPV6_PKTINFO,
+ t.Arch().Width(),
+ packetInfo,
+ )
+}
+
// PackOriginalDstAddress packs an IP_RECVORIGINALDSTADDR socket control message.
func PackOriginalDstAddress(t *kernel.Task, originalDstAddress linux.SockAddr, buf []byte) []byte {
var level uint32
@@ -412,6 +423,10 @@ func PackControlMessages(t *kernel.Task, cmsgs socket.ControlMessages, buf []byt
buf = PackIPPacketInfo(t, &cmsgs.IP.PacketInfo, buf)
}
+ if cmsgs.IP.HasIPv6PacketInfo {
+ buf = PackIPv6PacketInfo(t, &cmsgs.IP.IPv6PacketInfo, buf)
+ }
+
if cmsgs.IP.OriginalDstAddress != nil {
buf = PackOriginalDstAddress(t, cmsgs.IP.OriginalDstAddress, buf)
}
@@ -453,6 +468,10 @@ func CmsgsSpace(t *kernel.Task, cmsgs socket.ControlMessages) int {
space += cmsgSpace(t, linux.SizeOfControlMessageIPPacketInfo)
}
+ if cmsgs.IP.HasIPv6PacketInfo {
+ space += cmsgSpace(t, linux.SizeOfControlMessageIPv6PacketInfo)
+ }
+
if cmsgs.IP.OriginalDstAddress != nil {
space += cmsgSpace(t, cmsgs.IP.OriginalDstAddress.SizeBytes())
}
diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go
index aa081e90d..dedc32dda 100644
--- a/pkg/sentry/socket/netstack/netstack.go
+++ b/pkg/sentry/socket/netstack/netstack.go
@@ -1371,6 +1371,14 @@ func getSockOptIPv6(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name
v := primitive.Int32(boolToInt32(ep.SocketOptions().GetReceiveOriginalDstAddress()))
return &v, nil
+ case linux.IPV6_RECVPKTINFO:
+ if outLen < sizeOfInt32 {
+ return nil, syserr.ErrInvalidArgument
+ }
+
+ v := primitive.Int32(boolToInt32(ep.SocketOptions().GetIPv6ReceivePacketInfo()))
+ return &v, nil
+
case linux.IP6T_ORIGINAL_DST:
if outLen < sockAddrInet6Size {
return nil, syserr.ErrInvalidArgument
@@ -2127,6 +2135,15 @@ func setSockOptIPv6(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name
ep.SocketOptions().SetReceiveOriginalDstAddress(v != 0)
return nil
+ case linux.IPV6_RECVPKTINFO:
+ if len(optVal) < sizeOfInt32 {
+ return syserr.ErrInvalidArgument
+ }
+ v := int32(hostarch.ByteOrder.Uint32(optVal))
+
+ ep.SocketOptions().SetIPv6ReceivePacketInfo(v != 0)
+ return nil
+
case linux.IPV6_TCLASS:
if len(optVal) < sizeOfInt32 {
return syserr.ErrInvalidArgument
@@ -2516,7 +2533,6 @@ func emitUnimplementedEventIPv6(t *kernel.Task, name int) {
linux.IPV6_RECVHOPLIMIT,
linux.IPV6_RECVHOPOPTS,
linux.IPV6_RECVPATHMTU,
- linux.IPV6_RECVPKTINFO,
linux.IPV6_RECVRTHDR,
linux.IPV6_RTHDR,
linux.IPV6_RTHDRDSTOPTS,
@@ -2742,6 +2758,8 @@ func (s *socketOpsCommon) controlMessages(cm tcpip.ControlMessages) socket.Contr
TClass: readCM.TClass,
HasIPPacketInfo: readCM.HasIPPacketInfo,
PacketInfo: readCM.PacketInfo,
+ HasIPv6PacketInfo: readCM.HasIPv6PacketInfo,
+ IPv6PacketInfo: readCM.IPv6PacketInfo,
OriginalDstAddress: readCM.OriginalDstAddress,
SockErr: readCM.SockErr,
},
diff --git a/pkg/sentry/socket/socket.go b/pkg/sentry/socket/socket.go
index 841d5bd55..2f0eb4a6c 100644
--- a/pkg/sentry/socket/socket.go
+++ b/pkg/sentry/socket/socket.go
@@ -56,6 +56,17 @@ func packetInfoToLinux(packetInfo tcpip.IPPacketInfo) linux.ControlMessageIPPack
return p
}
+// ipv6PacketInfoToLinux converts IPv6PacketInfo from tcpip format to Linux
+// format.
+func ipv6PacketInfoToLinux(packetInfo tcpip.IPv6PacketInfo) linux.ControlMessageIPv6PacketInfo {
+ var p linux.ControlMessageIPv6PacketInfo
+ if n := copy(p.Addr[:], []byte(packetInfo.Addr)); n != len(p.Addr) {
+ panic(fmt.Sprintf("got copy(%x, %x) = %d, want = %d", p.Addr, packetInfo.Addr, n, len(p.Addr)))
+ }
+ p.NIC = uint32(packetInfo.NIC)
+ return p
+}
+
// errOriginToLinux maps tcpip socket origin to Linux socket origin constants.
func errOriginToLinux(origin tcpip.SockErrOrigin) uint8 {
switch origin {
@@ -114,7 +125,7 @@ func NewIPControlMessages(family int, cmgs tcpip.ControlMessages) IPControlMessa
if cmgs.HasOriginalDstAddress {
orgDstAddr, _ = ConvertAddress(family, cmgs.OriginalDstAddress)
}
- return IPControlMessages{
+ cm := IPControlMessages{
HasTimestamp: cmgs.HasTimestamp,
Timestamp: cmgs.Timestamp,
HasInq: cmgs.HasInq,
@@ -125,9 +136,16 @@ func NewIPControlMessages(family int, cmgs tcpip.ControlMessages) IPControlMessa
TClass: cmgs.TClass,
HasIPPacketInfo: cmgs.HasIPPacketInfo,
PacketInfo: packetInfoToLinux(cmgs.PacketInfo),
+ HasIPv6PacketInfo: cmgs.HasIPv6PacketInfo,
OriginalDstAddress: orgDstAddr,
SockErr: sockErrCmsgToLinux(cmgs.SockErr),
}
+
+ if cm.HasIPv6PacketInfo {
+ cm.IPv6PacketInfo = ipv6PacketInfoToLinux(cmgs.IPv6PacketInfo)
+ }
+
+ return cm
}
// IPControlMessages contains socket control messages for IP sockets.
@@ -166,6 +184,12 @@ type IPControlMessages struct {
// PacketInfo holds interface and address data on an incoming packet.
PacketInfo linux.ControlMessageIPPacketInfo
+ // HasIPv6PacketInfo indicates whether IPv6PacketInfo is set.
+ HasIPv6PacketInfo bool
+
+ // PacketInfo holds interface and address data on an incoming packet.
+ IPv6PacketInfo linux.ControlMessageIPv6PacketInfo
+
// OriginalDestinationAddress holds the original destination address
// and port of the incoming packet.
OriginalDstAddress linux.SockAddr
diff --git a/pkg/sentry/socket/socket_state_autogen.go b/pkg/sentry/socket/socket_state_autogen.go
index d050093f6..9b391d8ca 100644
--- a/pkg/sentry/socket/socket_state_autogen.go
+++ b/pkg/sentry/socket/socket_state_autogen.go
@@ -22,6 +22,8 @@ func (i *IPControlMessages) StateFields() []string {
"TClass",
"HasIPPacketInfo",
"PacketInfo",
+ "HasIPv6PacketInfo",
+ "IPv6PacketInfo",
"OriginalDstAddress",
"SockErr",
}
@@ -42,8 +44,10 @@ func (i *IPControlMessages) StateSave(stateSinkObject state.Sink) {
stateSinkObject.Save(7, &i.TClass)
stateSinkObject.Save(8, &i.HasIPPacketInfo)
stateSinkObject.Save(9, &i.PacketInfo)
- stateSinkObject.Save(10, &i.OriginalDstAddress)
- stateSinkObject.Save(11, &i.SockErr)
+ stateSinkObject.Save(10, &i.HasIPv6PacketInfo)
+ stateSinkObject.Save(11, &i.IPv6PacketInfo)
+ stateSinkObject.Save(12, &i.OriginalDstAddress)
+ stateSinkObject.Save(13, &i.SockErr)
}
func (i *IPControlMessages) afterLoad() {}
@@ -60,8 +64,10 @@ func (i *IPControlMessages) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(7, &i.TClass)
stateSourceObject.Load(8, &i.HasIPPacketInfo)
stateSourceObject.Load(9, &i.PacketInfo)
- stateSourceObject.Load(10, &i.OriginalDstAddress)
- stateSourceObject.Load(11, &i.SockErr)
+ stateSourceObject.Load(10, &i.HasIPv6PacketInfo)
+ stateSourceObject.Load(11, &i.IPv6PacketInfo)
+ stateSourceObject.Load(12, &i.OriginalDstAddress)
+ stateSourceObject.Load(13, &i.SockErr)
}
func (to *SendReceiveTimeout) StateTypeName() string {
diff --git a/pkg/tcpip/socketops.go b/pkg/tcpip/socketops.go
index 34ac62444..b0b2d0afd 100644
--- a/pkg/tcpip/socketops.go
+++ b/pkg/tcpip/socketops.go
@@ -170,10 +170,14 @@ type SocketOptions struct {
// message is passed with incoming packets.
receiveTClassEnabled uint32
- // receivePacketInfoEnabled is used to specify if more inforamtion is
- // provided with incoming packets such as interface index and address.
+ // receivePacketInfoEnabled is used to specify if more information is
+ // provided with incoming IPv4 packets.
receivePacketInfoEnabled uint32
+ // receivePacketInfoEnabled is used to specify if more information is
+ // provided with incoming IPv6 packets.
+ receiveIPv6PacketInfoEnabled uint32
+
// hdrIncludeEnabled is used to indicate for a raw endpoint that all packets
// being written have an IP header and the endpoint should not attach an IP
// header.
@@ -360,6 +364,16 @@ func (so *SocketOptions) SetReceivePacketInfo(v bool) {
storeAtomicBool(&so.receivePacketInfoEnabled, v)
}
+// GetIPv6ReceivePacketInfo gets value for IPV6_RECVPKTINFO option.
+func (so *SocketOptions) GetIPv6ReceivePacketInfo() bool {
+ return atomic.LoadUint32(&so.receiveIPv6PacketInfoEnabled) != 0
+}
+
+// SetIPv6ReceivePacketInfo sets value for IPV6_RECVPKTINFO option.
+func (so *SocketOptions) SetIPv6ReceivePacketInfo(v bool) {
+ storeAtomicBool(&so.receiveIPv6PacketInfoEnabled, v)
+}
+
// GetHeaderIncluded gets value for IP_HDRINCL option.
func (so *SocketOptions) GetHeaderIncluded() bool {
return atomic.LoadUint32(&so.hdrIncludedEnabled) != 0
diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go
index a9ce148b9..c5e896295 100644
--- a/pkg/tcpip/tcpip.go
+++ b/pkg/tcpip/tcpip.go
@@ -451,6 +451,12 @@ type ControlMessages struct {
// PacketInfo holds interface and address data on an incoming packet.
PacketInfo IPPacketInfo
+ // HasIPv6PacketInfo indicates whether IPv6PacketInfo is set.
+ HasIPv6PacketInfo bool
+
+ // IPv6PacketInfo holds interface and address data on an incoming packet.
+ IPv6PacketInfo IPv6PacketInfo
+
// HasOriginalDestinationAddress indicates whether OriginalDstAddress is
// set.
HasOriginalDstAddress bool
@@ -1164,6 +1170,14 @@ type IPPacketInfo struct {
DestinationAddr Address
}
+// IPv6PacketInfo is the message structure for IPV6_PKTINFO.
+//
+// +stateify savable
+type IPv6PacketInfo struct {
+ Addr Address
+ NIC NICID
+}
+
// SendBufferSizeOption is used by stack.(Stack*).Option/SetOption to
// get/set the default, min and max send buffer sizes.
type SendBufferSizeOption struct {
diff --git a/pkg/tcpip/tcpip_state_autogen.go b/pkg/tcpip/tcpip_state_autogen.go
index 9c34de9ef..c3df463eb 100644
--- a/pkg/tcpip/tcpip_state_autogen.go
+++ b/pkg/tcpip/tcpip_state_autogen.go
@@ -898,6 +898,7 @@ func (so *SocketOptions) StateFields() []string {
"receiveTOSEnabled",
"receiveTClassEnabled",
"receivePacketInfoEnabled",
+ "receiveIPv6PacketInfoEnabled",
"hdrIncludedEnabled",
"v6OnlyEnabled",
"quickAckEnabled",
@@ -929,18 +930,19 @@ func (so *SocketOptions) StateSave(stateSinkObject state.Sink) {
stateSinkObject.Save(8, &so.receiveTOSEnabled)
stateSinkObject.Save(9, &so.receiveTClassEnabled)
stateSinkObject.Save(10, &so.receivePacketInfoEnabled)
- stateSinkObject.Save(11, &so.hdrIncludedEnabled)
- stateSinkObject.Save(12, &so.v6OnlyEnabled)
- stateSinkObject.Save(13, &so.quickAckEnabled)
- stateSinkObject.Save(14, &so.delayOptionEnabled)
- stateSinkObject.Save(15, &so.corkOptionEnabled)
- stateSinkObject.Save(16, &so.receiveOriginalDstAddress)
- stateSinkObject.Save(17, &so.recvErrEnabled)
- stateSinkObject.Save(18, &so.errQueue)
- stateSinkObject.Save(19, &so.bindToDevice)
- stateSinkObject.Save(20, &so.sendBufferSize)
- stateSinkObject.Save(21, &so.receiveBufferSize)
- stateSinkObject.Save(22, &so.linger)
+ stateSinkObject.Save(11, &so.receiveIPv6PacketInfoEnabled)
+ stateSinkObject.Save(12, &so.hdrIncludedEnabled)
+ stateSinkObject.Save(13, &so.v6OnlyEnabled)
+ stateSinkObject.Save(14, &so.quickAckEnabled)
+ stateSinkObject.Save(15, &so.delayOptionEnabled)
+ stateSinkObject.Save(16, &so.corkOptionEnabled)
+ stateSinkObject.Save(17, &so.receiveOriginalDstAddress)
+ stateSinkObject.Save(18, &so.recvErrEnabled)
+ stateSinkObject.Save(19, &so.errQueue)
+ stateSinkObject.Save(20, &so.bindToDevice)
+ stateSinkObject.Save(21, &so.sendBufferSize)
+ stateSinkObject.Save(22, &so.receiveBufferSize)
+ stateSinkObject.Save(23, &so.linger)
}
func (so *SocketOptions) afterLoad() {}
@@ -958,18 +960,19 @@ func (so *SocketOptions) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(8, &so.receiveTOSEnabled)
stateSourceObject.Load(9, &so.receiveTClassEnabled)
stateSourceObject.Load(10, &so.receivePacketInfoEnabled)
- stateSourceObject.Load(11, &so.hdrIncludedEnabled)
- stateSourceObject.Load(12, &so.v6OnlyEnabled)
- stateSourceObject.Load(13, &so.quickAckEnabled)
- stateSourceObject.Load(14, &so.delayOptionEnabled)
- stateSourceObject.Load(15, &so.corkOptionEnabled)
- stateSourceObject.Load(16, &so.receiveOriginalDstAddress)
- stateSourceObject.Load(17, &so.recvErrEnabled)
- stateSourceObject.Load(18, &so.errQueue)
- stateSourceObject.Load(19, &so.bindToDevice)
- stateSourceObject.Load(20, &so.sendBufferSize)
- stateSourceObject.Load(21, &so.receiveBufferSize)
- stateSourceObject.Load(22, &so.linger)
+ stateSourceObject.Load(11, &so.receiveIPv6PacketInfoEnabled)
+ stateSourceObject.Load(12, &so.hdrIncludedEnabled)
+ stateSourceObject.Load(13, &so.v6OnlyEnabled)
+ stateSourceObject.Load(14, &so.quickAckEnabled)
+ stateSourceObject.Load(15, &so.delayOptionEnabled)
+ stateSourceObject.Load(16, &so.corkOptionEnabled)
+ stateSourceObject.Load(17, &so.receiveOriginalDstAddress)
+ stateSourceObject.Load(18, &so.recvErrEnabled)
+ stateSourceObject.Load(19, &so.errQueue)
+ stateSourceObject.Load(20, &so.bindToDevice)
+ stateSourceObject.Load(21, &so.sendBufferSize)
+ stateSourceObject.Load(22, &so.receiveBufferSize)
+ stateSourceObject.Load(23, &so.linger)
}
func (l *LocalSockError) StateTypeName() string {
@@ -1136,6 +1139,8 @@ func (c *ControlMessages) StateFields() []string {
"TClass",
"HasIPPacketInfo",
"PacketInfo",
+ "HasIPv6PacketInfo",
+ "IPv6PacketInfo",
"HasOriginalDstAddress",
"OriginalDstAddress",
"SockErr",
@@ -1157,9 +1162,11 @@ func (c *ControlMessages) StateSave(stateSinkObject state.Sink) {
stateSinkObject.Save(7, &c.TClass)
stateSinkObject.Save(8, &c.HasIPPacketInfo)
stateSinkObject.Save(9, &c.PacketInfo)
- stateSinkObject.Save(10, &c.HasOriginalDstAddress)
- stateSinkObject.Save(11, &c.OriginalDstAddress)
- stateSinkObject.Save(12, &c.SockErr)
+ stateSinkObject.Save(10, &c.HasIPv6PacketInfo)
+ stateSinkObject.Save(11, &c.IPv6PacketInfo)
+ stateSinkObject.Save(12, &c.HasOriginalDstAddress)
+ stateSinkObject.Save(13, &c.OriginalDstAddress)
+ stateSinkObject.Save(14, &c.SockErr)
}
func (c *ControlMessages) afterLoad() {}
@@ -1176,9 +1183,11 @@ func (c *ControlMessages) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(7, &c.TClass)
stateSourceObject.Load(8, &c.HasIPPacketInfo)
stateSourceObject.Load(9, &c.PacketInfo)
- stateSourceObject.Load(10, &c.HasOriginalDstAddress)
- stateSourceObject.Load(11, &c.OriginalDstAddress)
- stateSourceObject.Load(12, &c.SockErr)
+ stateSourceObject.Load(10, &c.HasIPv6PacketInfo)
+ stateSourceObject.Load(11, &c.IPv6PacketInfo)
+ stateSourceObject.Load(12, &c.HasOriginalDstAddress)
+ stateSourceObject.Load(13, &c.OriginalDstAddress)
+ stateSourceObject.Load(14, &c.SockErr)
}
func (l *LinkPacketInfo) StateTypeName() string {
@@ -1268,6 +1277,34 @@ func (i *IPPacketInfo) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(2, &i.DestinationAddr)
}
+func (i *IPv6PacketInfo) StateTypeName() string {
+ return "pkg/tcpip.IPv6PacketInfo"
+}
+
+func (i *IPv6PacketInfo) StateFields() []string {
+ return []string{
+ "Addr",
+ "NIC",
+ }
+}
+
+func (i *IPv6PacketInfo) beforeSave() {}
+
+// +checklocksignore
+func (i *IPv6PacketInfo) StateSave(stateSinkObject state.Sink) {
+ i.beforeSave()
+ stateSinkObject.Save(0, &i.Addr)
+ stateSinkObject.Save(1, &i.NIC)
+}
+
+func (i *IPv6PacketInfo) afterLoad() {}
+
+// +checklocksignore
+func (i *IPv6PacketInfo) StateLoad(stateSourceObject state.Source) {
+ stateSourceObject.Load(0, &i.Addr)
+ stateSourceObject.Load(1, &i.NIC)
+}
+
func init() {
state.Register((*ErrAborted)(nil))
state.Register((*ErrAddressFamilyNotSupported)(nil))
@@ -1320,4 +1357,5 @@ func init() {
state.Register((*LinkPacketInfo)(nil))
state.Register((*LingerOption)(nil))
state.Register((*IPPacketInfo)(nil))
+ state.Register((*IPv6PacketInfo)(nil))
}
diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go
index 4255457f9..b355fa7eb 100644
--- a/pkg/tcpip/transport/udp/endpoint.go
+++ b/pkg/tcpip/transport/udp/endpoint.go
@@ -243,19 +243,29 @@ func (e *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResult
cm.HasTOS = true
cm.TOS = p.tos
}
+
+ if e.ops.GetReceivePacketInfo() {
+ cm.HasIPPacketInfo = true
+ cm.PacketInfo = p.packetInfo
+ }
case header.IPv6ProtocolNumber:
if e.ops.GetReceiveTClass() {
cm.HasTClass = true
// Although TClass is an 8-bit value it's read in the CMsg as a uint32.
cm.TClass = uint32(p.tos)
}
+
+ if e.ops.GetIPv6ReceivePacketInfo() {
+ cm.HasIPv6PacketInfo = true
+ cm.IPv6PacketInfo = tcpip.IPv6PacketInfo{
+ NIC: p.packetInfo.NIC,
+ Addr: p.packetInfo.DestinationAddr,
+ }
+ }
default:
panic(fmt.Sprintf("unrecognized network protocol = %d", p.netProto))
}
- if e.ops.GetReceivePacketInfo() {
- cm.HasIPPacketInfo = true
- cm.PacketInfo = p.packetInfo
- }
+
if e.ops.GetReceiveOriginalDstAddress() {
cm.HasOriginalDstAddress = true
cm.OriginalDstAddress = p.destinationAddress