inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/tcpip/header/tcp.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 header 16 17 import ( 18 "encoding/binary" 19 20 "github.com/google/btree" 21 "inet.af/netstack/tcpip" 22 "inet.af/netstack/tcpip/seqnum" 23 ) 24 25 // These constants are the offsets of the respective fields in the TCP header. 26 const ( 27 TCPSrcPortOffset = 0 28 TCPDstPortOffset = 2 29 TCPSeqNumOffset = 4 30 TCPAckNumOffset = 8 31 TCPDataOffset = 12 32 TCPFlagsOffset = 13 33 TCPWinSizeOffset = 14 34 TCPChecksumOffset = 16 35 TCPUrgentPtrOffset = 18 36 ) 37 38 const ( 39 // MaxWndScale is maximum allowed window scaling, as described in 40 // RFC 1323, section 2.3, page 11. 41 MaxWndScale = 14 42 43 // TCPMaxSACKBlocks is the maximum number of SACK blocks that can 44 // be encoded in a TCP option field. 45 TCPMaxSACKBlocks = 4 46 ) 47 48 // TCPFlags is the dedicated type for TCP flags. 49 type TCPFlags uint8 50 51 // Intersects returns true iff there are flags common to both f and o. 52 func (f TCPFlags) Intersects(o TCPFlags) bool { 53 return f&o != 0 54 } 55 56 // Contains returns true iff all the flags in o are contained within f. 57 func (f TCPFlags) Contains(o TCPFlags) bool { 58 return f&o == o 59 } 60 61 // String implements Stringer.String. 62 func (f TCPFlags) String() string { 63 flagsStr := []byte("FSRPAU") 64 for i := range flagsStr { 65 if f&(1<<uint(i)) == 0 { 66 flagsStr[i] = ' ' 67 } 68 } 69 return string(flagsStr) 70 } 71 72 // Flags that may be set in a TCP segment. 73 const ( 74 TCPFlagFin TCPFlags = 1 << iota 75 TCPFlagSyn 76 TCPFlagRst 77 TCPFlagPsh 78 TCPFlagAck 79 TCPFlagUrg 80 ) 81 82 // Options that may be present in a TCP segment. 83 const ( 84 TCPOptionEOL = 0 85 TCPOptionNOP = 1 86 TCPOptionMSS = 2 87 TCPOptionWS = 3 88 TCPOptionTS = 8 89 TCPOptionSACKPermitted = 4 90 TCPOptionSACK = 5 91 ) 92 93 // Option Lengths. 94 const ( 95 TCPOptionMSSLength = 4 96 TCPOptionTSLength = 10 97 TCPOptionWSLength = 3 98 TCPOptionSackPermittedLength = 2 99 ) 100 101 // TCPFields contains the fields of a TCP packet. It is used to describe the 102 // fields of a packet that needs to be encoded. 103 type TCPFields struct { 104 // SrcPort is the "source port" field of a TCP packet. 105 SrcPort uint16 106 107 // DstPort is the "destination port" field of a TCP packet. 108 DstPort uint16 109 110 // SeqNum is the "sequence number" field of a TCP packet. 111 SeqNum uint32 112 113 // AckNum is the "acknowledgement number" field of a TCP packet. 114 AckNum uint32 115 116 // DataOffset is the "data offset" field of a TCP packet. It is the length of 117 // the TCP header in bytes. 118 DataOffset uint8 119 120 // Flags is the "flags" field of a TCP packet. 121 Flags TCPFlags 122 123 // WindowSize is the "window size" field of a TCP packet. 124 WindowSize uint16 125 126 // Checksum is the "checksum" field of a TCP packet. 127 Checksum uint16 128 129 // UrgentPointer is the "urgent pointer" field of a TCP packet. 130 UrgentPointer uint16 131 } 132 133 // TCPSynOptions is used to return the parsed TCP Options in a syn 134 // segment. 135 type TCPSynOptions struct { 136 // MSS is the maximum segment size provided by the peer in the SYN. 137 MSS uint16 138 139 // WS is the window scale option provided by the peer in the SYN. 140 // 141 // Set to -1 if no window scale option was provided. 142 WS int 143 144 // TS is true if the timestamp option was provided in the syn/syn-ack. 145 TS bool 146 147 // TSVal is the value of the TSVal field in the timestamp option. 148 TSVal uint32 149 150 // TSEcr is the value of the TSEcr field in the timestamp option. 151 TSEcr uint32 152 153 // SACKPermitted is true if the SACK option was provided in the SYN/SYN-ACK. 154 SACKPermitted bool 155 } 156 157 // SACKBlock represents a single contiguous SACK block. 158 // 159 // +stateify savable 160 type SACKBlock struct { 161 // Start indicates the lowest sequence number in the block. 162 Start seqnum.Value 163 164 // End indicates the sequence number immediately following the last 165 // sequence number of this block. 166 End seqnum.Value 167 } 168 169 // Less returns true if r.Start < b.Start. 170 func (r SACKBlock) Less(b btree.Item) bool { 171 return r.Start.LessThan(b.(SACKBlock).Start) 172 } 173 174 // Contains returns true if b is completely contained in r. 175 func (r SACKBlock) Contains(b SACKBlock) bool { 176 return r.Start.LessThanEq(b.Start) && b.End.LessThanEq(r.End) 177 } 178 179 // TCPOptions are used to parse and cache the TCP segment options for a non 180 // syn/syn-ack segment. 181 // 182 // +stateify savable 183 type TCPOptions struct { 184 // TS is true if the TimeStamp option is enabled. 185 TS bool 186 187 // TSVal is the value in the TSVal field of the segment. 188 TSVal uint32 189 190 // TSEcr is the value in the TSEcr field of the segment. 191 TSEcr uint32 192 193 // SACKBlocks are the SACK blocks specified in the segment. 194 SACKBlocks []SACKBlock 195 } 196 197 // TCP represents a TCP header stored in a byte array. 198 type TCP []byte 199 200 const ( 201 // TCPMinimumSize is the minimum size of a valid TCP packet. 202 TCPMinimumSize = 20 203 204 // TCPOptionsMaximumSize is the maximum size of TCP options. 205 TCPOptionsMaximumSize = 40 206 207 // TCPHeaderMaximumSize is the maximum header size of a TCP packet. 208 TCPHeaderMaximumSize = TCPMinimumSize + TCPOptionsMaximumSize 209 210 // TCPProtocolNumber is TCP's transport protocol number. 211 TCPProtocolNumber tcpip.TransportProtocolNumber = 6 212 213 // TCPMinimumMSS is the minimum acceptable value for MSS. This is the 214 // same as the value TCP_MIN_MSS defined net/tcp.h. 215 TCPMinimumMSS = IPv4MaximumHeaderSize + TCPHeaderMaximumSize + MinIPFragmentPayloadSize - IPv4MinimumSize - TCPMinimumSize 216 217 // TCPMaximumMSS is the maximum acceptable value for MSS. 218 TCPMaximumMSS = 0xffff 219 220 // TCPDefaultMSS is the MSS value that should be used if an MSS option 221 // is not received from the peer. It's also the value returned by 222 // TCP_MAXSEG option for a socket in an unconnected state. 223 // 224 // Per RFC 1122, page 85: "If an MSS option is not received at 225 // connection setup, TCP MUST assume a default send MSS of 536." 226 TCPDefaultMSS = 536 227 ) 228 229 // SourcePort returns the "source port" field of the TCP header. 230 func (b TCP) SourcePort() uint16 { 231 return binary.BigEndian.Uint16(b[TCPSrcPortOffset:]) 232 } 233 234 // DestinationPort returns the "destination port" field of the TCP header. 235 func (b TCP) DestinationPort() uint16 { 236 return binary.BigEndian.Uint16(b[TCPDstPortOffset:]) 237 } 238 239 // SequenceNumber returns the "sequence number" field of the TCP header. 240 func (b TCP) SequenceNumber() uint32 { 241 return binary.BigEndian.Uint32(b[TCPSeqNumOffset:]) 242 } 243 244 // AckNumber returns the "ack number" field of the TCP header. 245 func (b TCP) AckNumber() uint32 { 246 return binary.BigEndian.Uint32(b[TCPAckNumOffset:]) 247 } 248 249 // DataOffset returns the "data offset" field of the TCP header. The return 250 // value is the length of the TCP header in bytes. 251 func (b TCP) DataOffset() uint8 { 252 return (b[TCPDataOffset] >> 4) * 4 253 } 254 255 // Payload returns the data in the TCP packet. 256 func (b TCP) Payload() []byte { 257 return b[b.DataOffset():] 258 } 259 260 // Flags returns the flags field of the TCP header. 261 func (b TCP) Flags() TCPFlags { 262 return TCPFlags(b[TCPFlagsOffset]) 263 } 264 265 // WindowSize returns the "window size" field of the TCP header. 266 func (b TCP) WindowSize() uint16 { 267 return binary.BigEndian.Uint16(b[TCPWinSizeOffset:]) 268 } 269 270 // Checksum returns the "checksum" field of the TCP header. 271 func (b TCP) Checksum() uint16 { 272 return binary.BigEndian.Uint16(b[TCPChecksumOffset:]) 273 } 274 275 // UrgentPointer returns the "urgent pointer" field of the TCP header. 276 func (b TCP) UrgentPointer() uint16 { 277 return binary.BigEndian.Uint16(b[TCPUrgentPtrOffset:]) 278 } 279 280 // SetSourcePort sets the "source port" field of the TCP header. 281 func (b TCP) SetSourcePort(port uint16) { 282 binary.BigEndian.PutUint16(b[TCPSrcPortOffset:], port) 283 } 284 285 // SetDestinationPort sets the "destination port" field of the TCP header. 286 func (b TCP) SetDestinationPort(port uint16) { 287 binary.BigEndian.PutUint16(b[TCPDstPortOffset:], port) 288 } 289 290 // SetChecksum sets the checksum field of the TCP header. 291 func (b TCP) SetChecksum(checksum uint16) { 292 binary.BigEndian.PutUint16(b[TCPChecksumOffset:], checksum) 293 } 294 295 // SetDataOffset sets the data offset field of the TCP header. headerLen should 296 // be the length of the TCP header in bytes. 297 func (b TCP) SetDataOffset(headerLen uint8) { 298 b[TCPDataOffset] = (headerLen / 4) << 4 299 } 300 301 // SetSequenceNumber sets the sequence number field of the TCP header. 302 func (b TCP) SetSequenceNumber(seqNum uint32) { 303 binary.BigEndian.PutUint32(b[TCPSeqNumOffset:], seqNum) 304 } 305 306 // SetAckNumber sets the ack number field of the TCP header. 307 func (b TCP) SetAckNumber(ackNum uint32) { 308 binary.BigEndian.PutUint32(b[TCPAckNumOffset:], ackNum) 309 } 310 311 // SetFlags sets the flags field of the TCP header. 312 func (b TCP) SetFlags(flags uint8) { 313 b[TCPFlagsOffset] = flags 314 } 315 316 // SetWindowSize sets the window size field of the TCP header. 317 func (b TCP) SetWindowSize(rcvwnd uint16) { 318 binary.BigEndian.PutUint16(b[TCPWinSizeOffset:], rcvwnd) 319 } 320 321 // SetUrgentPoiner sets the window size field of the TCP header. 322 func (b TCP) SetUrgentPoiner(urgentPointer uint16) { 323 binary.BigEndian.PutUint16(b[TCPUrgentPtrOffset:], urgentPointer) 324 } 325 326 // CalculateChecksum calculates the checksum of the TCP segment. 327 // partialChecksum is the checksum of the network-layer pseudo-header 328 // and the checksum of the segment data. 329 func (b TCP) CalculateChecksum(partialChecksum uint16) uint16 { 330 // Calculate the rest of the checksum. 331 return Checksum(b[:b.DataOffset()], partialChecksum) 332 } 333 334 // IsChecksumValid returns true iff the TCP header's checksum is valid. 335 func (b TCP) IsChecksumValid(src, dst tcpip.Address, payloadChecksum, payloadLength uint16) bool { 336 xsum := PseudoHeaderChecksum(TCPProtocolNumber, src, dst, uint16(b.DataOffset())+payloadLength) 337 xsum = ChecksumCombine(xsum, payloadChecksum) 338 return b.CalculateChecksum(xsum) == 0xffff 339 } 340 341 // Options returns a slice that holds the unparsed TCP options in the segment. 342 func (b TCP) Options() []byte { 343 return b[TCPMinimumSize:b.DataOffset()] 344 } 345 346 // ParsedOptions returns a TCPOptions structure which parses and caches the TCP 347 // option values in the TCP segment. NOTE: Invoking this function repeatedly is 348 // expensive as it reparses the options on each invocation. 349 func (b TCP) ParsedOptions() TCPOptions { 350 return ParseTCPOptions(b.Options()) 351 } 352 353 func (b TCP) encodeSubset(seq, ack uint32, flags TCPFlags, rcvwnd uint16) { 354 binary.BigEndian.PutUint32(b[TCPSeqNumOffset:], seq) 355 binary.BigEndian.PutUint32(b[TCPAckNumOffset:], ack) 356 b[TCPFlagsOffset] = uint8(flags) 357 binary.BigEndian.PutUint16(b[TCPWinSizeOffset:], rcvwnd) 358 } 359 360 // Encode encodes all the fields of the TCP header. 361 func (b TCP) Encode(t *TCPFields) { 362 b.encodeSubset(t.SeqNum, t.AckNum, t.Flags, t.WindowSize) 363 binary.BigEndian.PutUint16(b[TCPSrcPortOffset:], t.SrcPort) 364 binary.BigEndian.PutUint16(b[TCPDstPortOffset:], t.DstPort) 365 b[TCPDataOffset] = (t.DataOffset / 4) << 4 366 binary.BigEndian.PutUint16(b[TCPChecksumOffset:], t.Checksum) 367 binary.BigEndian.PutUint16(b[TCPUrgentPtrOffset:], t.UrgentPointer) 368 } 369 370 // EncodePartial updates a subset of the fields of the TCP header. It is useful 371 // in cases when similar segments are produced. 372 func (b TCP) EncodePartial(partialChecksum, length uint16, seqnum, acknum uint32, flags TCPFlags, rcvwnd uint16) { 373 // Add the total length and "flags" field contributions to the checksum. 374 // We don't use the flags field directly from the header because it's a 375 // one-byte field with an odd offset, so it would be accounted for 376 // incorrectly by the Checksum routine. 377 tmp := make([]byte, 4) 378 binary.BigEndian.PutUint16(tmp, length) 379 binary.BigEndian.PutUint16(tmp[2:], uint16(flags)) 380 checksum := Checksum(tmp, partialChecksum) 381 382 // Encode the passed-in fields. 383 b.encodeSubset(seqnum, acknum, flags, rcvwnd) 384 385 // Add the contributions of the passed-in fields to the checksum. 386 checksum = Checksum(b[TCPSeqNumOffset:TCPSeqNumOffset+8], checksum) 387 checksum = Checksum(b[TCPWinSizeOffset:TCPWinSizeOffset+2], checksum) 388 389 // Encode the checksum. 390 b.SetChecksum(^checksum) 391 } 392 393 // SetSourcePortWithChecksumUpdate implements ChecksummableTransport. 394 func (b TCP) SetSourcePortWithChecksumUpdate(new uint16) { 395 old := b.SourcePort() 396 b.SetSourcePort(new) 397 b.SetChecksum(^checksumUpdate2ByteAlignedUint16(^b.Checksum(), old, new)) 398 } 399 400 // SetDestinationPortWithChecksumUpdate implements ChecksummableTransport. 401 func (b TCP) SetDestinationPortWithChecksumUpdate(new uint16) { 402 old := b.DestinationPort() 403 b.SetDestinationPort(new) 404 b.SetChecksum(^checksumUpdate2ByteAlignedUint16(^b.Checksum(), old, new)) 405 } 406 407 // UpdateChecksumPseudoHeaderAddress implements ChecksummableTransport. 408 func (b TCP) UpdateChecksumPseudoHeaderAddress(old, new tcpip.Address, fullChecksum bool) { 409 xsum := b.Checksum() 410 if fullChecksum { 411 xsum = ^xsum 412 } 413 414 xsum = checksumUpdate2ByteAlignedAddress(xsum, old, new) 415 if fullChecksum { 416 xsum = ^xsum 417 } 418 419 b.SetChecksum(xsum) 420 } 421 422 // ParseSynOptions parses the options received in a SYN segment and returns the 423 // relevant ones. opts should point to the option part of the TCP header. 424 func ParseSynOptions(opts []byte, isAck bool) TCPSynOptions { 425 limit := len(opts) 426 427 synOpts := TCPSynOptions{ 428 // Per RFC 1122, page 85: "If an MSS option is not received at 429 // connection setup, TCP MUST assume a default send MSS of 536." 430 MSS: TCPDefaultMSS, 431 // If no window scale option is specified, WS in options is 432 // returned as -1; this is because the absence of the option 433 // indicates that the we cannot use window scaling on the 434 // receive end either. 435 WS: -1, 436 } 437 438 for i := 0; i < limit; { 439 switch opts[i] { 440 case TCPOptionEOL: 441 i = limit 442 case TCPOptionNOP: 443 i++ 444 case TCPOptionMSS: 445 if i+4 > limit || opts[i+1] != 4 { 446 return synOpts 447 } 448 mss := uint16(opts[i+2])<<8 | uint16(opts[i+3]) 449 if mss == 0 { 450 return synOpts 451 } 452 synOpts.MSS = mss 453 i += 4 454 455 case TCPOptionWS: 456 if i+3 > limit || opts[i+1] != 3 { 457 return synOpts 458 } 459 ws := int(opts[i+2]) 460 if ws > MaxWndScale { 461 ws = MaxWndScale 462 } 463 synOpts.WS = ws 464 i += 3 465 466 case TCPOptionTS: 467 if i+10 > limit || opts[i+1] != 10 { 468 return synOpts 469 } 470 synOpts.TSVal = binary.BigEndian.Uint32(opts[i+2:]) 471 if isAck { 472 // If the segment is a SYN-ACK then store the Timestamp Echo Reply 473 // in the segment. 474 synOpts.TSEcr = binary.BigEndian.Uint32(opts[i+6:]) 475 } 476 synOpts.TS = true 477 i += 10 478 case TCPOptionSACKPermitted: 479 if i+2 > limit || opts[i+1] != 2 { 480 return synOpts 481 } 482 synOpts.SACKPermitted = true 483 i += 2 484 485 default: 486 // We don't recognize this option, just skip over it. 487 if i+2 > limit { 488 return synOpts 489 } 490 l := int(opts[i+1]) 491 // If the length is incorrect or if l+i overflows the 492 // total options length then return false. 493 if l < 2 || i+l > limit { 494 return synOpts 495 } 496 i += l 497 } 498 } 499 500 return synOpts 501 } 502 503 // ParseTCPOptions extracts and stores all known options in the provided byte 504 // slice in a TCPOptions structure. 505 func ParseTCPOptions(b []byte) TCPOptions { 506 opts := TCPOptions{} 507 limit := len(b) 508 for i := 0; i < limit; { 509 switch b[i] { 510 case TCPOptionEOL: 511 i = limit 512 case TCPOptionNOP: 513 i++ 514 case TCPOptionTS: 515 if i+10 > limit || (b[i+1] != 10) { 516 return opts 517 } 518 opts.TS = true 519 opts.TSVal = binary.BigEndian.Uint32(b[i+2:]) 520 opts.TSEcr = binary.BigEndian.Uint32(b[i+6:]) 521 i += 10 522 case TCPOptionSACK: 523 if i+2 > limit { 524 // Malformed SACK block, just return and stop parsing. 525 return opts 526 } 527 sackOptionLen := int(b[i+1]) 528 if i+sackOptionLen > limit || (sackOptionLen-2)%8 != 0 { 529 // Malformed SACK block, just return and stop parsing. 530 return opts 531 } 532 numBlocks := (sackOptionLen - 2) / 8 533 opts.SACKBlocks = []SACKBlock{} 534 for j := 0; j < numBlocks; j++ { 535 start := binary.BigEndian.Uint32(b[i+2+j*8:]) 536 end := binary.BigEndian.Uint32(b[i+2+j*8+4:]) 537 opts.SACKBlocks = append(opts.SACKBlocks, SACKBlock{ 538 Start: seqnum.Value(start), 539 End: seqnum.Value(end), 540 }) 541 } 542 i += sackOptionLen 543 default: 544 // We don't recognize this option, just skip over it. 545 if i+2 > limit { 546 return opts 547 } 548 l := int(b[i+1]) 549 // If the length is incorrect or if l+i overflows the 550 // total options length then return false. 551 if l < 2 || i+l > limit { 552 return opts 553 } 554 i += l 555 } 556 } 557 return opts 558 } 559 560 // EncodeMSSOption encodes the MSS TCP option with the provided MSS values in 561 // the supplied buffer. If the provided buffer is not large enough then it just 562 // returns without encoding anything. It returns the number of bytes written to 563 // the provided buffer. 564 func EncodeMSSOption(mss uint32, b []byte) int { 565 if len(b) < TCPOptionMSSLength { 566 return 0 567 } 568 b[0], b[1], b[2], b[3] = TCPOptionMSS, TCPOptionMSSLength, byte(mss>>8), byte(mss) 569 return TCPOptionMSSLength 570 } 571 572 // EncodeWSOption encodes the WS TCP option with the WS value in the 573 // provided buffer. If the provided buffer is not large enough then it just 574 // returns without encoding anything. It returns the number of bytes written to 575 // the provided buffer. 576 func EncodeWSOption(ws int, b []byte) int { 577 if len(b) < TCPOptionWSLength { 578 return 0 579 } 580 b[0], b[1], b[2] = TCPOptionWS, TCPOptionWSLength, uint8(ws) 581 return int(b[1]) 582 } 583 584 // EncodeTSOption encodes the provided tsVal and tsEcr values as a TCP timestamp 585 // option into the provided buffer. If the buffer is smaller than expected it 586 // just returns without encoding anything. It returns the number of bytes 587 // written to the provided buffer. 588 func EncodeTSOption(tsVal, tsEcr uint32, b []byte) int { 589 if len(b) < TCPOptionTSLength { 590 return 0 591 } 592 b[0], b[1] = TCPOptionTS, TCPOptionTSLength 593 binary.BigEndian.PutUint32(b[2:], tsVal) 594 binary.BigEndian.PutUint32(b[6:], tsEcr) 595 return int(b[1]) 596 } 597 598 // EncodeSACKPermittedOption encodes a SACKPermitted option into the provided 599 // buffer. If the buffer is smaller than required it just returns without 600 // encoding anything. It returns the number of bytes written to the provided 601 // buffer. 602 func EncodeSACKPermittedOption(b []byte) int { 603 if len(b) < TCPOptionSackPermittedLength { 604 return 0 605 } 606 607 b[0], b[1] = TCPOptionSACKPermitted, TCPOptionSackPermittedLength 608 return int(b[1]) 609 } 610 611 // EncodeSACKBlocks encodes the provided SACK blocks as a TCP SACK option block 612 // in the provided slice. It tries to fit in as many blocks as possible based on 613 // number of bytes available in the provided buffer. It returns the number of 614 // bytes written to the provided buffer. 615 func EncodeSACKBlocks(sackBlocks []SACKBlock, b []byte) int { 616 if len(sackBlocks) == 0 { 617 return 0 618 } 619 l := len(sackBlocks) 620 if l > TCPMaxSACKBlocks { 621 l = TCPMaxSACKBlocks 622 } 623 if ll := (len(b) - 2) / 8; ll < l { 624 l = ll 625 } 626 if l == 0 { 627 // There is not enough space in the provided buffer to add 628 // any SACK blocks. 629 return 0 630 } 631 b[0] = TCPOptionSACK 632 b[1] = byte(l*8 + 2) 633 for i := 0; i < l; i++ { 634 binary.BigEndian.PutUint32(b[i*8+2:], uint32(sackBlocks[i].Start)) 635 binary.BigEndian.PutUint32(b[i*8+6:], uint32(sackBlocks[i].End)) 636 } 637 return int(b[1]) 638 } 639 640 // EncodeNOP adds an explicit NOP to the option list. 641 func EncodeNOP(b []byte) int { 642 if len(b) == 0 { 643 return 0 644 } 645 b[0] = TCPOptionNOP 646 return 1 647 } 648 649 // AddTCPOptionPadding adds the required number of TCPOptionNOP to quad align 650 // the option buffer. It adds padding bytes after the offset specified and 651 // returns the number of padding bytes added. The passed in options slice 652 // must have space for the padding bytes. 653 func AddTCPOptionPadding(options []byte, offset int) int { 654 paddingToAdd := -offset & 3 655 // Now add any padding bytes that might be required to quad align the 656 // options. 657 for i := offset; i < offset+paddingToAdd; i++ { 658 options[i] = TCPOptionNOP 659 } 660 return paddingToAdd 661 } 662 663 // Acceptable checks if a segment that starts at segSeq and has length segLen is 664 // "acceptable" for arriving in a receive window that starts at rcvNxt and ends 665 // before rcvAcc, according to the table on page 26 and 69 of RFC 793. 666 func Acceptable(segSeq seqnum.Value, segLen seqnum.Size, rcvNxt, rcvAcc seqnum.Value) bool { 667 if rcvNxt == rcvAcc { 668 return segLen == 0 && segSeq == rcvNxt 669 } 670 if segLen == 0 { 671 // rcvWnd is incremented by 1 because that is Linux's behavior despite the 672 // RFC. 673 return segSeq.InRange(rcvNxt, rcvAcc.Add(1)) 674 } 675 // Page 70 of RFC 793 allows packets that can be made "acceptable" by trimming 676 // the payload, so we'll accept any payload that overlaps the receieve window. 677 // segSeq < rcvAcc is more correct according to RFC, however, Linux does it 678 // differently, it uses segSeq <= rcvAcc, we'd want to keep the same behavior 679 // as Linux. 680 return rcvNxt.LessThan(segSeq.Add(segLen)) && segSeq.LessThanEq(rcvAcc) 681 }