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 }