diff options
Diffstat (limited to 'sys/netinet6/ip6_ipsec.c')
-rw-r--r-- | sys/netinet6/ip6_ipsec.c | 151 |
1 files changed, 31 insertions, 120 deletions
diff --git a/sys/netinet6/ip6_ipsec.c b/sys/netinet6/ip6_ipsec.c index ea47566..ac49275 100644 --- a/sys/netinet6/ip6_ipsec.c +++ b/sys/netinet6/ip6_ipsec.c @@ -117,42 +117,18 @@ ip6_ipsec_filtertunnel(struct mbuf *m) /* * Check if this packet has an active SA and needs to be dropped instead * of forwarded. - * Called from ip6_input(). + * Called from ip6_forward(). * 1 = drop packet, 0 = forward packet. */ int ip6_ipsec_fwd(struct mbuf *m) { -#ifdef IPSEC - struct m_tag *mtag; - struct tdb_ident *tdbi; - struct secpolicy *sp; - int error; - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); - } else { - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } - if (sp == NULL) { /* NB: can happen if error */ - /*XXX error stat???*/ - DPRINTF(("%s: no SP for forwarding\n", __func__)); /*XXX*/ - return 1; - } - /* - * Check security policy against packet attributes. - */ - error = ipsec_in_reject(sp, m); - KEY_FREESP(&sp); - if (error) { - IP6STAT_INC(ip6s_cantforward); - return 1; - } -#endif /* IPSEC */ - return 0; +#ifdef IPSEC + return (ipsec6_in_reject(m, NULL)); +#else + return (0); +#endif /* !IPSEC */ } /* @@ -165,50 +141,17 @@ ip6_ipsec_fwd(struct mbuf *m) int ip6_ipsec_input(struct mbuf *m, int nxt) { + #ifdef IPSEC - struct m_tag *mtag; - struct tdb_ident *tdbi; - struct secpolicy *sp; - int error; /* * enforce IPsec policy checking if we are seeing last header. * note that we do not visit this with protocols with pcb layer * code - like udp/tcp/raw ip. */ - if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && - ipsec6_in_reject(m, NULL)) { - - /* - * Check if the packet has already had IPsec processing - * done. If so, then just pass it along. This tag gets - * set during AH, ESP, etc. input handling, before the - * packet is returned to the ip input queue for delivery. - */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); - } else { - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } - if (sp != NULL) { - /* - * Check security policy against packet attributes. - */ - error = ipsec_in_reject(sp, m); - KEY_FREESP(&sp); - } else { - /* XXX error stat??? */ - error = EINVAL; - DPRINTF(("%s: no SP, packet discarded\n", __func__));/*XXX*/ - return 1; - } - if (error) - return 1; - } + if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0) + return (ipsec6_in_reject(m, NULL)); #endif /* IPSEC */ - return 0; + return (0); } /* @@ -218,27 +161,26 @@ ip6_ipsec_input(struct mbuf *m, int nxt) */ int -ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error, - struct ifnet **ifp) +ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error) { #ifdef IPSEC - struct secpolicy *sp = NULL; - struct tdb_ident *tdbi; - struct m_tag *mtag; - /* XXX int s; */ - mtag = m_tag_find(*m, PACKET_TAG_IPSEC_PENDING_TDB, NULL); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND); - if (sp == NULL) - *error = -EINVAL; /* force silent drop */ - m_tag_delete(*m, mtag); - } else { - sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, *flags, - error, inp); - } + struct secpolicy *sp; /* + * Check the security policy (SP) for the packet and, if + * required, do IPsec-related processing. There are two + * cases here; the first time a packet is sent through + * it will be untagged and handled by ipsec4_checkpolicy. + * If the packet is resubmitted to ip6_output (e.g. after + * AH, ESP, etc. processing), there will be a tag to bypass + * the lookup and related policy checking. + */ + if (m_tag_find(*m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) { + *error = 0; + return (0); + } + sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, error, inp); + /* * There are four return cases: * sp != NULL apply IPsec policy * sp == NULL, error == 0 no IPsec handling needed @@ -246,36 +188,6 @@ ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error, * sp == NULL, error != 0 discard packet, report error */ if (sp != NULL) { - /* Loop detection, check if ipsec processing already done */ - KASSERT(sp->req != NULL, ("ip_output: no ipsec request")); - for (mtag = m_tag_first(*m); mtag != NULL; - mtag = m_tag_next(*m, mtag)) { - if (mtag->m_tag_cookie != MTAG_ABI_COMPAT) - continue; - if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE && - mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED) - continue; - /* - * Check if policy has no SA associated with it. - * This can happen when an SP has yet to acquire - * an SA; e.g. on first reference. If it occurs, - * then we let ipsec4_process_packet do its thing. - */ - if (sp->req->sav == NULL) - break; - tdbi = (struct tdb_ident *)(mtag + 1); - if (tdbi->spi == sp->req->sav->spi && - tdbi->proto == sp->req->sav->sah->saidx.proto && - bcmp(&tdbi->dst, &sp->req->sav->sah->saidx.dst, - sizeof (union sockaddr_union)) == 0) { - /* - * No IPsec processing is needed, free - * reference to SP. - */ - goto done; - } - } - /* * Do delayed checksums now because we send before * this is done in the normal processing path. @@ -300,7 +212,9 @@ ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error, /* NB: callee frees mbuf */ *error = ipsec6_process_packet(*m, sp->req); - + /* Release SP if an error occured */ + if (*error != 0) + KEY_FREESP(&sp); if (*error == EJUSTRETURN) { /* * We had a SP with a level of 'use' and no SA. We @@ -332,18 +246,15 @@ ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error, if (*error == -EINVAL) *error = 0; goto bad; - } else { - /* No IPsec processing for this packet. */ } + /* No IPsec processing for this packet. */ } done: if (sp != NULL) KEY_FREESP(&sp); return 0; reinjected: - if (sp != NULL) - KEY_FREESP(&sp); - return -1; + return (-1); bad: if (sp != NULL) KEY_FREESP(&sp); |