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