github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/tcpip/transport/icmp/endpoint.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 icmp 16 17 import ( 18 "sync" 19 20 "github.com/google/netstack/tcpip" 21 "github.com/google/netstack/tcpip/buffer" 22 "github.com/google/netstack/tcpip/header" 23 "github.com/google/netstack/tcpip/iptables" 24 "github.com/google/netstack/tcpip/stack" 25 "github.com/google/netstack/waiter" 26 ) 27 28 // +stateify savable 29 type icmpPacket struct { 30 icmpPacketEntry 31 senderAddress tcpip.FullAddress 32 data buffer.VectorisedView 33 timestamp int64 34 } 35 36 type endpointState int 37 38 const ( 39 stateInitial endpointState = iota 40 stateBound 41 stateConnected 42 stateClosed 43 ) 44 45 // endpoint represents an ICMP endpoint. This struct serves as the interface 46 // between users of the endpoint and the protocol implementation; it is legal to 47 // have concurrent goroutines make calls into the endpoint, they are properly 48 // synchronized. 49 // 50 // +stateify savable 51 type endpoint struct { 52 stack.TransportEndpointInfo 53 54 // The following fields are initialized at creation time and are 55 // immutable. 56 stack *stack.Stack 57 waiterQueue *waiter.Queue 58 uniqueID uint64 59 60 // The following fields are used to manage the receive queue, and are 61 // protected by rcvMu. 62 rcvMu sync.Mutex 63 rcvReady bool 64 rcvList icmpPacketList 65 rcvBufSizeMax int 66 rcvBufSize int 67 rcvClosed bool 68 69 // The following fields are protected by the mu mutex. 70 mu sync.RWMutex 71 sndBufSize int 72 // shutdownFlags represent the current shutdown state of the endpoint. 73 shutdownFlags tcpip.ShutdownFlags 74 state endpointState 75 route stack.Route 76 ttl uint8 77 stats tcpip.TransportEndpointStats 78 } 79 80 func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProto tcpip.TransportProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { 81 return &endpoint{ 82 stack: s, 83 TransportEndpointInfo: stack.TransportEndpointInfo{ 84 NetProto: netProto, 85 TransProto: transProto, 86 }, 87 waiterQueue: waiterQueue, 88 rcvBufSizeMax: 32 * 1024, 89 sndBufSize: 32 * 1024, 90 state: stateInitial, 91 uniqueID: s.UniqueID(), 92 }, nil 93 } 94 95 // UniqueID implements stack.TransportEndpoint.UniqueID. 96 func (e *endpoint) UniqueID() uint64 { 97 return e.uniqueID 98 } 99 100 // Close puts the endpoint in a closed state and frees all resources 101 // associated with it. 102 func (e *endpoint) Close() { 103 e.mu.Lock() 104 e.shutdownFlags = tcpip.ShutdownRead | tcpip.ShutdownWrite 105 switch e.state { 106 case stateBound, stateConnected: 107 e.stack.UnregisterTransportEndpoint(e.RegisterNICID, []tcpip.NetworkProtocolNumber{e.NetProto}, e.TransProto, e.ID, e, 0 /* bindToDevice */) 108 } 109 110 // Close the receive list and drain it. 111 e.rcvMu.Lock() 112 e.rcvClosed = true 113 e.rcvBufSize = 0 114 for !e.rcvList.Empty() { 115 p := e.rcvList.Front() 116 e.rcvList.Remove(p) 117 } 118 e.rcvMu.Unlock() 119 120 e.route.Release() 121 122 // Update the state. 123 e.state = stateClosed 124 125 e.mu.Unlock() 126 127 e.waiterQueue.Notify(waiter.EventHUp | waiter.EventErr | waiter.EventIn | waiter.EventOut) 128 } 129 130 // ModerateRecvBuf implements tcpip.Endpoint.ModerateRecvBuf. 131 func (e *endpoint) ModerateRecvBuf(copied int) {} 132 133 // IPTables implements tcpip.Endpoint.IPTables. 134 func (e *endpoint) IPTables() (iptables.IPTables, error) { 135 return e.stack.IPTables(), nil 136 } 137 138 // Read reads data from the endpoint. This method does not block if 139 // there is no data pending. 140 func (e *endpoint) Read(addr *tcpip.FullAddress) (buffer.View, tcpip.ControlMessages, *tcpip.Error) { 141 e.rcvMu.Lock() 142 143 if e.rcvList.Empty() { 144 err := tcpip.ErrWouldBlock 145 if e.rcvClosed { 146 e.stats.ReadErrors.ReadClosed.Increment() 147 err = tcpip.ErrClosedForReceive 148 } 149 e.rcvMu.Unlock() 150 return buffer.View{}, tcpip.ControlMessages{}, err 151 } 152 153 p := e.rcvList.Front() 154 e.rcvList.Remove(p) 155 e.rcvBufSize -= p.data.Size() 156 157 e.rcvMu.Unlock() 158 159 if addr != nil { 160 *addr = p.senderAddress 161 } 162 163 return p.data.ToView(), tcpip.ControlMessages{HasTimestamp: true, Timestamp: p.timestamp}, nil 164 } 165 166 // prepareForWrite prepares the endpoint for sending data. In particular, it 167 // binds it if it's still in the initial state. To do so, it must first 168 // reacquire the mutex in exclusive mode. 169 // 170 // Returns true for retry if preparation should be retried. 171 func (e *endpoint) prepareForWrite(to *tcpip.FullAddress) (retry bool, err *tcpip.Error) { 172 switch e.state { 173 case stateInitial: 174 case stateConnected: 175 return false, nil 176 177 case stateBound: 178 if to == nil { 179 return false, tcpip.ErrDestinationRequired 180 } 181 return false, nil 182 default: 183 return false, tcpip.ErrInvalidEndpointState 184 } 185 186 e.mu.RUnlock() 187 defer e.mu.RLock() 188 189 e.mu.Lock() 190 defer e.mu.Unlock() 191 192 // The state changed when we released the shared locked and re-acquired 193 // it in exclusive mode. Try again. 194 if e.state != stateInitial { 195 return true, nil 196 } 197 198 // The state is still 'initial', so try to bind the endpoint. 199 if err := e.bindLocked(tcpip.FullAddress{}); err != nil { 200 return false, err 201 } 202 203 return true, nil 204 } 205 206 // Write writes data to the endpoint's peer. This method does not block 207 // if the data cannot be written. 208 func (e *endpoint) Write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, <-chan struct{}, *tcpip.Error) { 209 n, ch, err := e.write(p, opts) 210 switch err { 211 case nil: 212 e.stats.PacketsSent.Increment() 213 case tcpip.ErrMessageTooLong, tcpip.ErrInvalidOptionValue: 214 e.stats.WriteErrors.InvalidArgs.Increment() 215 case tcpip.ErrClosedForSend: 216 e.stats.WriteErrors.WriteClosed.Increment() 217 case tcpip.ErrInvalidEndpointState: 218 e.stats.WriteErrors.InvalidEndpointState.Increment() 219 case tcpip.ErrNoLinkAddress: 220 e.stats.SendErrors.NoLinkAddr.Increment() 221 case tcpip.ErrNoRoute, tcpip.ErrBroadcastDisabled, tcpip.ErrNetworkUnreachable: 222 // Errors indicating any problem with IP routing of the packet. 223 e.stats.SendErrors.NoRoute.Increment() 224 default: 225 // For all other errors when writing to the network layer. 226 e.stats.SendErrors.SendToNetworkFailed.Increment() 227 } 228 return n, ch, err 229 } 230 231 func (e *endpoint) write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, <-chan struct{}, *tcpip.Error) { 232 // MSG_MORE is unimplemented. (This also means that MSG_EOR is a no-op.) 233 if opts.More { 234 return 0, nil, tcpip.ErrInvalidOptionValue 235 } 236 237 to := opts.To 238 239 e.mu.RLock() 240 defer e.mu.RUnlock() 241 242 // If we've shutdown with SHUT_WR we are in an invalid state for sending. 243 if e.shutdownFlags&tcpip.ShutdownWrite != 0 { 244 return 0, nil, tcpip.ErrClosedForSend 245 } 246 247 // Prepare for write. 248 for { 249 retry, err := e.prepareForWrite(to) 250 if err != nil { 251 return 0, nil, err 252 } 253 254 if !retry { 255 break 256 } 257 } 258 259 var route *stack.Route 260 if to == nil { 261 route = &e.route 262 263 if route.IsResolutionRequired() { 264 // Promote lock to exclusive if using a shared route, 265 // given that it may need to change in Route.Resolve() 266 // call below. 267 e.mu.RUnlock() 268 defer e.mu.RLock() 269 270 e.mu.Lock() 271 defer e.mu.Unlock() 272 273 // Recheck state after lock was re-acquired. 274 if e.state != stateConnected { 275 return 0, nil, tcpip.ErrInvalidEndpointState 276 } 277 } 278 } else { 279 // Reject destination address if it goes through a different 280 // NIC than the endpoint was bound to. 281 nicID := to.NIC 282 if e.BindNICID != 0 { 283 if nicID != 0 && nicID != e.BindNICID { 284 return 0, nil, tcpip.ErrNoRoute 285 } 286 287 nicID = e.BindNICID 288 } 289 290 toCopy := *to 291 to = &toCopy 292 netProto, err := e.checkV4Mapped(to, true) 293 if err != nil { 294 return 0, nil, err 295 } 296 297 // Find the enpoint. 298 r, err := e.stack.FindRoute(nicID, e.BindAddr, to.Addr, netProto, false /* multicastLoop */) 299 if err != nil { 300 return 0, nil, err 301 } 302 defer r.Release() 303 304 route = &r 305 } 306 307 if route.IsResolutionRequired() { 308 if ch, err := route.Resolve(nil); err != nil { 309 if err == tcpip.ErrWouldBlock { 310 return 0, ch, tcpip.ErrNoLinkAddress 311 } 312 return 0, nil, err 313 } 314 } 315 316 v, err := p.FullPayload() 317 if err != nil { 318 return 0, nil, err 319 } 320 321 switch e.NetProto { 322 case header.IPv4ProtocolNumber: 323 err = send4(route, e.ID.LocalPort, v, e.ttl) 324 325 case header.IPv6ProtocolNumber: 326 err = send6(route, e.ID.LocalPort, v, e.ttl) 327 } 328 329 if err != nil { 330 return 0, nil, err 331 } 332 333 return int64(len(v)), nil, nil 334 } 335 336 // Peek only returns data from a single datagram, so do nothing here. 337 func (e *endpoint) Peek([][]byte) (int64, tcpip.ControlMessages, *tcpip.Error) { 338 return 0, tcpip.ControlMessages{}, nil 339 } 340 341 // SetSockOpt sets a socket option. 342 func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error { 343 switch o := opt.(type) { 344 case tcpip.TTLOption: 345 e.mu.Lock() 346 e.ttl = uint8(o) 347 e.mu.Unlock() 348 } 349 350 return nil 351 } 352 353 // SetSockOptInt sets a socket option. Currently not supported. 354 func (e *endpoint) SetSockOptInt(opt tcpip.SockOpt, v int) *tcpip.Error { 355 return nil 356 } 357 358 // GetSockOptInt implements tcpip.Endpoint.GetSockOptInt. 359 func (e *endpoint) GetSockOptInt(opt tcpip.SockOpt) (int, *tcpip.Error) { 360 switch opt { 361 case tcpip.ReceiveQueueSizeOption: 362 v := 0 363 e.rcvMu.Lock() 364 if !e.rcvList.Empty() { 365 p := e.rcvList.Front() 366 v = p.data.Size() 367 } 368 e.rcvMu.Unlock() 369 return v, nil 370 case tcpip.SendBufferSizeOption: 371 e.mu.Lock() 372 v := e.sndBufSize 373 e.mu.Unlock() 374 return v, nil 375 376 case tcpip.ReceiveBufferSizeOption: 377 e.rcvMu.Lock() 378 v := e.rcvBufSizeMax 379 e.rcvMu.Unlock() 380 return v, nil 381 382 } 383 return -1, tcpip.ErrUnknownProtocolOption 384 } 385 386 // GetSockOpt implements tcpip.Endpoint.GetSockOpt. 387 func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error { 388 switch o := opt.(type) { 389 case tcpip.ErrorOption: 390 return nil 391 392 case *tcpip.KeepaliveEnabledOption: 393 *o = 0 394 return nil 395 396 case *tcpip.TTLOption: 397 e.rcvMu.Lock() 398 *o = tcpip.TTLOption(e.ttl) 399 e.rcvMu.Unlock() 400 return nil 401 402 default: 403 return tcpip.ErrUnknownProtocolOption 404 } 405 } 406 407 func send4(r *stack.Route, ident uint16, data buffer.View, ttl uint8) *tcpip.Error { 408 if len(data) < header.ICMPv4MinimumSize { 409 return tcpip.ErrInvalidEndpointState 410 } 411 412 hdr := buffer.NewPrependable(header.ICMPv4MinimumSize + int(r.MaxHeaderLength())) 413 414 icmpv4 := header.ICMPv4(hdr.Prepend(header.ICMPv4MinimumSize)) 415 copy(icmpv4, data) 416 // Set the ident to the user-specified port. Sequence number should 417 // already be set by the user. 418 icmpv4.SetIdent(ident) 419 data = data[header.ICMPv4MinimumSize:] 420 421 // Linux performs these basic checks. 422 if icmpv4.Type() != header.ICMPv4Echo || icmpv4.Code() != 0 { 423 return tcpip.ErrInvalidEndpointState 424 } 425 426 icmpv4.SetChecksum(0) 427 icmpv4.SetChecksum(^header.Checksum(icmpv4, header.Checksum(data, 0))) 428 429 if ttl == 0 { 430 ttl = r.DefaultTTL() 431 } 432 return r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: header.ICMPv4ProtocolNumber, TTL: ttl, TOS: stack.DefaultTOS}, tcpip.PacketBuffer{ 433 Header: hdr, 434 Data: data.ToVectorisedView(), 435 TransportHeader: buffer.View(icmpv4), 436 }) 437 } 438 439 func send6(r *stack.Route, ident uint16, data buffer.View, ttl uint8) *tcpip.Error { 440 if len(data) < header.ICMPv6EchoMinimumSize { 441 return tcpip.ErrInvalidEndpointState 442 } 443 444 hdr := buffer.NewPrependable(header.ICMPv6MinimumSize + int(r.MaxHeaderLength())) 445 446 icmpv6 := header.ICMPv6(hdr.Prepend(header.ICMPv6MinimumSize)) 447 copy(icmpv6, data) 448 // Set the ident. Sequence number is provided by the user. 449 icmpv6.SetIdent(ident) 450 data = data[header.ICMPv6MinimumSize:] 451 452 if icmpv6.Type() != header.ICMPv6EchoRequest || icmpv6.Code() != 0 { 453 return tcpip.ErrInvalidEndpointState 454 } 455 456 dataVV := data.ToVectorisedView() 457 icmpv6.SetChecksum(header.ICMPv6Checksum(icmpv6, r.LocalAddress, r.RemoteAddress, dataVV)) 458 459 if ttl == 0 { 460 ttl = r.DefaultTTL() 461 } 462 return r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: ttl, TOS: stack.DefaultTOS}, tcpip.PacketBuffer{ 463 Header: hdr, 464 Data: dataVV, 465 TransportHeader: buffer.View(icmpv6), 466 }) 467 } 468 469 func (e *endpoint) checkV4Mapped(addr *tcpip.FullAddress, allowMismatch bool) (tcpip.NetworkProtocolNumber, *tcpip.Error) { 470 netProto := e.NetProto 471 if header.IsV4MappedAddress(addr.Addr) { 472 return 0, tcpip.ErrNoRoute 473 } 474 475 // Fail if we're bound to an address length different from the one we're 476 // checking. 477 if l := len(e.ID.LocalAddress); !allowMismatch && l != 0 && l != len(addr.Addr) { 478 return 0, tcpip.ErrInvalidEndpointState 479 } 480 481 return netProto, nil 482 } 483 484 // Disconnect implements tcpip.Endpoint.Disconnect. 485 func (*endpoint) Disconnect() *tcpip.Error { 486 return tcpip.ErrNotSupported 487 } 488 489 // Connect connects the endpoint to its peer. Specifying a NIC is optional. 490 func (e *endpoint) Connect(addr tcpip.FullAddress) *tcpip.Error { 491 e.mu.Lock() 492 defer e.mu.Unlock() 493 494 nicID := addr.NIC 495 localPort := uint16(0) 496 switch e.state { 497 case stateBound, stateConnected: 498 localPort = e.ID.LocalPort 499 if e.BindNICID == 0 { 500 break 501 } 502 503 if nicID != 0 && nicID != e.BindNICID { 504 return tcpip.ErrInvalidEndpointState 505 } 506 507 nicID = e.BindNICID 508 default: 509 return tcpip.ErrInvalidEndpointState 510 } 511 512 netProto, err := e.checkV4Mapped(&addr, false) 513 if err != nil { 514 return err 515 } 516 517 // Find a route to the desired destination. 518 r, err := e.stack.FindRoute(nicID, e.BindAddr, addr.Addr, netProto, false /* multicastLoop */) 519 if err != nil { 520 return err 521 } 522 defer r.Release() 523 524 id := stack.TransportEndpointID{ 525 LocalAddress: r.LocalAddress, 526 LocalPort: localPort, 527 RemoteAddress: r.RemoteAddress, 528 } 529 530 // Even if we're connected, this endpoint can still be used to send 531 // packets on a different network protocol, so we register both even if 532 // v6only is set to false and this is an ipv6 endpoint. 533 netProtos := []tcpip.NetworkProtocolNumber{netProto} 534 535 id, err = e.registerWithStack(nicID, netProtos, id) 536 if err != nil { 537 return err 538 } 539 540 e.ID = id 541 e.route = r.Clone() 542 e.RegisterNICID = nicID 543 544 e.state = stateConnected 545 546 e.rcvMu.Lock() 547 e.rcvReady = true 548 e.rcvMu.Unlock() 549 550 return nil 551 } 552 553 // ConnectEndpoint is not supported. 554 func (*endpoint) ConnectEndpoint(tcpip.Endpoint) *tcpip.Error { 555 return tcpip.ErrInvalidEndpointState 556 } 557 558 // Shutdown closes the read and/or write end of the endpoint connection 559 // to its peer. 560 func (e *endpoint) Shutdown(flags tcpip.ShutdownFlags) *tcpip.Error { 561 e.mu.Lock() 562 defer e.mu.Unlock() 563 e.shutdownFlags |= flags 564 565 if e.state != stateConnected { 566 return tcpip.ErrNotConnected 567 } 568 569 if flags&tcpip.ShutdownRead != 0 { 570 e.rcvMu.Lock() 571 wasClosed := e.rcvClosed 572 e.rcvClosed = true 573 e.rcvMu.Unlock() 574 575 if !wasClosed { 576 e.waiterQueue.Notify(waiter.EventIn) 577 } 578 } 579 580 return nil 581 } 582 583 // Listen is not supported by UDP, it just fails. 584 func (*endpoint) Listen(int) *tcpip.Error { 585 return tcpip.ErrNotSupported 586 } 587 588 // Accept is not supported by UDP, it just fails. 589 func (*endpoint) Accept() (tcpip.Endpoint, *waiter.Queue, *tcpip.Error) { 590 return nil, nil, tcpip.ErrNotSupported 591 } 592 593 func (e *endpoint) registerWithStack(nicID tcpip.NICID, netProtos []tcpip.NetworkProtocolNumber, id stack.TransportEndpointID) (stack.TransportEndpointID, *tcpip.Error) { 594 if id.LocalPort != 0 { 595 // The endpoint already has a local port, just attempt to 596 // register it. 597 err := e.stack.RegisterTransportEndpoint(nicID, netProtos, e.TransProto, id, e, false /* reuse */, 0 /* bindToDevice */) 598 return id, err 599 } 600 601 // We need to find a port for the endpoint. 602 _, err := e.stack.PickEphemeralPort(func(p uint16) (bool, *tcpip.Error) { 603 id.LocalPort = p 604 err := e.stack.RegisterTransportEndpoint(nicID, netProtos, e.TransProto, id, e, false /* reuse */, 0 /* bindtodevice */) 605 switch err { 606 case nil: 607 return true, nil 608 case tcpip.ErrPortInUse: 609 return false, nil 610 default: 611 return false, err 612 } 613 }) 614 615 return id, err 616 } 617 618 func (e *endpoint) bindLocked(addr tcpip.FullAddress) *tcpip.Error { 619 // Don't allow binding once endpoint is not in the initial state 620 // anymore. 621 if e.state != stateInitial { 622 return tcpip.ErrInvalidEndpointState 623 } 624 625 netProto, err := e.checkV4Mapped(&addr, false) 626 if err != nil { 627 return err 628 } 629 630 // Expand netProtos to include v4 and v6 if the caller is binding to a 631 // wildcard (empty) address, and this is an IPv6 endpoint with v6only 632 // set to false. 633 netProtos := []tcpip.NetworkProtocolNumber{netProto} 634 635 if len(addr.Addr) != 0 { 636 // A local address was specified, verify that it's valid. 637 if e.stack.CheckLocalAddress(addr.NIC, netProto, addr.Addr) == 0 { 638 return tcpip.ErrBadLocalAddress 639 } 640 } 641 642 id := stack.TransportEndpointID{ 643 LocalPort: addr.Port, 644 LocalAddress: addr.Addr, 645 } 646 id, err = e.registerWithStack(addr.NIC, netProtos, id) 647 if err != nil { 648 return err 649 } 650 651 e.ID = id 652 e.RegisterNICID = addr.NIC 653 654 // Mark endpoint as bound. 655 e.state = stateBound 656 657 e.rcvMu.Lock() 658 e.rcvReady = true 659 e.rcvMu.Unlock() 660 661 return nil 662 } 663 664 // Bind binds the endpoint to a specific local address and port. 665 // Specifying a NIC is optional. 666 func (e *endpoint) Bind(addr tcpip.FullAddress) *tcpip.Error { 667 e.mu.Lock() 668 defer e.mu.Unlock() 669 670 err := e.bindLocked(addr) 671 if err != nil { 672 return err 673 } 674 675 e.BindNICID = addr.NIC 676 e.BindAddr = addr.Addr 677 678 return nil 679 } 680 681 // GetLocalAddress returns the address to which the endpoint is bound. 682 func (e *endpoint) GetLocalAddress() (tcpip.FullAddress, *tcpip.Error) { 683 e.mu.RLock() 684 defer e.mu.RUnlock() 685 686 return tcpip.FullAddress{ 687 NIC: e.RegisterNICID, 688 Addr: e.ID.LocalAddress, 689 Port: e.ID.LocalPort, 690 }, nil 691 } 692 693 // GetRemoteAddress returns the address to which the endpoint is connected. 694 func (e *endpoint) GetRemoteAddress() (tcpip.FullAddress, *tcpip.Error) { 695 e.mu.RLock() 696 defer e.mu.RUnlock() 697 698 if e.state != stateConnected { 699 return tcpip.FullAddress{}, tcpip.ErrNotConnected 700 } 701 702 return tcpip.FullAddress{ 703 NIC: e.RegisterNICID, 704 Addr: e.ID.RemoteAddress, 705 Port: e.ID.RemotePort, 706 }, nil 707 } 708 709 // Readiness returns the current readiness of the endpoint. For example, if 710 // waiter.EventIn is set, the endpoint is immediately readable. 711 func (e *endpoint) Readiness(mask waiter.EventMask) waiter.EventMask { 712 // The endpoint is always writable. 713 result := waiter.EventOut & mask 714 715 // Determine if the endpoint is readable if requested. 716 if (mask & waiter.EventIn) != 0 { 717 e.rcvMu.Lock() 718 if !e.rcvList.Empty() || e.rcvClosed { 719 result |= waiter.EventIn 720 } 721 e.rcvMu.Unlock() 722 } 723 724 return result 725 } 726 727 // HandlePacket is called by the stack when new packets arrive to this transport 728 // endpoint. 729 func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, pkt tcpip.PacketBuffer) { 730 // Only accept echo replies. 731 switch e.NetProto { 732 case header.IPv4ProtocolNumber: 733 h := header.ICMPv4(pkt.Data.First()) 734 if h.Type() != header.ICMPv4EchoReply { 735 e.stack.Stats().DroppedPackets.Increment() 736 e.stats.ReceiveErrors.MalformedPacketsReceived.Increment() 737 return 738 } 739 case header.IPv6ProtocolNumber: 740 h := header.ICMPv6(pkt.Data.First()) 741 if h.Type() != header.ICMPv6EchoReply { 742 e.stack.Stats().DroppedPackets.Increment() 743 e.stats.ReceiveErrors.MalformedPacketsReceived.Increment() 744 return 745 } 746 } 747 748 e.rcvMu.Lock() 749 750 // Drop the packet if our buffer is currently full. 751 if !e.rcvReady || e.rcvClosed { 752 e.rcvMu.Unlock() 753 e.stack.Stats().DroppedPackets.Increment() 754 e.stats.ReceiveErrors.ClosedReceiver.Increment() 755 return 756 } 757 758 if e.rcvBufSize >= e.rcvBufSizeMax { 759 e.rcvMu.Unlock() 760 e.stack.Stats().DroppedPackets.Increment() 761 e.stats.ReceiveErrors.ReceiveBufferOverflow.Increment() 762 return 763 } 764 765 wasEmpty := e.rcvBufSize == 0 766 767 // Push new packet into receive list and increment the buffer size. 768 packet := &icmpPacket{ 769 senderAddress: tcpip.FullAddress{ 770 NIC: r.NICID(), 771 Addr: id.RemoteAddress, 772 }, 773 } 774 775 packet.data = pkt.Data 776 777 e.rcvList.PushBack(packet) 778 e.rcvBufSize += packet.data.Size() 779 780 packet.timestamp = e.stack.NowNanoseconds() 781 782 e.rcvMu.Unlock() 783 e.stats.PacketsReceived.Increment() 784 // Notify any waiters that there's data to be read now. 785 if wasEmpty { 786 e.waiterQueue.Notify(waiter.EventIn) 787 } 788 } 789 790 // HandleControlPacket implements stack.TransportEndpoint.HandleControlPacket. 791 func (e *endpoint) HandleControlPacket(id stack.TransportEndpointID, typ stack.ControlType, extra uint32, pkt tcpip.PacketBuffer) { 792 } 793 794 // State implements tcpip.Endpoint.State. The ICMP endpoint currently doesn't 795 // expose internal socket state. 796 func (e *endpoint) State() uint32 { 797 return 0 798 } 799 800 // Info returns a copy of the endpoint info. 801 func (e *endpoint) Info() tcpip.EndpointInfo { 802 e.mu.RLock() 803 // Make a copy of the endpoint info. 804 ret := e.TransportEndpointInfo 805 e.mu.RUnlock() 806 return &ret 807 } 808 809 // Stats returns a pointer to the endpoint stats. 810 func (e *endpoint) Stats() tcpip.EndpointStats { 811 return &e.stats 812 } 813 814 // Wait implements stack.TransportEndpoint.Wait. 815 func (*endpoint) Wait() {}