|
16 | 16 | */
|
17 | 17 |
|
18 | 18 | #include "qemu/osdep.h"
|
| 19 | +#include "qemu/crc32c.h" |
19 | 20 | #include "trace.h"
|
20 | 21 | #include "net_rx_pkt.h"
|
21 | 22 | #include "net/checksum.h"
|
@@ -554,32 +555,73 @@ _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt)
|
554 | 555 | return csum;
|
555 | 556 | }
|
556 | 557 |
|
557 |
| -bool net_rx_pkt_validate_l4_csum(struct NetRxPkt *pkt, bool *csum_valid) |
| 558 | +static bool |
| 559 | +_net_rx_pkt_validate_sctp_sum(struct NetRxPkt *pkt) |
558 | 560 | {
|
559 |
| - uint16_t csum; |
| 561 | + size_t csum_off; |
| 562 | + size_t off = pkt->l4hdr_off; |
| 563 | + size_t vec_len = pkt->vec_len; |
| 564 | + struct iovec *vec; |
| 565 | + uint32_t calculated = 0; |
| 566 | + uint32_t original; |
| 567 | + bool valid; |
560 | 568 |
|
561 |
| - trace_net_rx_pkt_l4_csum_validate_entry(); |
| 569 | + for (vec = pkt->vec; vec->iov_len < off; vec++) { |
| 570 | + off -= vec->iov_len; |
| 571 | + vec_len--; |
| 572 | + } |
562 | 573 |
|
563 |
| - if (pkt->l4hdr_info.proto != ETH_L4_HDR_PROTO_TCP && |
564 |
| - pkt->l4hdr_info.proto != ETH_L4_HDR_PROTO_UDP) { |
565 |
| - trace_net_rx_pkt_l4_csum_validate_not_xxp(); |
| 574 | + csum_off = off + 8; |
| 575 | + |
| 576 | + if (!iov_to_buf(vec, vec_len, csum_off, &original, sizeof(original))) { |
566 | 577 | return false;
|
567 | 578 | }
|
568 | 579 |
|
569 |
| - if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP && |
570 |
| - pkt->l4hdr_info.hdr.udp.uh_sum == 0) { |
571 |
| - trace_net_rx_pkt_l4_csum_validate_udp_with_no_checksum(); |
| 580 | + if (!iov_from_buf(vec, vec_len, csum_off, |
| 581 | + &calculated, sizeof(calculated))) { |
572 | 582 | return false;
|
573 | 583 | }
|
574 | 584 |
|
| 585 | + calculated = crc32c(0xffffffff, |
| 586 | + (uint8_t *)vec->iov_base + off, vec->iov_len - off); |
| 587 | + calculated = iov_crc32c(calculated ^ 0xffffffff, vec + 1, vec_len - 1); |
| 588 | + valid = calculated == le32_to_cpu(original); |
| 589 | + iov_from_buf(vec, vec_len, csum_off, &original, sizeof(original)); |
| 590 | + |
| 591 | + return valid; |
| 592 | +} |
| 593 | + |
| 594 | +bool net_rx_pkt_validate_l4_csum(struct NetRxPkt *pkt, bool *csum_valid) |
| 595 | +{ |
| 596 | + uint32_t csum; |
| 597 | + |
| 598 | + trace_net_rx_pkt_l4_csum_validate_entry(); |
| 599 | + |
575 | 600 | if (pkt->hasip4 && pkt->ip4hdr_info.fragment) {
|
576 | 601 | trace_net_rx_pkt_l4_csum_validate_ip4_fragment();
|
577 | 602 | return false;
|
578 | 603 | }
|
579 | 604 |
|
580 |
| - csum = _net_rx_pkt_calc_l4_csum(pkt); |
| 605 | + switch (pkt->l4hdr_info.proto) { |
| 606 | + case ETH_L4_HDR_PROTO_UDP: |
| 607 | + if (pkt->l4hdr_info.hdr.udp.uh_sum == 0) { |
| 608 | + trace_net_rx_pkt_l4_csum_validate_udp_with_no_checksum(); |
| 609 | + return false; |
| 610 | + } |
| 611 | + /* fall through */ |
| 612 | + case ETH_L4_HDR_PROTO_TCP: |
| 613 | + csum = _net_rx_pkt_calc_l4_csum(pkt); |
| 614 | + *csum_valid = ((csum == 0) || (csum == 0xFFFF)); |
| 615 | + break; |
| 616 | + |
| 617 | + case ETH_L4_HDR_PROTO_SCTP: |
| 618 | + *csum_valid = _net_rx_pkt_validate_sctp_sum(pkt); |
| 619 | + break; |
581 | 620 |
|
582 |
| - *csum_valid = ((csum == 0) || (csum == 0xFFFF)); |
| 621 | + default: |
| 622 | + trace_net_rx_pkt_l4_csum_validate_not_xxp(); |
| 623 | + return false; |
| 624 | + } |
583 | 625 |
|
584 | 626 | trace_net_rx_pkt_l4_csum_validate_csum(*csum_valid);
|
585 | 627 |
|
|
0 commit comments