github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/socket/socket.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package socket provides the interfaces that need to be provided by socket
    16  // implementations and providers, as well as per family demultiplexing of socket
    17  // creation.
    18  package socket
    19  
    20  import (
    21  	"bytes"
    22  	"fmt"
    23  	"time"
    24  
    25  	"golang.org/x/sys/unix"
    26  	"github.com/nicocha30/gvisor-ligolo/pkg/abi/linux"
    27  	"github.com/nicocha30/gvisor-ligolo/pkg/atomicbitops"
    28  	"github.com/nicocha30/gvisor-ligolo/pkg/context"
    29  	"github.com/nicocha30/gvisor-ligolo/pkg/hostarch"
    30  	"github.com/nicocha30/gvisor-ligolo/pkg/marshal"
    31  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel"
    32  	ktime "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/time"
    33  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/socket/unix/transport"
    34  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/vfs"
    35  	"github.com/nicocha30/gvisor-ligolo/pkg/syserr"
    36  	"github.com/nicocha30/gvisor-ligolo/pkg/tcpip"
    37  	"github.com/nicocha30/gvisor-ligolo/pkg/tcpip/header"
    38  	"github.com/nicocha30/gvisor-ligolo/pkg/usermem"
    39  )
    40  
    41  // ControlMessages represents the union of unix control messages and tcpip
    42  // control messages.
    43  type ControlMessages struct {
    44  	Unix transport.ControlMessages
    45  	IP   IPControlMessages
    46  }
    47  
    48  // packetInfoToLinux converts IPPacketInfo from tcpip format to Linux format.
    49  func packetInfoToLinux(packetInfo tcpip.IPPacketInfo) linux.ControlMessageIPPacketInfo {
    50  	var p linux.ControlMessageIPPacketInfo
    51  	p.NIC = int32(packetInfo.NIC)
    52  	copy(p.LocalAddr[:], packetInfo.LocalAddr.AsSlice())
    53  	copy(p.DestinationAddr[:], packetInfo.DestinationAddr.AsSlice())
    54  	return p
    55  }
    56  
    57  // ipv6PacketInfoToLinux converts IPv6PacketInfo from tcpip format to Linux
    58  // format.
    59  func ipv6PacketInfoToLinux(packetInfo tcpip.IPv6PacketInfo) linux.ControlMessageIPv6PacketInfo {
    60  	var p linux.ControlMessageIPv6PacketInfo
    61  	if n := copy(p.Addr[:], packetInfo.Addr.AsSlice()); n != len(p.Addr) {
    62  		panic(fmt.Sprintf("got copy(%x, %x) = %d, want = %d", p.Addr, packetInfo.Addr, n, len(p.Addr)))
    63  	}
    64  	p.NIC = uint32(packetInfo.NIC)
    65  	return p
    66  }
    67  
    68  // errOriginToLinux maps tcpip socket origin to Linux socket origin constants.
    69  func errOriginToLinux(origin tcpip.SockErrOrigin) uint8 {
    70  	switch origin {
    71  	case tcpip.SockExtErrorOriginNone:
    72  		return linux.SO_EE_ORIGIN_NONE
    73  	case tcpip.SockExtErrorOriginLocal:
    74  		return linux.SO_EE_ORIGIN_LOCAL
    75  	case tcpip.SockExtErrorOriginICMP:
    76  		return linux.SO_EE_ORIGIN_ICMP
    77  	case tcpip.SockExtErrorOriginICMP6:
    78  		return linux.SO_EE_ORIGIN_ICMP6
    79  	default:
    80  		panic(fmt.Sprintf("unknown socket origin: %d", origin))
    81  	}
    82  }
    83  
    84  // sockErrCmsgToLinux converts SockError control message from tcpip format to
    85  // Linux format.
    86  func sockErrCmsgToLinux(sockErr *tcpip.SockError) linux.SockErrCMsg {
    87  	if sockErr == nil {
    88  		return nil
    89  	}
    90  
    91  	ee := linux.SockExtendedErr{
    92  		Errno:  uint32(syserr.TranslateNetstackError(sockErr.Err).ToLinux()),
    93  		Origin: errOriginToLinux(sockErr.Cause.Origin()),
    94  		Type:   sockErr.Cause.Type(),
    95  		Code:   sockErr.Cause.Code(),
    96  		Info:   sockErr.Cause.Info(),
    97  	}
    98  
    99  	switch sockErr.NetProto {
   100  	case header.IPv4ProtocolNumber:
   101  		errMsg := &linux.SockErrCMsgIPv4{SockExtendedErr: ee}
   102  		if len(sockErr.Offender.Addr.AsSlice()) > 0 {
   103  			addr, _ := ConvertAddress(linux.AF_INET, sockErr.Offender)
   104  			errMsg.Offender = *addr.(*linux.SockAddrInet)
   105  		}
   106  		return errMsg
   107  	case header.IPv6ProtocolNumber:
   108  		errMsg := &linux.SockErrCMsgIPv6{SockExtendedErr: ee}
   109  		if len(sockErr.Offender.Addr.AsSlice()) > 0 {
   110  			addr, _ := ConvertAddress(linux.AF_INET6, sockErr.Offender)
   111  			errMsg.Offender = *addr.(*linux.SockAddrInet6)
   112  		}
   113  		return errMsg
   114  	default:
   115  		panic(fmt.Sprintf("invalid net proto for creating SockErrCMsg: %d", sockErr.NetProto))
   116  	}
   117  }
   118  
   119  // NewIPControlMessages converts the tcpip.ReceivableControlMessages (which does
   120  // not have Linux specific format) to Linux format.
   121  func NewIPControlMessages(family int, cmgs tcpip.ReceivableControlMessages) IPControlMessages {
   122  	var orgDstAddr linux.SockAddr
   123  	if cmgs.HasOriginalDstAddress {
   124  		orgDstAddr, _ = ConvertAddress(family, cmgs.OriginalDstAddress)
   125  	}
   126  	cm := IPControlMessages{
   127  		HasTimestamp:       cmgs.HasTimestamp,
   128  		Timestamp:          cmgs.Timestamp,
   129  		HasInq:             cmgs.HasInq,
   130  		Inq:                cmgs.Inq,
   131  		HasTOS:             cmgs.HasTOS,
   132  		TOS:                cmgs.TOS,
   133  		HasTTL:             cmgs.HasTTL,
   134  		TTL:                uint32(cmgs.TTL),
   135  		HasHopLimit:        cmgs.HasHopLimit,
   136  		HopLimit:           uint32(cmgs.HopLimit),
   137  		HasTClass:          cmgs.HasTClass,
   138  		TClass:             cmgs.TClass,
   139  		HasIPPacketInfo:    cmgs.HasIPPacketInfo,
   140  		PacketInfo:         packetInfoToLinux(cmgs.PacketInfo),
   141  		HasIPv6PacketInfo:  cmgs.HasIPv6PacketInfo,
   142  		OriginalDstAddress: orgDstAddr,
   143  		SockErr:            sockErrCmsgToLinux(cmgs.SockErr),
   144  	}
   145  
   146  	if cm.HasIPv6PacketInfo {
   147  		cm.IPv6PacketInfo = ipv6PacketInfoToLinux(cmgs.IPv6PacketInfo)
   148  	}
   149  
   150  	return cm
   151  }
   152  
   153  // IPControlMessages contains socket control messages for IP sockets.
   154  // This can contain Linux specific structures unlike tcpip.ControlMessages.
   155  //
   156  // +stateify savable
   157  type IPControlMessages struct {
   158  	// HasTimestamp indicates whether Timestamp is valid/set.
   159  	HasTimestamp bool
   160  
   161  	// Timestamp is the time that the last packet used to create the read data
   162  	// was received.
   163  	Timestamp time.Time `state:".(int64)"`
   164  
   165  	// HasInq indicates whether Inq is valid/set.
   166  	HasInq bool
   167  
   168  	// Inq is the number of bytes ready to be received.
   169  	Inq int32
   170  
   171  	// HasTOS indicates whether Tos is valid/set.
   172  	HasTOS bool
   173  
   174  	// TOS is the IPv4 type of service of the associated packet.
   175  	TOS uint8
   176  
   177  	// HasTTL indicates whether TTL is valid/set.
   178  	HasTTL bool
   179  
   180  	// TTL is the IPv4 Time To Live of the associated packet.
   181  	TTL uint32
   182  
   183  	// HasHopLimit indicates whether HopLimit is valid/set.
   184  	HasHopLimit bool
   185  
   186  	// HopLimit is the IPv6 Hop Limit of the associated packet.
   187  	HopLimit uint32
   188  
   189  	// HasTClass indicates whether TClass is valid/set.
   190  	HasTClass bool
   191  
   192  	// TClass is the IPv6 traffic class of the associated packet.
   193  	TClass uint32
   194  
   195  	// HasIPPacketInfo indicates whether PacketInfo is set.
   196  	HasIPPacketInfo bool
   197  
   198  	// PacketInfo holds interface and address data on an incoming packet.
   199  	PacketInfo linux.ControlMessageIPPacketInfo
   200  
   201  	// HasIPv6PacketInfo indicates whether IPv6PacketInfo is set.
   202  	HasIPv6PacketInfo bool
   203  
   204  	// PacketInfo holds interface and address data on an incoming packet.
   205  	IPv6PacketInfo linux.ControlMessageIPv6PacketInfo
   206  
   207  	// OriginalDestinationAddress holds the original destination address
   208  	// and port of the incoming packet.
   209  	OriginalDstAddress linux.SockAddr
   210  
   211  	// SockErr is the dequeued socket error on recvmsg(MSG_ERRQUEUE).
   212  	SockErr linux.SockErrCMsg
   213  }
   214  
   215  // Release releases Unix domain socket credentials and rights.
   216  func (c *ControlMessages) Release(ctx context.Context) {
   217  	c.Unix.Release(ctx)
   218  }
   219  
   220  // Socket is an interface containing socket syscalls used by the syscall
   221  // layer to redirect them to the appropriate implementation.
   222  type Socket interface {
   223  	vfs.FileDescriptionImpl
   224  
   225  	// Connect implements the connect(2) linux unix.
   226  	Connect(t *kernel.Task, sockaddr []byte, blocking bool) *syserr.Error
   227  
   228  	// Accept implements the accept4(2) linux unix.
   229  	// Returns fd, real peer address length and error. Real peer address
   230  	// length is only set if len(peer) > 0.
   231  	Accept(t *kernel.Task, peerRequested bool, flags int, blocking bool) (int32, linux.SockAddr, uint32, *syserr.Error)
   232  
   233  	// Bind implements the bind(2) linux unix.
   234  	Bind(t *kernel.Task, sockaddr []byte) *syserr.Error
   235  
   236  	// Listen implements the listen(2) linux unix.
   237  	Listen(t *kernel.Task, backlog int) *syserr.Error
   238  
   239  	// Shutdown implements the shutdown(2) linux unix.
   240  	Shutdown(t *kernel.Task, how int) *syserr.Error
   241  
   242  	// GetSockOpt implements the getsockopt(2) linux unix.
   243  	GetSockOpt(t *kernel.Task, level int, name int, outPtr hostarch.Addr, outLen int) (marshal.Marshallable, *syserr.Error)
   244  
   245  	// SetSockOpt implements the setsockopt(2) linux unix.
   246  	SetSockOpt(t *kernel.Task, level int, name int, opt []byte) *syserr.Error
   247  
   248  	// GetSockName implements the getsockname(2) linux unix.
   249  	//
   250  	// addrLen is the address length to be returned to the application, not
   251  	// necessarily the actual length of the address.
   252  	GetSockName(t *kernel.Task) (addr linux.SockAddr, addrLen uint32, err *syserr.Error)
   253  
   254  	// GetPeerName implements the getpeername(2) linux unix.
   255  	//
   256  	// addrLen is the address length to be returned to the application, not
   257  	// necessarily the actual length of the address.
   258  	GetPeerName(t *kernel.Task) (addr linux.SockAddr, addrLen uint32, err *syserr.Error)
   259  
   260  	// RecvMsg implements the recvmsg(2) linux unix.
   261  	//
   262  	// senderAddrLen is the address length to be returned to the application,
   263  	// not necessarily the actual length of the address.
   264  	//
   265  	// flags control how RecvMsg should be completed. msgFlags indicate how
   266  	// the RecvMsg call was completed. Note that control message truncation
   267  	// may still be required even if the MSG_CTRUNC bit is not set in
   268  	// msgFlags. In that case, the caller should set MSG_CTRUNC appropriately.
   269  	//
   270  	// If err != nil, the recv was not successful.
   271  	RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlDataLen uint64) (n int, msgFlags int, senderAddr linux.SockAddr, senderAddrLen uint32, controlMessages ControlMessages, err *syserr.Error)
   272  
   273  	// SendMsg implements the sendmsg(2) linux unix. SendMsg does not take
   274  	// ownership of the ControlMessage on error.
   275  	//
   276  	// If n > 0, err will either be nil or an error from t.Block.
   277  	SendMsg(t *kernel.Task, src usermem.IOSequence, to []byte, flags int, haveDeadline bool, deadline ktime.Time, controlMessages ControlMessages) (n int, err *syserr.Error)
   278  
   279  	// SetRecvTimeout sets the timeout (in ns) for recv operations. Zero means
   280  	// no timeout, and negative means DONTWAIT.
   281  	SetRecvTimeout(nanoseconds int64)
   282  
   283  	// RecvTimeout gets the current timeout (in ns) for recv operations. Zero
   284  	// means no timeout, and negative means DONTWAIT.
   285  	RecvTimeout() int64
   286  
   287  	// SetSendTimeout sets the timeout (in ns) for send operations. Zero means
   288  	// no timeout, and negative means DONTWAIT.
   289  	SetSendTimeout(nanoseconds int64)
   290  
   291  	// SendTimeout gets the current timeout (in ns) for send operations. Zero
   292  	// means no timeout, and negative means DONTWAIT.
   293  	SendTimeout() int64
   294  
   295  	// State returns the current state of the socket, as represented by Linux in
   296  	// procfs. The returned state value is protocol-specific.
   297  	State() uint32
   298  
   299  	// Type returns the family, socket type and protocol of the socket.
   300  	Type() (family int, skType linux.SockType, protocol int)
   301  }
   302  
   303  // Provider is the interface implemented by providers of sockets for
   304  // specific address families (e.g., AF_INET).
   305  type Provider interface {
   306  	// Socket creates a new socket.
   307  	//
   308  	// If a nil Socket _and_ a nil error is returned, it means that the
   309  	// protocol is not supported. A non-nil error should only be returned
   310  	// if the protocol is supported, but an error occurs during creation.
   311  	Socket(t *kernel.Task, stype linux.SockType, protocol int) (*vfs.FileDescription, *syserr.Error)
   312  
   313  	// Pair creates a pair of connected sockets.
   314  	//
   315  	// See Socket for error information.
   316  	Pair(t *kernel.Task, stype linux.SockType, protocol int) (*vfs.FileDescription, *vfs.FileDescription, *syserr.Error)
   317  }
   318  
   319  // families holds a map of all known address families and their providers.
   320  var families = make(map[int][]Provider)
   321  
   322  // RegisterProvider registers the provider of a given address family so that
   323  // sockets of that type can be created via socket() and/or socketpair()
   324  // syscalls.
   325  //
   326  // This should only be called during the initialization of the address family.
   327  func RegisterProvider(family int, provider Provider) {
   328  	families[family] = append(families[family], provider)
   329  }
   330  
   331  // New creates a new socket with the given family, type and protocol.
   332  func New(t *kernel.Task, family int, stype linux.SockType, protocol int) (*vfs.FileDescription, *syserr.Error) {
   333  	for _, p := range families[family] {
   334  		s, err := p.Socket(t, stype, protocol)
   335  		if err != nil {
   336  			return nil, err
   337  		}
   338  		if s != nil {
   339  			t.Kernel().RecordSocket(s)
   340  			return s, nil
   341  		}
   342  	}
   343  
   344  	return nil, syserr.ErrAddressFamilyNotSupported
   345  }
   346  
   347  // Pair creates a new connected socket pair with the given family, type and
   348  // protocol.
   349  func Pair(t *kernel.Task, family int, stype linux.SockType, protocol int) (*vfs.FileDescription, *vfs.FileDescription, *syserr.Error) {
   350  	providers, ok := families[family]
   351  	if !ok {
   352  		return nil, nil, syserr.ErrAddressFamilyNotSupported
   353  	}
   354  
   355  	for _, p := range providers {
   356  		s1, s2, err := p.Pair(t, stype, protocol)
   357  		if err != nil {
   358  			return nil, nil, err
   359  		}
   360  		if s1 != nil && s2 != nil {
   361  			k := t.Kernel()
   362  			k.RecordSocket(s1)
   363  			k.RecordSocket(s2)
   364  			return s1, s2, nil
   365  		}
   366  	}
   367  
   368  	return nil, nil, syserr.ErrSocketNotSupported
   369  }
   370  
   371  // SendReceiveTimeout stores timeouts for send and receive calls.
   372  //
   373  // It is meant to be embedded into Socket implementations to help satisfy the
   374  // interface.
   375  //
   376  // Care must be taken when copying SendReceiveTimeout as it contains atomic
   377  // variables.
   378  //
   379  // +stateify savable
   380  type SendReceiveTimeout struct {
   381  	// send is length of the send timeout in nanoseconds.
   382  	//
   383  	// send must be accessed atomically.
   384  	send atomicbitops.Int64
   385  
   386  	// recv is length of the receive timeout in nanoseconds.
   387  	//
   388  	// recv must be accessed atomically.
   389  	recv atomicbitops.Int64
   390  }
   391  
   392  // SetRecvTimeout implements Socket.SetRecvTimeout.
   393  func (to *SendReceiveTimeout) SetRecvTimeout(nanoseconds int64) {
   394  	to.recv.Store(nanoseconds)
   395  }
   396  
   397  // RecvTimeout implements Socket.RecvTimeout.
   398  func (to *SendReceiveTimeout) RecvTimeout() int64 {
   399  	return to.recv.Load()
   400  }
   401  
   402  // SetSendTimeout implements Socket.SetSendTimeout.
   403  func (to *SendReceiveTimeout) SetSendTimeout(nanoseconds int64) {
   404  	to.send.Store(nanoseconds)
   405  }
   406  
   407  // SendTimeout implements Socket.SendTimeout.
   408  func (to *SendReceiveTimeout) SendTimeout() int64 {
   409  	return to.send.Load()
   410  }
   411  
   412  // UnmarshalSockAddr unmarshals memory representing a struct sockaddr to one of
   413  // the ABI socket address types.
   414  //
   415  // Precondition: data must be long enough to represent a socket address of the
   416  // given family.
   417  func UnmarshalSockAddr(family int, data []byte) linux.SockAddr {
   418  	switch family {
   419  	case unix.AF_INET:
   420  		var addr linux.SockAddrInet
   421  		addr.UnmarshalUnsafe(data)
   422  		return &addr
   423  	case unix.AF_INET6:
   424  		var addr linux.SockAddrInet6
   425  		addr.UnmarshalUnsafe(data)
   426  		return &addr
   427  	case unix.AF_UNIX:
   428  		var addr linux.SockAddrUnix
   429  		addr.UnmarshalUnsafe(data)
   430  		return &addr
   431  	case unix.AF_NETLINK:
   432  		var addr linux.SockAddrNetlink
   433  		addr.UnmarshalUnsafe(data)
   434  		return &addr
   435  	case unix.AF_PACKET:
   436  		var addr linux.SockAddrLink
   437  		addr.UnmarshalUnsafe(data)
   438  		return &addr
   439  	default:
   440  		panic(fmt.Sprintf("Unsupported socket family %v", family))
   441  	}
   442  }
   443  
   444  var sockAddrLinkSize = (&linux.SockAddrLink{}).SizeBytes()
   445  var sockAddrInetSize = (&linux.SockAddrInet{}).SizeBytes()
   446  var sockAddrInet6Size = (&linux.SockAddrInet6{}).SizeBytes()
   447  
   448  // Ntohs converts a 16-bit number from network byte order to host byte order. It
   449  // assumes that the host is little endian.
   450  func Ntohs(v uint16) uint16 {
   451  	return v<<8 | v>>8
   452  }
   453  
   454  // Htons converts a 16-bit number from host byte order to network byte order. It
   455  // assumes that the host is little endian.
   456  func Htons(v uint16) uint16 {
   457  	return Ntohs(v)
   458  }
   459  
   460  // isLinkLocal determines if the given IPv6 address is link-local. This is the
   461  // case when it has the fe80::/10 prefix. This check is used to determine when
   462  // the NICID is relevant for a given IPv6 address.
   463  func isLinkLocal(addr tcpip.Address) bool {
   464  	addrBytes := addr.AsSlice()
   465  	return len(addrBytes) >= 2 && addrBytes[0] == 0xfe && addrBytes[1]&0xc0 == 0x80
   466  }
   467  
   468  // ConvertAddress converts the given address to a native format.
   469  func ConvertAddress(family int, addr tcpip.FullAddress) (linux.SockAddr, uint32) {
   470  	switch family {
   471  	case linux.AF_INET:
   472  		var out linux.SockAddrInet
   473  		copy(out.Addr[:], addr.Addr.AsSlice())
   474  		out.Family = linux.AF_INET
   475  		out.Port = Htons(addr.Port)
   476  		return &out, uint32(sockAddrInetSize)
   477  
   478  	case linux.AF_INET6:
   479  		var out linux.SockAddrInet6
   480  		addrBytes := addr.Addr.AsSlice()
   481  		if len(addrBytes) == header.IPv4AddressSize {
   482  			// Copy address in v4-mapped format.
   483  			copy(out.Addr[12:], addrBytes)
   484  			out.Addr[10] = 0xff
   485  			out.Addr[11] = 0xff
   486  		} else {
   487  			copy(out.Addr[:], addrBytes)
   488  		}
   489  		out.Family = linux.AF_INET6
   490  		out.Port = Htons(addr.Port)
   491  		if isLinkLocal(addr.Addr) {
   492  			out.Scope_id = uint32(addr.NIC)
   493  		}
   494  		return &out, uint32(sockAddrInet6Size)
   495  
   496  	case linux.AF_PACKET:
   497  		var out linux.SockAddrLink
   498  		out.Family = linux.AF_PACKET
   499  		out.InterfaceIndex = int32(addr.NIC)
   500  		out.HardwareAddrLen = header.EthernetAddressSize
   501  		copy(out.HardwareAddr[:], addr.LinkAddr)
   502  		return &out, uint32(sockAddrLinkSize)
   503  
   504  	default:
   505  		return nil, 0
   506  	}
   507  }
   508  
   509  // BytesToIPAddress converts an IPv4 or IPv6 address from the user to the
   510  // netstack representation taking any addresses into account.
   511  func BytesToIPAddress(addr []byte) tcpip.Address {
   512  	if bytes.Equal(addr, make([]byte, 4)) || bytes.Equal(addr, make([]byte, 16)) {
   513  		return tcpip.Address{}
   514  	}
   515  	return tcpip.AddrFromSlice(addr)
   516  }
   517  
   518  // AddressAndFamily reads an sockaddr struct from the given address and
   519  // converts it to the FullAddress format. It supports AF_UNIX, AF_INET,
   520  // AF_INET6, and AF_PACKET addresses.
   521  //
   522  // AddressAndFamily returns an address and its family.
   523  func AddressAndFamily(addr []byte) (tcpip.FullAddress, uint16, *syserr.Error) {
   524  	// Make sure we have at least 2 bytes for the address family.
   525  	if len(addr) < 2 {
   526  		return tcpip.FullAddress{}, 0, syserr.ErrInvalidArgument
   527  	}
   528  
   529  	// Get the rest of the fields based on the address family.
   530  	switch family := hostarch.ByteOrder.Uint16(addr); family {
   531  	case linux.AF_INET:
   532  		var a linux.SockAddrInet
   533  		if len(addr) < sockAddrInetSize {
   534  			return tcpip.FullAddress{}, family, syserr.ErrInvalidArgument
   535  		}
   536  		a.UnmarshalUnsafe(addr)
   537  
   538  		out := tcpip.FullAddress{
   539  			Addr: BytesToIPAddress(a.Addr[:]),
   540  			Port: Ntohs(a.Port),
   541  		}
   542  		return out, family, nil
   543  
   544  	case linux.AF_INET6:
   545  		var a linux.SockAddrInet6
   546  		if len(addr) < sockAddrInet6Size {
   547  			return tcpip.FullAddress{}, family, syserr.ErrInvalidArgument
   548  		}
   549  		a.UnmarshalUnsafe(addr)
   550  
   551  		out := tcpip.FullAddress{
   552  			Addr: BytesToIPAddress(a.Addr[:]),
   553  			Port: Ntohs(a.Port),
   554  		}
   555  		if isLinkLocal(out.Addr) {
   556  			out.NIC = tcpip.NICID(a.Scope_id)
   557  		}
   558  		return out, family, nil
   559  
   560  	case linux.AF_PACKET:
   561  		var a linux.SockAddrLink
   562  		if len(addr) < sockAddrLinkSize {
   563  			return tcpip.FullAddress{}, family, syserr.ErrInvalidArgument
   564  		}
   565  		a.UnmarshalUnsafe(addr)
   566  		// TODO(https://gvisor.dev/issue/6530): Do not assume all interfaces have
   567  		// an ethernet address.
   568  		if a.Family != linux.AF_PACKET || a.HardwareAddrLen != header.EthernetAddressSize {
   569  			return tcpip.FullAddress{}, family, syserr.ErrInvalidArgument
   570  		}
   571  
   572  		return tcpip.FullAddress{
   573  			NIC:      tcpip.NICID(a.InterfaceIndex),
   574  			LinkAddr: tcpip.LinkAddress(a.HardwareAddr[:a.HardwareAddrLen]),
   575  			Port:     Ntohs(a.Protocol),
   576  		}, family, nil
   577  
   578  	case linux.AF_UNSPEC:
   579  		return tcpip.FullAddress{}, family, nil
   580  
   581  	default:
   582  		return tcpip.FullAddress{}, 0, syserr.ErrAddressFamilyNotSupported
   583  	}
   584  }
   585  
   586  // IsTCP returns true if the socket is a TCP socket.
   587  func IsTCP(s Socket) bool {
   588  	fam, typ, proto := s.Type()
   589  	if fam != linux.AF_INET && fam != linux.AF_INET6 {
   590  		return false
   591  	}
   592  	return typ == linux.SOCK_STREAM && (proto == 0 || proto == linux.IPPROTO_TCP)
   593  }
   594  
   595  // IsUDP returns true if the socket is a UDP socket.
   596  func IsUDP(s Socket) bool {
   597  	fam, typ, proto := s.Type()
   598  	if fam != linux.AF_INET && fam != linux.AF_INET6 {
   599  		return false
   600  	}
   601  	return typ == linux.SOCK_DGRAM && (proto == 0 || proto == linux.IPPROTO_UDP)
   602  }
   603  
   604  // IsICMP returns true if the socket is an ICMP socket.
   605  func IsICMP(s Socket) bool {
   606  	fam, typ, proto := s.Type()
   607  	if fam != linux.AF_INET && fam != linux.AF_INET6 {
   608  		return false
   609  	}
   610  	return typ == linux.SOCK_DGRAM && (proto == linux.IPPROTO_ICMP || proto == linux.IPPROTO_ICMPV6)
   611  }
   612  
   613  // IsRaw returns true if the socket is a raw socket.
   614  func IsRaw(s Socket) bool {
   615  	fam, typ, _ := s.Type()
   616  	if fam != linux.AF_INET && fam != linux.AF_INET6 {
   617  		return false
   618  	}
   619  	return typ == linux.SOCK_RAW
   620  }