| 744 | |
| 745 | |
| 746 | class TCP(Packet): |
| 747 | name = "TCP" |
| 748 | fields_desc = [ShortEnumField("sport", 20, TCP_SERVICES), |
| 749 | ShortEnumField("dport", 80, TCP_SERVICES), |
| 750 | IntField("seq", 0), |
| 751 | IntField("ack", 0), |
| 752 | BitField("dataofs", None, 4), |
| 753 | BitField("reserved", 0, 3), |
| 754 | FlagsField("flags", 0x2, 9, "FSRPAUECN"), |
| 755 | ShortField("window", 8192), |
| 756 | XShortField("chksum", None), |
| 757 | ShortField("urgptr", 0), |
| 758 | TCPOptionsField("options", "")] |
| 759 | |
| 760 | def post_build(self, p, pay): |
| 761 | p += pay |
| 762 | dataofs = self.dataofs |
| 763 | if dataofs is None: |
| 764 | opt_len = len(self.get_field("options").i2m(self, self.options)) |
| 765 | dataofs = 5 + ((opt_len + 3) // 4) |
| 766 | dataofs = (dataofs << 4) | orb(p[12]) & 0x0f |
| 767 | p = p[:12] + chb(dataofs & 0xff) + p[13:] |
| 768 | if self.chksum is None: |
| 769 | if isinstance(self.underlayer, IP): |
| 770 | ck = in4_chksum(socket.IPPROTO_TCP, self.underlayer, p) |
| 771 | p = p[:16] + struct.pack("!H", ck) + p[18:] |
| 772 | elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr): # noqa: E501 |
| 773 | ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p) # noqa: E501 |
| 774 | p = p[:16] + struct.pack("!H", ck) + p[18:] |
| 775 | else: |
| 776 | log_runtime.info( |
| 777 | "No IP underlayer to compute checksum. Leaving null." |
| 778 | ) |
| 779 | return p |
| 780 | |
| 781 | def hashret(self): |
| 782 | if conf.checkIPsrc: |
| 783 | return struct.pack("H", self.sport ^ self.dport) + self.payload.hashret() # noqa: E501 |
| 784 | else: |
| 785 | return self.payload.hashret() |
| 786 | |
| 787 | def answers(self, other): |
| 788 | if not isinstance(other, TCP): |
| 789 | return 0 |
| 790 | # RST packets don't get answers |
| 791 | if other.flags.R: |
| 792 | return 0 |
| 793 | # We do not support the four-way handshakes with the SYN+ACK |
| 794 | # answer split in two packets (one ACK and one SYN): in that |
| 795 | # case the ACK will be seen as an answer, but not the SYN. |
| 796 | if self.flags.S: |
| 797 | # SYN packets without ACK are not answers |
| 798 | if not self.flags.A: |
| 799 | return 0 |
| 800 | # SYN+ACK packets answer SYN packets |
| 801 | if not other.flags.S: |
| 802 | return 0 |
| 803 | if conf.checkIPsrc: |
no test coverage detected