| 538 | #undef PULLUP_CHECK |
| 539 | |
| 540 | static int |
| 541 | ng_checksum_rcvdata(hook_p hook, item_p item) |
| 542 | { |
| 543 | const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); |
| 544 | struct mbuf *m; |
| 545 | hook_p out; |
| 546 | int error = 0; |
| 547 | |
| 548 | priv->stats.received++; |
| 549 | |
| 550 | NGI_GET_M(item, m); |
| 551 | |
| 552 | #define PULLUP_CHECK(mbuf, length) do { \ |
| 553 | pullup_len += length; \ |
| 554 | if (((mbuf)->m_pkthdr.len < pullup_len) || \ |
| 555 | (pullup_len > MHLEN)) { \ |
| 556 | error = EINVAL; \ |
| 557 | goto bypass; \ |
| 558 | } \ |
| 559 | if ((mbuf)->m_len < pullup_len && \ |
| 560 | (((mbuf) = m_pullup((mbuf), pullup_len)) == NULL)) { \ |
| 561 | error = ENOBUFS; \ |
| 562 | goto drop; \ |
| 563 | } \ |
| 564 | } while (0) |
| 565 | |
| 566 | if (!(priv->conf && hook == priv->in && m && (m->m_flags & M_PKTHDR))) |
| 567 | goto bypass; |
| 568 | |
| 569 | m->m_pkthdr.csum_flags |= priv->conf->csum_flags; |
| 570 | |
| 571 | if (m->m_pkthdr.csum_flags & (NG_CHECKSUM_CSUM_IPV4|NG_CHECKSUM_CSUM_IPV6)) |
| 572 | { |
| 573 | struct ether_header *eh; |
| 574 | struct ng_checksum_vlan_header *vh; |
| 575 | int pullup_len = 0; |
| 576 | uint16_t etype; |
| 577 | |
| 578 | m = m_unshare(m, M_NOWAIT); |
| 579 | |
| 580 | if (m == NULL) |
| 581 | ERROUT(ENOMEM); |
| 582 | |
| 583 | switch (priv->dlt) |
| 584 | { |
| 585 | case DLT_EN10MB: |
| 586 | PULLUP_CHECK(m, sizeof(struct ether_header)); |
| 587 | eh = mtod(m, struct ether_header *); |
| 588 | etype = ntohs(eh->ether_type); |
| 589 | |
| 590 | for (;;) { /* QinQ support */ |
| 591 | switch (etype) |
| 592 | { |
| 593 | case 0x8100: |
| 594 | case 0x88A8: |
| 595 | case 0x9100: |
| 596 | PULLUP_CHECK(m, sizeof(struct ng_checksum_vlan_header)); |
| 597 | vh = (struct ng_checksum_vlan_header *) mtodo(m, |
nothing calls this directly
no test coverage detected