| 449 | } |
| 450 | |
| 451 | int |
| 452 | ipsec_if_input(struct mbuf *m, struct secasvar *sav, uint32_t af) |
| 453 | { |
| 454 | IPSEC_RLOCK_TRACKER; |
| 455 | struct secasindex *saidx; |
| 456 | struct ipsec_softc *sc; |
| 457 | struct ifnet *ifp; |
| 458 | |
| 459 | if (sav->state != SADB_SASTATE_MATURE && |
| 460 | sav->state != SADB_SASTATE_DYING) { |
| 461 | m_freem(m); |
| 462 | return (ENETDOWN); |
| 463 | } |
| 464 | |
| 465 | if (sav->sah->saidx.mode != IPSEC_MODE_TUNNEL || |
| 466 | sav->sah->saidx.proto != IPPROTO_ESP) |
| 467 | return (0); |
| 468 | |
| 469 | IPSEC_RLOCK(); |
| 470 | CK_LIST_FOREACH(sc, ipsec_idhash(sav->sah->saidx.reqid), idhash) { |
| 471 | if (sc->family == 0) |
| 472 | continue; |
| 473 | saidx = ipsec_getsaidx(sc, IPSEC_DIR_INBOUND, |
| 474 | sav->sah->saidx.src.sa.sa_family); |
| 475 | /* SA's reqid should match reqid in SP */ |
| 476 | if (saidx == NULL || |
| 477 | sav->sah->saidx.reqid != saidx->reqid) |
| 478 | continue; |
| 479 | /* SAH's addresses should match tunnel endpoints. */ |
| 480 | if (key_sockaddrcmp(&sav->sah->saidx.dst.sa, |
| 481 | &saidx->dst.sa, 0) != 0) |
| 482 | continue; |
| 483 | if (key_sockaddrcmp(&sav->sah->saidx.src.sa, |
| 484 | &saidx->src.sa, 0) == 0) |
| 485 | break; |
| 486 | } |
| 487 | if (sc == NULL) { |
| 488 | IPSEC_RUNLOCK(); |
| 489 | /* Tunnel was not found. Nothing to do. */ |
| 490 | return (0); |
| 491 | } |
| 492 | ifp = sc->ifp; |
| 493 | if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || |
| 494 | (ifp->if_flags & IFF_UP) == 0) { |
| 495 | IPSEC_RUNLOCK(); |
| 496 | m_freem(m); |
| 497 | return (ENETDOWN); |
| 498 | } |
| 499 | /* |
| 500 | * We found matching and working tunnel. |
| 501 | * Set its ifnet as receiving interface. |
| 502 | */ |
| 503 | m->m_pkthdr.rcvif = ifp; |
| 504 | |
| 505 | m_clrprotoflags(m); |
| 506 | M_SETFIB(m, ifp->if_fib); |
| 507 | BPF_MTAP2(ifp, &af, sizeof(af), m); |
| 508 | if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); |
no test coverage detected