|
7 | 7 | #include <tcpip_error_handler.h> |
8 | 8 |
|
9 | 9 | #include "../firewall/firewall.hh" |
| 10 | +#include "checksum-internal.h" |
10 | 11 | #include "network-internal.h" |
11 | 12 | #include "tcpip-internal.h" |
12 | 13 |
|
@@ -472,6 +473,39 @@ namespace |
472 | 473 | } |
473 | 474 | } // namespace |
474 | 475 |
|
| 476 | +uint16_t network_calculate_ipv4_checksum(const uint8_t *ipv4Header, size_t headerLength) |
| 477 | +{ |
| 478 | + // Note: no restarting checks because stateless. |
| 479 | + |
| 480 | + // `usGenerateChecksum` returns a checksum which is 1) not negated (we |
| 481 | + // must bitwise NOT it) and 2) in host byte order. |
| 482 | + return htons(~usGenerateChecksum( |
| 483 | + 0 /* generate checksum for the full packet */, ipv4Header, headerLength)); |
| 484 | +} |
| 485 | + |
| 486 | +uint16_t network_calculate_tcp_checksum(const uint8_t *frame, |
| 487 | + size_t frameLength, |
| 488 | + size_t tcpChecksumOffset) |
| 489 | +{ |
| 490 | + // Note: no restarting checks because stateless. |
| 491 | + |
| 492 | + // `usGenerateProtocolChecksum` *writes* the checksum into the packet |
| 493 | + // buffer. It is not possible to have it return the checksum instead of |
| 494 | + // modifying the buffer. This is really annoying because we only have a |
| 495 | + // read-only capability to the frame, as we want to *return* the |
| 496 | + // checksum. |
| 497 | + // |
| 498 | + // To workaround this, make a local copy of the Ethernet frame and |
| 499 | + // extract the computed checksum from it using `tcpChecksumOffset`. |
| 500 | + // Putting this copy on the stack should be fine since this is only |
| 501 | + // used in RST packets which have no payload. |
| 502 | + uint8_t copy[frameLength]; |
| 503 | + memcpy(copy, frame, frameLength); |
| 504 | + uint16_t *checksum = reinterpret_cast<uint16_t *>(©[tcpChecksumOffset]); |
| 505 | + usGenerateProtocolChecksum(copy, frameLength, true /* write checksum */); |
| 506 | + return *checksum; |
| 507 | +} |
| 508 | + |
475 | 509 | int network_host_resolve(const char *hostname, |
476 | 510 | bool useIPv6, |
477 | 511 | NetworkAddress *address) |
|
0 commit comments