(ipv4 *layers.IPv4, tcp *layers.TCP, payload []byte)
| 408 | } |
| 409 | |
| 410 | func (s *tcpStack) handlePacket(ipv4 *layers.IPv4, tcp *layers.TCP, payload []byte) { |
| 411 | // it happens that a process will connect to the same remote service multiple times in from |
| 412 | // different source ports so we must key by a descriptor that includes both endpoints |
| 413 | dst := AddrPort{Addr: ipv4.DstIP, Port: uint16(tcp.DstPort)} |
| 414 | src := AddrPort{Addr: ipv4.SrcIP, Port: uint16(tcp.SrcPort)} |
| 415 | |
| 416 | // put source address, source port, destination address, and destination port into a human-readable string |
| 417 | srcdst := src.String() + " => " + dst.String() |
| 418 | stream, found := s.streamsBySrcDst[srcdst] |
| 419 | if !found { |
| 420 | // create a new stream no matter what kind of packet this is |
| 421 | // later we will reject everything other than SYN packets sent to a fresh stream |
| 422 | stream = newTCPStream(dst, src, s.toSubprocess) |
| 423 | stream.ack = tcp.Seq |
| 424 | s.streamsBySrcDst[srcdst] = stream |
| 425 | } |
| 426 | |
| 427 | // handle connection establishment |
| 428 | if tcp.SYN && stream.state == StateInit { |
| 429 | stream.state = StateSynReceived |
| 430 | atomic.StoreUint32(&stream.ack, tcp.Seq+1) |
| 431 | verbosef("got SYN to %v:%v, now state is %v", ipv4.DstIP, tcp.DstPort, stream.state) |
| 432 | s.app.notifyTCP(stream) |
| 433 | } |
| 434 | |
| 435 | // handle connection teardown |
| 436 | if tcp.FIN && stream.state != StateInit { |
| 437 | // according to the tcp spec we are always allowed to ack the other side's FIN, even if we have |
| 438 | // already sent our own FIN |
| 439 | stream.state = StateOtherSideFinished |
| 440 | seq := atomic.AddUint32(&stream.seq, 1) - 1 |
| 441 | atomic.StoreUint32(&stream.ack, tcp.Seq+1) |
| 442 | verbosef("got FIN to %v:%v, now state is %v", ipv4.DstIP, tcp.DstPort, stream.state) |
| 443 | |
| 444 | // make a FIN+ACK reply to send to the subprocess |
| 445 | replytcp := layers.TCP{ |
| 446 | SrcPort: tcp.DstPort, |
| 447 | DstPort: tcp.SrcPort, |
| 448 | FIN: true, |
| 449 | ACK: true, |
| 450 | Seq: seq, |
| 451 | Ack: tcp.Seq + 1, |
| 452 | Window: 64240, // number of bytes we are willing to receive (copied from sender) |
| 453 | } |
| 454 | |
| 455 | replyipv4 := layers.IPv4{ |
| 456 | Version: 4, // indicates IPv4 |
| 457 | TTL: ttl, |
| 458 | Protocol: layers.IPProtocolTCP, |
| 459 | SrcIP: ipv4.DstIP, |
| 460 | DstIP: ipv4.SrcIP, |
| 461 | } |
| 462 | |
| 463 | replytcp.SetNetworkLayerForChecksum(&replyipv4) |
| 464 | |
| 465 | // log |
| 466 | verbosef("sending FIN+ACK to subprocess: %s", summarizeTCP(&replyipv4, &replytcp, nil)) |
| 467 |
nothing calls this directly
no test coverage detected