| 349 | } |
| 350 | |
| 351 | static int |
| 352 | ipsec_transmit(struct ifnet *ifp, struct mbuf *m) |
| 353 | { |
| 354 | IPSEC_RLOCK_TRACKER; |
| 355 | struct ipsec_softc *sc; |
| 356 | struct secpolicy *sp; |
| 357 | struct ip *ip; |
| 358 | uint32_t af; |
| 359 | int error; |
| 360 | |
| 361 | IPSEC_RLOCK(); |
| 362 | #ifdef MAC |
| 363 | error = mac_ifnet_check_transmit(ifp, m); |
| 364 | if (error) { |
| 365 | m_freem(m); |
| 366 | goto err; |
| 367 | } |
| 368 | #endif |
| 369 | error = ENETDOWN; |
| 370 | sc = ifp->if_softc; |
| 371 | if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || |
| 372 | (ifp->if_flags & IFF_MONITOR) != 0 || |
| 373 | (ifp->if_flags & IFF_UP) == 0 || sc->family == 0) { |
| 374 | m_freem(m); |
| 375 | goto err; |
| 376 | } |
| 377 | |
| 378 | /* Determine address family to correctly handle packet in BPF */ |
| 379 | ip = mtod(m, struct ip *); |
| 380 | switch (ip->ip_v) { |
| 381 | #ifdef INET |
| 382 | case IPVERSION: |
| 383 | af = AF_INET; |
| 384 | break; |
| 385 | #endif |
| 386 | #ifdef INET6 |
| 387 | case (IPV6_VERSION >> 4): |
| 388 | af = AF_INET6; |
| 389 | break; |
| 390 | #endif |
| 391 | default: |
| 392 | error = EAFNOSUPPORT; |
| 393 | m_freem(m); |
| 394 | goto err; |
| 395 | } |
| 396 | |
| 397 | /* |
| 398 | * Loop prevention. |
| 399 | * XXX: for now just check presence of IPSEC_OUT_DONE mbuf tag. |
| 400 | * We can read full chain and compare destination address, |
| 401 | * proto and mode from xform_history with values from softc. |
| 402 | */ |
| 403 | if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) { |
| 404 | m_freem(m); |
| 405 | goto err; |
| 406 | } |
| 407 | |
| 408 | sp = ipsec_getpolicy(sc, IPSEC_DIR_OUTBOUND, af); |
nothing calls this directly
no test coverage detected