* Routine called from ip_output() to loop back a copy of an IP multicast * packet to the input queue of a specified interface. Note that this * calls the output routine of the loopback "driver", but with an interface * pointer that might NOT be a loopback interface -- evil, but easier than * replicating that code here. */
| 1595 | * replicating that code here. |
| 1596 | */ |
| 1597 | static void |
| 1598 | ip_mloopback(struct ifnet *ifp, const struct mbuf *m, int hlen) |
| 1599 | { |
| 1600 | struct ip *ip; |
| 1601 | struct mbuf *copym; |
| 1602 | |
| 1603 | /* |
| 1604 | * Make a deep copy of the packet because we're going to |
| 1605 | * modify the pack in order to generate checksums. |
| 1606 | */ |
| 1607 | copym = m_dup(m, M_NOWAIT); |
| 1608 | if (copym != NULL && (!M_WRITABLE(copym) || copym->m_len < hlen)) |
| 1609 | copym = m_pullup(copym, hlen); |
| 1610 | if (copym != NULL) { |
| 1611 | /* If needed, compute the checksum and mark it as valid. */ |
| 1612 | if (copym->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { |
| 1613 | in_delayed_cksum(copym); |
| 1614 | copym->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; |
| 1615 | copym->m_pkthdr.csum_flags |= |
| 1616 | CSUM_DATA_VALID | CSUM_PSEUDO_HDR; |
| 1617 | copym->m_pkthdr.csum_data = 0xffff; |
| 1618 | } |
| 1619 | /* |
| 1620 | * We don't bother to fragment if the IP length is greater |
| 1621 | * than the interface's MTU. Can this possibly matter? |
| 1622 | */ |
| 1623 | ip = mtod(copym, struct ip *); |
| 1624 | ip->ip_sum = 0; |
| 1625 | ip->ip_sum = in_cksum(copym, hlen); |
| 1626 | if_simloop(ifp, copym, AF_INET, 0); |
| 1627 | } |
| 1628 | } |
no test coverage detected