* if_simloop() * * This function is to support software emulation of hardware loopback, * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't * hear their own broadcasts, we create a copy of the packet that we * would normally receive via a hardware loopback. * * This function expects the packet to include the media header of length hlen. */
| 283 | * This function expects the packet to include the media header of length hlen. |
| 284 | */ |
| 285 | int |
| 286 | if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen) |
| 287 | { |
| 288 | int isr; |
| 289 | |
| 290 | M_ASSERTPKTHDR(m); |
| 291 | m_tag_delete_nonpersistent(m); |
| 292 | m->m_pkthdr.rcvif = ifp; |
| 293 | |
| 294 | #ifdef MAC |
| 295 | mac_ifnet_create_mbuf(ifp, m); |
| 296 | #endif |
| 297 | |
| 298 | /* |
| 299 | * Let BPF see incoming packet in the following manner: |
| 300 | * - Emulated packet loopback for a simplex interface |
| 301 | * (net/if_ethersubr.c) |
| 302 | * -> passes it to ifp's BPF |
| 303 | * - IPv4/v6 multicast packet loopback (netinet(6)/ip(6)_output.c) |
| 304 | * -> not passes it to any BPF |
| 305 | * - Normal packet loopback from myself to myself (net/if_loop.c) |
| 306 | * -> passes to lo0's BPF (even in case of IPv6, where ifp!=lo0) |
| 307 | */ |
| 308 | if (hlen > 0) { |
| 309 | if (bpf_peers_present(ifp->if_bpf)) { |
| 310 | bpf_mtap(ifp->if_bpf, m); |
| 311 | } |
| 312 | } else { |
| 313 | if (bpf_peers_present(V_loif->if_bpf)) { |
| 314 | if ((m->m_flags & M_MCAST) == 0 || V_loif == ifp) { |
| 315 | /* XXX beware sizeof(af) != 4 */ |
| 316 | u_int32_t af1 = af; |
| 317 | |
| 318 | /* |
| 319 | * We need to prepend the address family. |
| 320 | */ |
| 321 | bpf_mtap2(V_loif->if_bpf, &af1, sizeof(af1), m); |
| 322 | } |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | /* Strip away media header */ |
| 327 | if (hlen > 0) { |
| 328 | m_adj(m, hlen); |
| 329 | #ifndef __NO_STRICT_ALIGNMENT |
| 330 | /* |
| 331 | * Some archs do not like unaligned data, so |
| 332 | * we move data down in the first mbuf. |
| 333 | */ |
| 334 | if (mtod(m, vm_offset_t) & 3) { |
| 335 | KASSERT(hlen >= 3, ("if_simloop: hlen too small")); |
| 336 | bcopy(m->m_data, |
| 337 | (char *)(mtod(m, vm_offset_t) |
| 338 | - (mtod(m, vm_offset_t) & 3)), |
| 339 | m->m_len); |
| 340 | m->m_data -= (mtod(m,vm_offset_t) & 3); |
| 341 | } |
| 342 | #endif |
no test coverage detected