diff options
author | gVisor bot <gvisor-bot@google.com> | 2021-09-19 20:19:42 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-09-19 20:19:42 +0000 |
commit | 453feae0e363ce6f8de82f1c2af107a001c37709 (patch) | |
tree | 6330eaf5295aae5c39a3c68a0d5670e20a59c2c1 /pkg | |
parent | d5c50f7005285605bf5fbc4b2fa604fd295cb957 (diff) | |
parent | 89a0011c100d778cd8a0cc5e1b14996461c66629 (diff) |
Merge release-20210906.0-46-g89a0011c1 (automated)
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/abi/linux/linux_abi_autogen_unsafe.go | 130 | ||||
-rw-r--r-- | pkg/abi/linux/linux_state_autogen.go | 29 | ||||
-rw-r--r-- | pkg/abi/linux/socket.go | 13 | ||||
-rw-r--r-- | pkg/sentry/socket/control/control.go | 19 | ||||
-rw-r--r-- | pkg/sentry/socket/netstack/netstack.go | 20 | ||||
-rw-r--r-- | pkg/sentry/socket/socket.go | 26 | ||||
-rw-r--r-- | pkg/sentry/socket/socket_state_autogen.go | 14 | ||||
-rw-r--r-- | pkg/tcpip/socketops.go | 18 | ||||
-rw-r--r-- | pkg/tcpip/tcpip.go | 14 | ||||
-rw-r--r-- | pkg/tcpip/tcpip_state_autogen.go | 98 | ||||
-rw-r--r-- | pkg/tcpip/transport/udp/endpoint.go | 18 |
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 |