summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6.c1
-rw-r--r--sys/netinet6/ip6_forward.c54
-rw-r--r--sys/netinet6/ip6_input.c8
-rw-r--r--sys/netinet6/ip6_ipsec.c153
-rw-r--r--sys/netinet6/ip6_ipsec.h3
-rw-r--r--sys/netinet6/ip6_output.c3
-rw-r--r--sys/netinet6/ip6_var.h4
-rw-r--r--sys/netinet6/raw_ip6.c2
-rw-r--r--sys/netinet6/udp6_usrreq.c1
9 files changed, 63 insertions, 166 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index e2073f5..e3c3229 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2375,6 +2375,7 @@ in6if_do_dad(struct ifnet *ifp)
case IFT_DUMMY:
#endif
case IFT_FAITH:
+ case IFT_STF:
/*
* These interfaces do not have the IFF_LOOPBACK flag,
* but loop packets back. We do not have to do DAD on such
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index caa58e6..053864a 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_pcb.h>
#ifdef IPSEC
+#include <netinet6/ip6_ipsec.h>
#include <netipsec/ipsec.h>
#include <netipsec/ipsec6.h>
#include <netipsec/key.h>
@@ -111,21 +112,6 @@ ip6_forward(struct mbuf *m, int srcrt)
struct m_tag *fwd_tag;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
-#ifdef IPSEC
- /*
- * Check AH/ESP integrity.
- */
- /*
- * Don't increment ip6s_cantforward because this is the check
- * before forwarding packet actually.
- */
- if (ipsec6_in_reject(m, NULL)) {
- IPSEC6STAT_INC(ips_in_polvio);
- m_freem(m);
- return;
- }
-#endif /* IPSEC */
-
/*
* Do not forward packets to multicast destination (should be handled
* by ip6_mforward().
@@ -150,6 +136,17 @@ ip6_forward(struct mbuf *m, int srcrt)
m_freem(m);
return;
}
+#ifdef IPSEC
+ /*
+ * Check if this packet has an active SA and needs to be dropped
+ * instead of forwarded.
+ */
+ if (ip6_ipsec_fwd(m) != 0) {
+ IP6STAT_INC(ip6s_cantforward);
+ m_freem(m);
+ return;
+ }
+#endif /* IPSEC */
#ifdef IPSTEALTH
if (!V_ip6stealth) {
@@ -179,8 +176,7 @@ ip6_forward(struct mbuf *m, int srcrt)
#ifdef IPSEC
/* get a security policy for this packet */
- sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND,
- IP_FORWARDING, &error);
+ sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, &error);
if (sp == NULL) {
IPSEC6STAT_INC(ips_out_inval);
IP6STAT_INC(ip6s_cantforward);
@@ -254,8 +250,7 @@ ip6_forward(struct mbuf *m, int srcrt)
/*
* when the kernel forwards a packet, it is not proper to apply
- * IPsec transport mode to the packet is not proper. this check
- * avoid from this.
+ * IPsec transport mode to the packet. This check avoid from this.
* at present, if there is even a transport mode SA request in the
* security policy, the kernel does not apply IPsec to the packet.
* this check is not enough because the following case is valid.
@@ -289,9 +284,9 @@ ip6_forward(struct mbuf *m, int srcrt)
* ipsec6_proces_packet will send the packet using ip6_output
*/
error = ipsec6_process_packet(m, sp->req);
-
- KEY_FREESP(&sp);
-
+ /* 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
@@ -557,8 +552,6 @@ pass:
if (mcopy) {
u_long mtu;
#ifdef IPSEC
- struct secpolicy *sp;
- int ipsecerror;
size_t ipsechdrsiz;
#endif /* IPSEC */
@@ -571,15 +564,10 @@ pass:
* case, as we have the outgoing interface for
* encapsulated packet as "rt->rt_ifp".
*/
- sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
- IP_FORWARDING, &ipsecerror);
- if (sp) {
- ipsechdrsiz = ipsec_hdrsiz(mcopy,
- IPSEC_DIR_OUTBOUND, NULL);
- if (ipsechdrsiz < mtu)
- mtu -= ipsechdrsiz;
- }
-
+ ipsechdrsiz = ipsec_hdrsiz(mcopy, IPSEC_DIR_OUTBOUND,
+ NULL);
+ if (ipsechdrsiz < mtu)
+ mtu -= ipsechdrsiz;
/*
* if mtu becomes less than minimum MTU,
* tell minimum MTU (and I'll need to fragment it).
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index b8a75c6..0d1d307 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -136,6 +136,7 @@ static struct netisr_handler ip6_nh = {
VNET_DECLARE(struct callout, in6_tmpaddrtimer_ch);
#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
+SYSCTL_DECL(_net_inet6_ip6);
VNET_DEFINE(struct pfil_head, inet6_pfil_hook);
VNET_PCPUSTAT_DEFINE(struct ip6stat, ip6stat);
@@ -182,6 +183,9 @@ ip6_init(void)
if ((i = pfil_head_register(&V_inet6_pfil_hook)) != 0)
printf("%s: WARNING: unable to register pfil hook, "
"error %d\n", __func__, i);
+ else
+ pfil_head_export_sysctl(&V_inet6_pfil_hook,
+ SYSCTL_STATIC_CHILDREN(_net_inet6_ip6));
scope6_init();
addrsel_policy_init();
@@ -1726,7 +1730,7 @@ ip6_get_prevhdr(struct mbuf *m, int off)
* get next header offset. m will be retained.
*/
int
-ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp)
+ip6_nexthdr(const struct mbuf *m, int off, int proto, int *nxtp)
{
struct ip6_hdr ip6;
struct ip6_ext ip6e;
@@ -1801,7 +1805,7 @@ ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp)
* get offset for the last header in the chain. m will be kept untainted.
*/
int
-ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp)
+ip6_lasthdr(const struct mbuf *m, int off, int proto, int *nxtp)
{
int newoff;
int nxt;
diff --git a/sys/netinet6/ip6_ipsec.c b/sys/netinet6/ip6_ipsec.c
index ea47566..e10f274 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,7 @@ ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error,
/* NB: callee frees mbuf */
*error = ipsec6_process_packet(*m, sp->req);
-
+ KEY_FREESP(&sp);
if (*error == EJUSTRETURN) {
/*
* We had a SP with a level of 'use' and no SA. We
@@ -332,18 +244,13 @@ 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;
+ return (0);
reinjected:
- if (sp != NULL)
- KEY_FREESP(&sp);
- return -1;
+ return (-1);
bad:
if (sp != NULL)
KEY_FREESP(&sp);
diff --git a/sys/netinet6/ip6_ipsec.h b/sys/netinet6/ip6_ipsec.h
index a65b19a..e335d85 100644
--- a/sys/netinet6/ip6_ipsec.h
+++ b/sys/netinet6/ip6_ipsec.h
@@ -35,8 +35,7 @@
int ip6_ipsec_filtertunnel(struct mbuf *);
int ip6_ipsec_fwd(struct mbuf *);
int ip6_ipsec_input(struct mbuf *, int);
-int ip6_ipsec_output(struct mbuf **, struct inpcb *, int *, int *,
- struct ifnet **);
+int ip6_ipsec_output(struct mbuf **, struct inpcb *, int *);
#if 0
int ip6_ipsec_mtu(struct mbuf *);
#endif
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 4fbac61..09eab20 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -348,8 +348,9 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
/*
* IPSec checking which handles several cases.
* FAST IPSEC: We re-injected the packet.
+ * XXX: need scope argument.
*/
- switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp))
+ switch(ip6_ipsec_output(&m, inp, &error))
{
case 1: /* Bad packet */
goto freehdrs;
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index eba7f1c..a38f719 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -391,8 +391,8 @@ void ip6_freepcbopts(struct ip6_pktopts *);
int ip6_unknown_opt(u_int8_t *, struct mbuf *, int);
char * ip6_get_prevhdr(struct mbuf *, int);
-int ip6_nexthdr(struct mbuf *, int, int, int *);
-int ip6_lasthdr(struct mbuf *, int, int, int *);
+int ip6_nexthdr(const struct mbuf *, int, int, int *);
+int ip6_lasthdr(const struct mbuf *, int, int, int *);
#ifdef __notyet__
struct ip6aux *ip6_findaux(struct mbuf *);
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index a37dfc5..54841d1 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -269,7 +269,6 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
*/
if (n && ipsec6_in_reject(n, last)) {
m_freem(n);
- IPSEC6STAT_INC(ips_in_polvio);
/* Do not inject data into pcb. */
} else
#endif /* IPSEC */
@@ -301,7 +300,6 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
*/
if ((last != NULL) && ipsec6_in_reject(m, last)) {
m_freem(m);
- IPSEC6STAT_INC(ips_in_polvio);
IP6STAT_DEC(ip6s_delivered);
/* Do not inject data into pcb. */
INP_RUNLOCK(last);
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 17de377..92e6780 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -156,7 +156,6 @@ udp6_append(struct inpcb *inp, struct mbuf *n, int off,
/* Check AH/ESP integrity. */
if (ipsec6_in_reject(n, inp)) {
m_freem(n);
- IPSEC6STAT_INC(ips_in_polvio);
return;
}
#endif /* IPSEC */
OpenPOWER on IntegriCloud