Calculating TCP Header Length? - networking

Can anyone guide me on the following?
I'm trying to figure out the answer as seen in the first question inside the blog malwarejake[.]blogspot.com/2015/05/packet-analysis-practice-part-3.html .
As per sample packet found
What is the embedded protocol, the destination port, and the amount of data not including protocol headers?
0x0000: 4500 004c 1986 4000 4006 9cba c0a8 0165
0x0010: c0a8 01b6 0015 bf3c dad0 5039 2a8c 25be
0x0020: 8018 0072 06ec 0000 0101 080a 008a 70ac
The answer for the above question is as above.
Embedded protocol: TCP
Total packet length: 76
IP Header length: 20
Protocol header length: 32
Data length: 24
Dest Port: 0xbf3c (48956)
I managed to get all the other answer with the exception of Protocol Header Length and Data Length.
Isn't TCP Header Length normally 20 bytes with the extension up to 40 bytes? But how is 32 bytes derived from the above packet? I don't understand.
Thanks!

Here's the TCP Header directly from the RFC:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The values 0015 and bf3c are the ports.
The values dad0 5039 and 2a8c 25be are the sequence/ack numbers.
Now take a look at the next 4 bits. The ones at offset 0x20. The value of the byte is 0x80, which means that the topmost 4 bits are 1000. They correspond to the "data offset" field:
Data Offset: 4 bits
The number of 32 bit words in the TCP Header. This indicates where
the data begins. The TCP header (even one including options) is an
integral number of 32 bits long.
So 1000 means that the header consists of 8 x 32-bit words, which means 8 x 4 bytes = 32 bytes.

Related

how do you tidy and combine two data frames with slightly different primary keys?

stream table
experiment
protocol
test
stream_size
metric
value
1
tcp
stream
64
throughput Gbps
10
1
tcp
stream
64
cpu utilization
.5
2
tcp
stream
64
throughput Gbps
40
2
tcp
stream
64
cpu utilization
.9
3
udp
stream
64
throughput Gbps
20
3
udp
stream
64
cpu utilization
.5
4
udp
stream
64
throughput Gbps
60
4
udp
stream
64
cpu utilization
.8
rr table
experiment
protocol
test
request_size
response_size
metric
value
5
tcp
request and response
64
64
transactions per second
10
5
tcp
request and response
64
64
cpu utilization
.6
6
tcp
request and response
64
1024
transactions per second
8
6
tcp
request and response
64
1024
cpu utilization
.5
7
udp
request and response
64
64
transactions per second
30
7
udp
request and response
64
64
cpu utilization
.4
8
udp
request and response
64
1024
transactions per second
29
8
udp
request and response
64
64
cpu utilization
.75
As of now, the outcomes for the experiments are the listed in the metric column, and their value is in the value column.
I know that I can drop the test specific columns like stream_size, request_size, and response_size, and then bind the rows to make one data frame.
Using R and tidyverse tools, how would you go about combining the two data frames into a long format, so that the combined data frame does not have the test specific columns, stream_size, request_size, and response_size?
Is there a better or more succinct way to make the schema for these experiments' data to facilitate combining the data frames?
You could bind the 2 dataframes together, then pivot just the columns that end with size to long form.
library(tidyverse)
bind_rows(stream, rr) %>%
pivot_longer(ends_with("size"), names_to = "test_specific", values_to = "size", values_drop_na = TRUE)
Output
experiment protocol test metric value test_specific size
<int> <chr> <chr> <chr> <dbl> <chr> <int>
1 1 tcp stream throughput Gbps 10 stream_size 64
2 1 tcp stream cpu utilization 0.5 stream_size 64
3 2 tcp stream throughput Gbps 40 stream_size 64
4 2 tcp stream cpu utilization 0.9 stream_size 64
5 3 udp stream throughput Gbps 20 stream_size 64
6 3 udp stream cpu utilization 0.5 stream_size 64
7 4 udp stream throughput Gbps 60 stream_size 64
8 4 udp stream cpu utilization 0.8 stream_size 64
9 5 tcp request and response transactions per second 10 request_size 64
10 5 tcp request and response transactions per second 10 response_size 64
# … with 14 more rows

Decoding Thrift Object what are these extra bytes?

I'm working on writing a pure JS thrift decoder that doesn't depend on thrift definitions. I have been following this handy guide which has been my bible for the past few days: https://erikvanoosten.github.io/thrift-missing-specification/
I almost have my parser working, but there is a string type that throws a wrench into the program, and I don't quite understand what it's doing. Here is an excerpt of the hexdump, which I did my best to annotate:
Correctly parsing:
000001a0 0a 32 30 32 31 2d 31 31 2d 32 34 16 02 00 18 07 |.2021-11-24.....|
........................blah blah blah............| | |
Object End-| | |
0x18 & 0xF = 0x8 = Binary-| |
The binary sequence is 0x7 characters long-|
000001b0 53 65 61 74 74 6c 65 18 02 55 53 18 02 55 53 18 |Seattle..US..US.|
S E A T T L E |___| U S |___| U S
Another string, 2 bytes long |------------|
So far so good.
But then I get to this point:
There string I am trying to extract is "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4592.0 Safari/537.36 Edg/94.0.975.1" and is 134 bytes long.
000001c0 09 54 61 68 6f 65 2c 20 43 41 12 12 00 00 08 c8 |.Tahoe, CA......|
Object ends here-| | |
0x8 & 0xF = 0x8 = Binary -| |
0xc8 bytes long (200)-|
000001d0 01 86 01 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 |...Mozilla/5.0 (|
| | | M o z i l l a
???? |--|-134, encoded as var-int
000001e0 4d 61 63 69 6e 74 6f 73 68 3b 20 49 6e 74 65 6c |Macintosh; Intel|
As you can see, I have a byte sequence 0x08 0xC8 0x01 0x86 0x01 which contains the length of the string I'm looking for, is followed by the string I'm looking for but has 3 extra bytes that are unclear in purpose.
The 0x01 is especially confusing as it neither a type identifier, nor seems to have a concrete value.
What am I missing?
Thrift supports pluggable serialization schemes. In tree you have binary, compact and json. Out of tree anything goes. From the looks of it you are trying to decode compact protocol, so I'll answer accordingly.
Everything sent and everything returned in a Thrift RPC call is packaged in a struct. Every field in a struct has a 1 byte type and a 2 byte field ID prefix. In compact protocol field ids, when possible, are delta encoded into the type and all ints are compressed down to just the bits needed to store them (and some flags). Because ints can now take up varying numbers of bytes we need to know when they end. Compact protocol encodes the int bits in 7 bits of a byte and sets the high order bit to 1 if the next byte continues the int. If the high order bit is 0 the int is complete. Thus the int 5 (101) would be encoded in one byte as 0000101. Compact knows this is the end of the int because the high order bit is 0.
In your case, the int 134 (binary 10000110) will need 2 bytes to encode because it is more than 7 bits. The fist 7 bits are stored in byte 1 with the 0x80 bit set to flag "the int continues". The second and final byte encodes the last bit (00000001). What you thought was 134 was just the encoding of the first seven bits. The stray 1 was the final bit of the 134.
I'd recommend you use the in tree source to do any needed protocol encoding/decoding. It's already written and tested: https://github.com/apache/thrift/blob/master/lib/nodejs/lib/thrift/compact_protocol.js
The byte sequence reads as follows
0x08: String type, the next 2 bytes define the elementId
0xC8 0x01: ElementId, encoded in 16 bits
0x86 0x01: String length, encoded as var int
It turns out that if the type identifier does not contain bits defining the elementId, the elementId will be stored in the next 2 bytes.

TCPDF - Problem with Alphanumerical characters (wrong size)

I have a size problem when using TCPDF to generate QR code with only ALPHANUMERICAL characters. My objective: generate the longest URL (with a random part), but keeping the QR code at its lowest size, i.e. 21x21 modules (version1).
Documentation (QRcode.com) reports that using only alphanumerical characters set (thonky.com), URL can be 25 characters long with ERC set to L.
Using write2DBarCode with this 25 Alphanumerical URL leads to version1 (21x21mod) QR as expected
$pdf->write2DBarcode('HTTP://SITE-COM/123456789', 'QRCODE,L', 20, 20, 40, 40, $style, 'N');
but changing to this other URL, with also 25 Alphanumerical, I get a version 2 (25x25mod) QR code, whereas a version 1 could be done (Tested on Nayuki)
$pdf->write2DBarcode('HTTP://TXT-CH/AYAWEQYAF4A', 'QRCODE,L', 20, 70, 40, 40, $style, 'N');
I join the TCPDF Outputs of the 2 QR codes given as examples TCPDF Outputs
Thank you in advance for your help on this wonderful TCPDF library.
Short answer: The TCPDF software that you are using is suboptimal. It is generating a full 4-bit terminator even when a shorter one suffices. Please contact the software's authors to fix the problem. You can link them to this thread.
So I cropped your image into two QR Code images, and submitted them to ZXing Decoder Online and KaarPoSoft QR Decode with debug output.
ZXing, first barcode:
Decode Succeeded
Raw text HTTP://SITE-COM/123456789
Raw bytes 20 83 1a a6 5f 9f d5 b4 75 3e 8d 20 48 81 23 db 91 8a 80
Barcode format QR_CODE
Parsed Result Type URI
Parsed Result HTTP://SITE-COM/123456789
ZXing, second barcode:
Decode Succeeded
Raw text HTTP://TXT-CH/AYAWEQYAF4A
Raw bytes 20 cb 1a a6 5f 9f d6 5e ae 82 ca 0f 21 e2 52 18 11 53 94 00 ec 11 ec 11 ec 11 ec 11 ec 11 ec 11 ec 11
Barcode format QR_CODE
Parsed Result Type URI
Parsed Result HTTP://TXT-CH/AYAWEQYAF4A
KaarPoSoft, first barcode:
Debug output
skew_limit=7.21875
skew=0
left=31 right=427 top=27 bottom=423
size=397
matchVersion version=1 finder0=64 finder1=64 finder2=64
matchVersion version=1 timing0=1 timing1=1 alignment=1
matchVersion version=1 format_NW =14 0 format_NESW =14 1 format = 14 ecl = 1 mask = 6
matchVersion version=1 grades(F(V)TAF): 4444->4
findModuleSize matchVersion version=1 grade=4
findModuleSize version=1 grade=4 error_correction_level=1 mask=6
getCodewords mask=6 length=26
getCodewords = 32,131,26,166,95,159,213,180,117,62,141,32,72,129,35,219,145,138,128,62,191,105,157,147,176,164
setBlocks n_blocks_first=1 n_blocks_second=0 n_blocks=1 n_block_words_first=19 n_block_words_second=0 n_block_ec_words=7 total=26
setBlocks block 0 (26): 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25
RS calculateSyndroms: No errors
correctErrors in = 32,131,26,166,95,159,213,180,117,62,141,32,72,129,35,219,145,138,128,62,191,105,157,147,176,164
correctErrors out = 32,131,26,166,95,159,213,180,117,62,141,32,72,129,35,219,145,138,128
error_grade=4
extractData bytes in (19) = 32,131,26,166,95,159,213,180,117,62,141,32,72,129,35,219,145,138,128
extractData mode = 2
extractAlphanum charcount = 16
extractData mode = 1
extractNumeric charcount = 9
extractData mode = 0
extractData data(25) = 72,84,84,80,58,47,47,83,73,84,69,45,67,79,77,47,49,50,51,52,53,54,55,56,57
KaarPoSoft, second barcode:
Debug output
skew_limit=7.015625
skew=1
left=21 right=417 top=30 bottom=425
size=396.5
findModuleSize matchVersion version=1 grade=0
matchVersion version=2 finder0=64 finder1=64 finder2=64
matchVersion version=2 timing0=1 timing1=1 alignment=1
matchVersion version=2 format_NW =14 0 format_NESW =14 1 format = 14 ecl = 1 mask = 6
matchVersion version=2 grades(F(V)TAF): 4444->4
findModuleSize matchVersion version=2 grade=4
findModuleSize version=2 grade=4 error_correction_level=1 mask=6
getCodewords mask=6 length=44
getCodewords = 32,203,26,166,95,159,214,94,174,130,202,15,33,226,82,24,17,83,148,0,236,17,236,17,236,17,236,17,236,17,236,17,236,17,87,194,99,197,7,184,131,204,163,52
setBlocks n_blocks_first=1 n_blocks_second=0 n_blocks=1 n_block_words_first=34 n_block_words_second=0 n_block_ec_words=10 total=44
setBlocks block 0 (44): 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43
RS calculateSyndroms: No errors
correctErrors in = 32,203,26,166,95,159,214,94,174,130,202,15,33,226,82,24,17,83,148,0,236,17,236,17,236,17,236,17,236,17,236,17,236,17,87,194,99,197,7,184,131,204,163,52
correctErrors out = 32,203,26,166,95,159,214,94,174,130,202,15,33,226,82,24,17,83,148,0,236,17,236,17,236,17,236,17,236,17,236,17,236,17
error_grade=4
extractData bytes in (34) = 32,203,26,166,95,159,214,94,174,130,202,15,33,226,82,24,17,83,148,0,236,17,236,17,236,17,236,17,236,17,236,17,236,17
extractData mode = 2
extractAlphanum charcount = 25
extractData mode = 0
extractData data(25) = 72,84,84,80,58,47,47,84,88,84,45,67,72,47,65,89,65,87,69,81,89,65,70,52,65
Both QR Codes appear to have no problems regarding error correction or format violations.
From the KaarPoSoft output, we can see the segments in the QR Codes.
The first barcode has two segments:
Alphanumeric mode, count = 16, text = "HTTP://SITE-COM/". Segment bit length = 4 (mode) + 9 (count) + 88 (data) = 101 bits.
Numeric mode, count = 9, text = "123456789". Segment bit length = 4 (mode) + 10 (count) + 30 (data) = 44 bits.
The second barcode has one segment:
Alphanumeric mode, count = 25, text = "HTTP://TXT-CH/AYAWEQYAF4A". Segment bit length = 4 (mode) + 9 (count) + 138 (data) = 151 bits.
Now, a QR Code at version 1 with low error correction level has capacity for 19 data codeword bytes, or 152 bits. The first barcode uses 101 + 44 = 145 bits = 19 bytes (rounded up), so it fits. The second barcode uses 151 bits = 19 bytes (rounded up), so it fits. So in theory, both lists of segments of text data should fit in version 1 low ECC.
According to the QR spec, after the list of segments ends, these bits are appended:
(TERM) Up to four "0" bits (but less if the data capacity is reached) for the terminator pseudo-mode.
(BITPAD) Zero to seven "0" bits to fill up the last partial byte.
(BYTEPAD) Alternating bytes of 0xEC and 0x11 until the data capacity is reached.
Let's dissect what actually happened. Convert the ZXing hexadecimal byte output to binary, and annotate the fields.
First barcode:
20 83 1a a6 5f 9f d5 b4 75 3e 8d 20 48 81 23 db 91 8a 80
0010 000010000 [88 bits] 0001 0000001001 [30 bits] 0000 000 (Total length = 152 bits)
^Mode ^Count ^Data ^Mode ^Count ^Data ^TERM ^BITPAD
Second barcode:
20 cb 1a a6 5f 9f d6 5e ae 82 ca 0f 21 e2 52 18 11 53 94 00 ec 11 ec 11 ec 11 ec 11 ec 11 ec 11 ec 11
0010 000011001 [138 bits] | 0000 00000 11101100 00010001 [...] (Total length = 272 bits)
^Mode ^Count ^Data | ^TERM ^BITPAD ^BYTEPAD
Note that in the second barcode, at the position | just before the TERMinator, there are 151 bits on the left side. The terminator is normally four "0" bits, but is allowed to be shortened if the capacity (of 152 bits) is reached. So the optimal terminator is a single bit of "0", and then there must be no bit padding and no byte padding.

How does wildcard mask really work?

I'm studying for my cisco CCENT and I'm having a real hard time understanding wildcard masking this video was pretty straight forward and simple:
Wildcard Mask Video
However when applied to this question it yields the wrong answer:
You need to create a wildcard mask for the entire Class B private IPv4 address space
172.16.0.0/16 through 172.31.0.0/16. What is the wildcard mask?
One is tempted based upon the video to answer 0.0.255.255 however this is the incorrect answer with the correct answer being 0.15.255.255???
No matter how much I tinker with the bits to try and make sense of it I feel I am missing something can someone explain?
It occurs to me they could be super strict and only want the wildcard mask for the given range but in which case I would answer 2^5 for 32 = 255.248.0.0 = WCM 0.7.255.255 but alas this was not the answer either not even close what am I missing?
Here is another similar question...
Which address and wildcard mask combination will match all IPv4 addresses in the networks
192.168.0.0/24 through 192.168.63.0/24?
What I wanted to say: 192.168.0.0 0.0.0.255
Answer: 192.168.0.0 0.0.63.255
Create an IP Slide Rule with the mask on the first row and the bit values on the second row.
Mask 128 192 224 240 248 252 254 255
128 64 32 16 8 4 2 1
Now you need to convert the IP address to binary
I hope my paste doesn't go funky. Here are the examples
Mask 128 192 224 240 248 252 254 255
128 64 32 16 8 4 2 1
192.168.0 0 0 0 0 0 0 0.00000000
192.168.0 0 1 1 1 1 1 1.00000000 x.x=192.168 since they are the same
Now you need to find from the IP slide rule the last bit where they are identical.
In this case it is the 64 and the mask for 64 is 192. Now you will subtract the new mask from 255
255 255 255 255
255 255 192 0 =
0. 0. 63.255 Wildcard mask is 0.0.63.255 answer is 192.168.0.0 0.0.63.255
You need to create a wildcard mask for the entire Class B private IPv4 address space
172.16.0.0/16 through 172.31.0.0/16. What is the wildcard mask?
Answer 0.15.255.255
Mask 128 192 224 240 248 252 254 255
128 64 32 16 8 4 2 1
172. 0 0 0 1 0 0 0 0 0.0
172. 0 0 0 1 1 1 1 1 0.0
Now you need to find in the ip slide rule the last bit where they are identical.
In this case it is the 16 and the mask for 16 is 240. Now you will subtract the new mask from 255
255 255 255 255
255 240 0 0
0. 15.255.255 Wildcard mask is 0.15.255.255 answer is 172.0.0.0 0.15.255.255
Results of the wildcard mask calculation provide the first IP address and last IP address in the wildcard mask network range.
If it was only 192.168.0.0 /24 your output would be 0.0.0.255 but your question is combination of 192.168.0.0/24 through 192.168.63.0/24 so you must calculate it.

Calculate size and start of TCP packet data (excluding header)

How would I go about calculating the size and starting byte of the data in a TCP packet (excluding the header information)?
I am going to assume that you are dealing with a TCP/IP packet. You will need to calculate this size yourself.
The IP header has a 'Total Length' field that gives you the length of the entire IP packet in bytes. If you subtract the number of 32-bit words that make up the header (given by the Header Length field in the IP header) you will know the size of the TCP packet. Usually, the header is 20 bytes for the IP packet, unless Options are present.
In the TCP header, the Data Offset field specifies the size of the TCP header in 32-bit words. Again, you can subtract the number (multiplied with 4 to give you the number of bytes in the header) from the size of the TCP packet you calculated earlier to get you the size of the data in the TCP packet.
Given the Header Length in the IP header and the Data Offset in the TCP header, you can add those two and multiply by 4 to give you the byte offset till the data in the TCP packet starts.
I just captured a TCP packet on my router, then I calculated the TCP data length.
IHL = 5
Total Length = 0x00a8
Data Offset = 8
---------------------
0x00a8 - (5 + 8) * 4 = 116 bytes
# tcpdump -n -i br-lan -c 1 -e -XX tcp port 22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-lan, link-type EN10MB (Ethernet), capture size 65535 bytes
15:33:53.917593 ae:ca:87:aa:aa:aa > b8:e8:56:bb:bb:bb, ethertype IPv4 (0x0800), length 182: 192.168.31.1.22 > 192.168.31.102.54076: Flags [P.], seq 582717816:582717932, ack 442380252, win 4706, options [nop,nop,TS val 100656432 ecr 1139948861], length 116
0x0000: b8e8 56bb bbbb aeca 87aa aaaa 0800 4510 ..V........x..E.
^
0x0010: 00a8 8d0c 4000 4006 ed7b c0a8 1f01 c0a8 ....#.#..{......
^^^^
0x0020: 1f66 0016 d33c 22bb 9178 1a5e 2fdc 8018 .f...<"..x.^/...
^
0x0030: 1262 c052 0000 0101 080a 05ff e530 43f2 .b.R.........0C.
0x0040: 3d3d f6e4 f672 736f 6c6c 191f 64ec 80a6 ==...rsoll..d...
0x0050: ba74 e8f7 b2ce 99ec 2725 2d49 f4f6 7760 .t......'%-I..w`
0x0060: c83f 5130 83bb ca22 c32c 6251 7381 08e2 .?Q0...".,bQs...
0x0070: c036 1c12 f22f fe8b c36a eeff c95c 36fa .6.../...j...\6.
0x0080: 7baa 810b 4c75 8ccf 19e4 62df 2c2c c5fd {...Lu....b.,,..
0x0090: a0c8 aa53 1130 d413 7097 f1cd 34dc 92b7 ...S.0..p...4...
0x00a0: ea9b 3bd6 02f8 ea93 c8f3 7d32 4a58 39aa ..;.......}2JX9.
0x00b0: 12d3 e2bd 18d4 ......
Entire ethernet frame
IP header (IHL / Total Length)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|**IHL**|Type of Service|**********Total Length*********|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding | <-- optional
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DATA ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP header (Data Offset)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |C|E|U|A|P|R|S|F| |
| Offset| Res. |W|C|R|C|S|S|Y|I| Window |
| ******| |R|E|G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Resources