* Routine called from ip6_output() to loop back a copy of an IP6 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 &loif -- easier than replicating that code here. */
| 3287 | * pointer that might NOT be &loif -- easier than replicating that code here. |
| 3288 | */ |
| 3289 | void |
| 3290 | ip6_mloopback(struct ifnet *ifp, struct mbuf *m) |
| 3291 | { |
| 3292 | struct mbuf *copym; |
| 3293 | struct ip6_hdr *ip6; |
| 3294 | |
| 3295 | copym = m_copym(m, 0, M_COPYALL, M_NOWAIT); |
| 3296 | if (copym == NULL) |
| 3297 | return; |
| 3298 | |
| 3299 | /* |
| 3300 | * Make sure to deep-copy IPv6 header portion in case the data |
| 3301 | * is in an mbuf cluster, so that we can safely override the IPv6 |
| 3302 | * header portion later. |
| 3303 | */ |
| 3304 | if (!M_WRITABLE(copym) || |
| 3305 | copym->m_len < sizeof(struct ip6_hdr)) { |
| 3306 | copym = m_pullup(copym, sizeof(struct ip6_hdr)); |
| 3307 | if (copym == NULL) |
| 3308 | return; |
| 3309 | } |
| 3310 | ip6 = mtod(copym, struct ip6_hdr *); |
| 3311 | /* |
| 3312 | * clear embedded scope identifiers if necessary. |
| 3313 | * in6_clearscope will touch the addresses only when necessary. |
| 3314 | */ |
| 3315 | in6_clearscope(&ip6->ip6_src); |
| 3316 | in6_clearscope(&ip6->ip6_dst); |
| 3317 | if (copym->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { |
| 3318 | copym->m_pkthdr.csum_flags |= CSUM_DATA_VALID_IPV6 | |
| 3319 | CSUM_PSEUDO_HDR; |
| 3320 | copym->m_pkthdr.csum_data = 0xffff; |
| 3321 | } |
| 3322 | if_simloop(ifp, copym, AF_INET6, 0); |
| 3323 | } |
| 3324 | |
| 3325 | /* |
| 3326 | * Chop IPv6 header off from the payload. |
no test coverage detected