| | 457 | /** |
|---|
| | 458 | * Calculates the checksum for the TCP header given the IP header, |
|---|
| | 459 | * TCP header and payload. |
|---|
| | 460 | * |
|---|
| | 461 | * @returns The checksum (network endian). |
|---|
| | 462 | * @param pIpHdr Pointer to the IPv4 header, in network endian (big). |
|---|
| | 463 | * @param pTcpHdr Pointer to the TCP header, in network endian (big). |
|---|
| | 464 | * @param pvData Pointer to the TCP payload. The size is taken from the |
|---|
| | 465 | * TCP header and the caller is supposed to have validated |
|---|
| | 466 | * this before calling. |
|---|
| | 467 | * If NULL then we assume the data follows immediately after |
|---|
| | 468 | * the TCP header. |
|---|
| | 469 | */ |
|---|
| | 470 | RTDECL(uint16_t) RTNetIPv4TCPChecksum(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, void const *pvData) |
|---|
| | 471 | { |
|---|
| | 472 | uint32_t u32Sum = rtNetIPv4PseudoChecksum(pIpHdr); |
|---|
| | 473 | u32Sum = rtNetIPv4AddTCPChecksum(pTcpHdr, u32Sum); |
|---|
| | 474 | bool fOdd = false; |
|---|
| | 475 | size_t cbData = RT_BE2H_U16(pIpHdr->ip_len) - pIpHdr->ip_hl * 4 - pTcpHdr->th_off * 4; |
|---|
| | 476 | u32Sum = rtNetIPv4AddDataChecksum(pvData ? pvData : (uint8_t const *)pTcpHdr + pTcpHdr->th_off * 4, |
|---|
| | 477 | cbData, u32Sum, &fOdd); |
|---|
| | 478 | return rtNetIPv4FinalizeChecksum(u32Sum); |
|---|
| | 479 | } |
|---|
| | 480 | |
|---|
| | 481 | |
|---|
| | 482 | /** |
|---|
| | 483 | * Verficiation of a TCP header. |
|---|
| | 484 | * |
|---|
| | 485 | * @returns true if valid, false if invalid. |
|---|
| | 486 | * @param pIpHdr Pointer to the IPv4 header, in network endian (big). |
|---|
| | 487 | * This is assumed to be valid and the minimum size being mapped. |
|---|
| | 488 | * @param pTcpHdr Pointer to the TCP header, in network endian (big). |
|---|
| | 489 | * @param cbHdrMax The max TCP header size (what pTcpHdr points to). |
|---|
| | 490 | * @param cbPktMax The max TCP packet size, TCP header and payload (data). |
|---|
| | 491 | */ |
|---|
| | 492 | DECLINLINE(bool) rtNetIPv4IsTCPSizeValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, size_t cbPktMax) |
|---|
| | 493 | { |
|---|
| | 494 | Assert(cbPktMax >= cbHdrMax); |
|---|
| | 495 | |
|---|
| | 496 | /* |
|---|
| | 497 | * Size validations. |
|---|
| | 498 | */ |
|---|
| | 499 | if (RT_UNLIKELY(cbPktMax < RTNETTCP_MIN_LEN)) |
|---|
| | 500 | return false; |
|---|
| | 501 | size_t cbTcpHdr = pTcpHdr->th_off * 4; |
|---|
| | 502 | if (RT_UNLIKELY(cbTcpHdr > cbHdrMax)) |
|---|
| | 503 | return false; |
|---|
| | 504 | size_t cbTcp = RT_BE2H_U16(pIpHdr->ip_len) - pIpHdr->ip_hl * 4; |
|---|
| | 505 | if (RT_UNLIKELY(cbTcp > cbPktMax)) |
|---|
| | 506 | return false; |
|---|
| | 507 | return true; |
|---|
| | 508 | } |
|---|
| | 509 | |
|---|
| | 510 | |
|---|
| | 511 | /** |
|---|
| | 512 | * Simple verficiation of an TCP packet size. |
|---|
| | 513 | * |
|---|
| | 514 | * @returns true if valid, false if invalid. |
|---|
| | 515 | * @param pIpHdr Pointer to the IPv4 header, in network endian (big). |
|---|
| | 516 | * This is assumed to be valid and the minimum size being mapped. |
|---|
| | 517 | * @param pTcpHdr Pointer to the TCP header, in network endian (big). |
|---|
| | 518 | * @param cbHdrMax The max TCP header size (what pTcpHdr points to). |
|---|
| | 519 | * @param cbPktMax The max TCP packet size, TCP header and payload (data). |
|---|
| | 520 | */ |
|---|
| | 521 | RTDECL(bool) RTNetIPv4IsTCPSizeValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, size_t cbPktMax) |
|---|
| | 522 | { |
|---|
| | 523 | return rtNetIPv4IsTCPSizeValid(pIpHdr, pTcpHdr, cbHdrMax, cbPktMax); |
|---|
| | 524 | } |
|---|
| | 525 | |
|---|
| | 526 | |
|---|
| | 527 | /** |
|---|
| | 528 | * Simple verficiation of an TCP packet (size + checksum). |
|---|
| | 529 | * |
|---|
| | 530 | * @returns true if valid, false if invalid. |
|---|
| | 531 | * @param pIpHdr Pointer to the IPv4 header, in network endian (big). |
|---|
| | 532 | * This is assumed to be valid and the minimum size being mapped. |
|---|
| | 533 | * @param pTcpHdr Pointer to the TCP header, in network endian (big). |
|---|
| | 534 | * @param cbHdrMax The max TCP header size (what pTcpHdr points to). |
|---|
| | 535 | * @param pvData Pointer to the data, assuming it's one single segment |
|---|
| | 536 | * and that cbPktMax - sizeof(RTNETTCP) is mapped here. |
|---|
| | 537 | * If NULL then we assume the data follows immediately after |
|---|
| | 538 | * the TCP header. |
|---|
| | 539 | * @param cbPktMax The max TCP packet size, TCP header and payload (data). |
|---|
| | 540 | */ |
|---|
| | 541 | RTDECL(bool) RTNetIPv4IsTCPValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, void const *pvData, size_t cbPktMax) |
|---|
| | 542 | { |
|---|
| | 543 | if (RT_UNLIKELY(!rtNetIPv4IsTCPSizeValid(pIpHdr, pTcpHdr, cbHdrMax, cbPktMax))) |
|---|
| | 544 | return false; |
|---|
| | 545 | uint16_t u16Sum = RTNetIPv4TCPChecksum(pIpHdr, pTcpHdr, pvData); |
|---|
| | 546 | if (RT_UNLIKELY(pTcpHdr->th_sum != u16Sum)) |
|---|
| | 547 | return false; |
|---|
| | 548 | return true; |
|---|
| | 549 | } |
|---|
| | 550 | |
|---|