summaryrefslogtreecommitdiffstats
path: root/sys/netipsec/ipsec_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netipsec/ipsec_input.c')
-rw-r--r--sys/netipsec/ipsec_input.c281
1 files changed, 146 insertions, 135 deletions
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
index 0512b66..9eefa4d 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -91,11 +91,11 @@
#include <machine/in_cksum.h>
#include <machine/stdarg.h>
-#include <net/net_osdep.h>
-
#define IPSEC_ISTAT(p,x,y,z) ((p) == IPPROTO_ESP ? (x)++ : \
(p) == IPPROTO_AH ? (y)++ : (z)++)
+static void ipsec4_common_ctlinput(int, struct sockaddr *, void *, int);
+
/*
* ipsec_common_input gets called when an IPsec-protected packet
* is received by IPv4 or IPv6. It's job is to find the right SA
@@ -113,7 +113,7 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
IPSEC_ISTAT(sproto, espstat.esps_input, ahstat.ahs_input,
ipcompstat.ipcomps_input);
- KASSERT(m != NULL, ("ipsec_common_input: null packet"));
+ IPSEC_ASSERT(m != NULL, ("null packet"));
if ((sproto == IPPROTO_ESP && !esp_enable) ||
(sproto == IPPROTO_AH && !ah_enable) ||
@@ -128,7 +128,7 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
m_freem(m);
IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops,
ipcompstat.ipcomps_hdrops);
- DPRINTF(("ipsec_common_input: packet too small\n"));
+ DPRINTF(("%s: packet too small\n", __func__));
return EINVAL;
}
@@ -170,8 +170,7 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
break;
#endif /* INET6 */
default:
- DPRINTF(("ipsec_common_input: unsupported protocol "
- "family %u\n", af));
+ DPRINTF(("%s: unsupported protocol family %u\n", __func__, af));
m_freem(m);
IPSEC_ISTAT(sproto, espstat.esps_nopf, ahstat.ahs_nopf,
ipcompstat.ipcomps_nopf);
@@ -181,9 +180,8 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
/* NB: only pass dst since key_allocsa follows RFC2401 */
sav = KEY_ALLOCSA(&dst_address, sproto, spi);
if (sav == NULL) {
- DPRINTF(("ipsec_common_input: no key association found for"
- " SA %s/%08lx/%u\n",
- ipsec_address(&dst_address),
+ DPRINTF(("%s: no key association found for SA %s/%08lx/%u\n",
+ __func__, ipsec_address(&dst_address),
(u_long) ntohl(spi), sproto));
IPSEC_ISTAT(sproto, espstat.esps_notdb, ahstat.ahs_notdb,
ipcompstat.ipcomps_notdb);
@@ -192,9 +190,8 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
}
if (sav->tdb_xform == NULL) {
- DPRINTF(("ipsec_common_input: attempted to use uninitialized"
- " SA %s/%08lx/%u\n",
- ipsec_address(&dst_address),
+ DPRINTF(("%s: attempted to use uninitialized SA %s/%08lx/%u\n",
+ __func__, ipsec_address(&dst_address),
(u_long) ntohl(spi), sproto));
IPSEC_ISTAT(sproto, espstat.esps_noxform, ahstat.ahs_noxform,
ipcompstat.ipcomps_noxform);
@@ -236,12 +233,26 @@ ah4_input(struct mbuf *m, int off)
{
ipsec4_common_input(m, off, IPPROTO_AH);
}
+void
+ah4_ctlinput(int cmd, struct sockaddr *sa, void *v)
+{
+ if (sa->sa_family == AF_INET &&
+ sa->sa_len == sizeof(struct sockaddr_in))
+ ipsec4_common_ctlinput(cmd, sa, v, IPPROTO_AH);
+}
void
esp4_input(struct mbuf *m, int off)
{
ipsec4_common_input(m, off, IPPROTO_ESP);
}
+void
+esp4_ctlinput(int cmd, struct sockaddr *sa, void *v)
+{
+ if (sa->sa_family == AF_INET &&
+ sa->sa_len == sizeof(struct sockaddr_in))
+ ipsec4_common_ctlinput(cmd, sa, v, IPPROTO_ESP);
+}
void
ipcomp4_input(struct mbuf *m, int off)
@@ -266,25 +277,22 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
struct secasindex *saidx;
int error;
-#if 0
- SPLASSERT(net, "ipsec4_common_input_cb");
-#endif
+ IPSEC_SPLASSERT_SOFTNET(__func__);
- KASSERT(m != NULL, ("ipsec4_common_input_cb: null mbuf"));
- KASSERT(sav != NULL, ("ipsec4_common_input_cb: null SA"));
- KASSERT(sav->sah != NULL, ("ipsec4_common_input_cb: null SAH"));
+ IPSEC_ASSERT(m != NULL, ("null mbuf"));
+ IPSEC_ASSERT(sav != NULL, ("null SA"));
+ IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
saidx = &sav->sah->saidx;
af = saidx->dst.sa.sa_family;
- KASSERT(af == AF_INET, ("ipsec4_common_input_cb: unexpected af %u",af));
+ IPSEC_ASSERT(af == AF_INET, ("unexpected af %u", af));
sproto = saidx->proto;
- KASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
+ IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
sproto == IPPROTO_IPCOMP,
- ("ipsec4_common_input_cb: unexpected security protocol %u",
- sproto));
+ ("unexpected security protocol %u", sproto));
/* Sanity check */
if (m == NULL) {
- DPRINTF(("ipsec4_common_input_cb: null mbuf"));
+ DPRINTF(("%s: null mbuf", __func__));
IPSEC_ISTAT(sproto, espstat.esps_badkcr, ahstat.ahs_badkcr,
ipcompstat.ipcomps_badkcr);
KEY_FREESAV(&sav);
@@ -294,9 +302,8 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
if (skip != 0) {
/* Fix IPv4 header */
if (m->m_len < skip && (m = m_pullup(m, skip)) == NULL) {
- DPRINTF(("ipsec4_common_input_cb: processing failed "
- "for SA %s/%08lx\n",
- ipsec_address(&sav->sah->saidx.dst),
+ DPRINTF(("%s: processing failed for SA %s/%08lx\n",
+ __func__, ipsec_address(&sav->sah->saidx.dst),
(u_long) ntohl(sav->spi)));
IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops,
ipcompstat.ipcomps_hdrops);
@@ -343,9 +350,9 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
(saidx->proxy.sa.sa_family != AF_INET &&
saidx->proxy.sa.sa_family != 0)) {
- DPRINTF(("ipsec4_common_input_cb: inner "
- "source address %s doesn't correspond to "
- "expected proxy source %s, SA %s/%08lx\n",
+ DPRINTF(("%s: inner source address %s doesn't "
+ "correspond to expected proxy source %s, "
+ "SA %s/%08lx\n", __func__,
inet_ntoa4(ipn.ip_src),
ipsp_address(saidx->proxy),
ipsp_address(saidx->dst),
@@ -387,9 +394,9 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
(saidx->proxy.sa.sa_family != AF_INET6 &&
saidx->proxy.sa.sa_family != 0)) {
- DPRINTF(("ipsec4_common_input_cb: inner "
- "source address %s doesn't correspond to "
- "expected proxy source %s, SA %s/%08lx\n",
+ DPRINTF(("%s: inner source address %s doesn't "
+ "correspond to expected proxy source %s, "
+ "SA %s/%08lx\n", __func__,
ip6_sprintf(&ip6n.ip6_src),
ipsec_address(&saidx->proxy),
ipsec_address(&saidx->dst),
@@ -417,7 +424,7 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
sizeof(struct tdb_ident), M_NOWAIT);
if (mtag == NULL) {
- DPRINTF(("ipsec4_common_input_cb: failed to get tag\n"));
+ DPRINTF(("%s: failed to get tag\n", __func__));
IPSEC_ISTAT(sproto, espstat.esps_hdrops,
ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops);
error = ENOMEM;
@@ -444,8 +451,8 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
IPSEC_ISTAT(sproto, espstat.esps_qfull, ahstat.ahs_qfull,
ipcompstat.ipcomps_qfull);
- DPRINTF(("ipsec4_common_input_cb: queue full; "
- "proto %u packet dropped\n", sproto));
+ DPRINTF(("%s: queue full; proto %u packet dropped\n",
+ __func__, sproto));
return ENOBUFS;
}
return 0;
@@ -453,6 +460,12 @@ bad:
m_freem(m);
return error;
}
+
+void
+ipsec4_common_ctlinput(int cmd, struct sockaddr *sa, void *v, int proto)
+{
+ /* XXX nothing just yet */
+}
#endif /* INET */
#ifdef INET6
@@ -465,7 +478,7 @@ ipsec6_common_input(struct mbuf **mp, int *offp, int proto)
struct ip6_ext ip6e;
if (*offp < sizeof(struct ip6_hdr)) {
- DPRINTF(("ipsec6_common_input: bad offset %u\n", *offp));
+ DPRINTF(("%s: bad offset %u\n", __func__, *offp));
return IPPROTO_DONE;
} else if (*offp == sizeof(struct ip6_hdr)) {
protoff = offsetof(struct ip6_hdr, ip6_nxt);
@@ -482,13 +495,13 @@ ipsec6_common_input(struct mbuf **mp, int *offp, int proto)
l = (ip6e.ip6e_len + 2) << 2;
else
l = (ip6e.ip6e_len + 1) << 3;
- KASSERT(l > 0, ("ah6_input: l went zero or negative"));
+ IPSEC_ASSERT(l > 0, ("l went zero or negative"));
} while (protoff + l < *offp);
/* Malformed packet check */
if (protoff + l != *offp) {
- DPRINTF(("ipsec6_common_input: bad packet header chain, "
- "protoff %u, l %u, off %u\n", protoff, l, *offp));
+ DPRINTF(("%s: bad packet header chain, protoff %u, "
+ "l %u, off %u\n", __func__, protoff, l, *offp));
IPSEC_ISTAT(proto, espstat.esps_hdrops,
ahstat.ahs_hdrops,
ipcompstat.ipcomps_hdrops);
@@ -502,82 +515,6 @@ ipsec6_common_input(struct mbuf **mp, int *offp, int proto)
return IPPROTO_DONE;
}
-void
-esp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
-{
- if (sa->sa_family != AF_INET6 ||
- sa->sa_len != sizeof(struct sockaddr_in6))
- return;
- if ((unsigned)cmd >= PRC_NCMDS)
- return;
-
- /* if the parameter is from icmp6, decode it. */
- if (d != NULL) {
- struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
- struct mbuf *m = ip6cp->ip6c_m;
- int off = ip6cp->ip6c_off;
-
- struct ip6ctlparam ip6cp1;
-
- /*
- * Notify the error to all possible sockets via pfctlinput2.
- * Since the upper layer information (such as protocol type,
- * source and destination ports) is embedded in the encrypted
- * data and might have been cut, we can't directly call
- * an upper layer ctlinput function. However, the pcbnotify
- * function will consider source and destination addresses
- * as well as the flow info value, and may be able to find
- * some PCB that should be notified.
- * Although pfctlinput2 will call esp6_ctlinput(), there is
- * no possibility of an infinite loop of function calls,
- * because we don't pass the inner IPv6 header.
- */
- bzero(&ip6cp1, sizeof(ip6cp1));
- ip6cp1.ip6c_src = ip6cp->ip6c_src;
- pfctlinput2(cmd, sa, (void *)&ip6cp1);
-
- /*
- * Then go to special cases that need ESP header information.
- * XXX: We assume that when ip6 is non NULL,
- * M and OFF are valid.
- */
-
- if (cmd == PRC_MSGSIZE) {
- struct secasvar *sav;
- u_int32_t spi;
- int valid;
-
- /* check header length before using m_copydata */
- if (m->m_pkthdr.len < off + sizeof (struct esp))
- return;
- m_copydata(m, off + offsetof(struct esp, esp_spi),
- sizeof(u_int32_t), (caddr_t) &spi);
- /*
- * Check to see if we have a valid SA corresponding to
- * the address in the ICMP message payload.
- */
- sav = KEY_ALLOCSA((union sockaddr_union *)sa,
- IPPROTO_ESP, spi);
- valid = (sav != NULL);
- if (sav)
- KEY_FREESAV(&sav);
-
- /* XXX Further validation? */
-
- /*
- * Depending on whether the SA is "valid" and
- * routing table size (mtudisc_{hi,lo}wat), we will:
- * - recalcurate the new MTU and create the
- * corresponding routing entry, or
- * - ignore the MTU change notification.
- */
- icmp6_mtudisc_update(ip6cp, valid);
- }
- } else {
- /* we normally notify any pcb here */
- }
-}
-
/*
* IPsec input callback, called by the transform callback. Takes care of
* filtering and other sanity checks on the processed packet.
@@ -595,22 +532,20 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
u_int8_t nxt8;
int error, nest;
- KASSERT(m != NULL, ("ipsec6_common_input_cb: null mbuf"));
- KASSERT(sav != NULL, ("ipsec6_common_input_cb: null SA"));
- KASSERT(sav->sah != NULL, ("ipsec6_common_input_cb: null SAH"));
+ IPSEC_ASSERT(m != NULL, ("null mbuf"));
+ IPSEC_ASSERT(sav != NULL, ("null SA"));
+ IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
saidx = &sav->sah->saidx;
af = saidx->dst.sa.sa_family;
- KASSERT(af == AF_INET6,
- ("ipsec6_common_input_cb: unexpected af %u", af));
+ IPSEC_ASSERT(af == AF_INET6, ("unexpected af %u", af));
sproto = saidx->proto;
- KASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
+ IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
sproto == IPPROTO_IPCOMP,
- ("ipsec6_common_input_cb: unexpected security protocol %u",
- sproto));
+ ("unexpected security protocol %u", sproto));
/* Sanity check */
if (m == NULL) {
- DPRINTF(("ipsec4_common_input_cb: null mbuf"));
+ DPRINTF(("%s: null mbuf", __func__));
IPSEC_ISTAT(sproto, espstat.esps_badkcr, ahstat.ahs_badkcr,
ipcompstat.ipcomps_badkcr);
error = EINVAL;
@@ -621,8 +556,8 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
if (m->m_len < sizeof(struct ip6_hdr) &&
(m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
- DPRINTF(("ipsec_common_input_cb: processing failed "
- "for SA %s/%08lx\n", ipsec_address(&sav->sah->saidx.dst),
+ DPRINTF(("%s: processing failed for SA %s/%08lx\n",
+ __func__, ipsec_address(&sav->sah->saidx.dst),
(u_long) ntohl(sav->spi)));
IPSEC_ISTAT(sproto, espstat.esps_hdrops, ahstat.ahs_hdrops,
@@ -663,9 +598,9 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
(saidx->proxy.sa.sa_family != AF_INET &&
saidx->proxy.sa.sa_family != 0)) {
- DPRINTF(("ipsec_common_input_cb: inner "
- "source address %s doesn't correspond to "
- "expected proxy source %s, SA %s/%08lx\n",
+ DPRINTF(("%s: inner source address %s doesn't "
+ "correspond to expected proxy source %s, "
+ "SA %s/%08lx\n", __func__,
inet_ntoa4(ipn.ip_src),
ipsec_address(&saidx->proxy),
ipsec_address(&saidx->dst),
@@ -707,9 +642,9 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
(saidx->proxy.sa.sa_family != AF_INET6 &&
saidx->proxy.sa.sa_family != 0)) {
- DPRINTF(("ipsec_common_input_cb: inner "
- "source address %s doesn't correspond to "
- "expected proxy source %s, SA %s/%08lx\n",
+ DPRINTF(("%s: inner source address %s doesn't "
+ "correspond to expected proxy source %s, "
+ "SA %s/%08lx\n", __func__,
ip6_sprintf(&ip6n.ip6_src),
ipsec_address(&saidx->proxy),
ipsec_address(&saidx->dst),
@@ -735,8 +670,7 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
sizeof(struct tdb_ident), M_NOWAIT);
if (mtag == NULL) {
- DPRINTF(("ipsec_common_input_cb: failed to "
- "get tag\n"));
+ DPRINTF(("%s: failed to get tag\n", __func__));
IPSEC_ISTAT(sproto, espstat.esps_hdrops,
ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops);
error = ENOMEM;
@@ -750,7 +684,8 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
m_tag_prepend(m, mtag);
} else {
- mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE;
+ if (mt != NULL)
+ mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE;
/* XXX do we need to mark m_flags??? */
}
@@ -800,4 +735,80 @@ bad:
m_freem(m);
return error;
}
+
+void
+esp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
+{
+ if (sa->sa_family != AF_INET6 ||
+ sa->sa_len != sizeof(struct sockaddr_in6))
+ return;
+ if ((unsigned)cmd >= PRC_NCMDS)
+ return;
+
+ /* if the parameter is from icmp6, decode it. */
+ if (d != NULL) {
+ struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
+ struct mbuf *m = ip6cp->ip6c_m;
+ int off = ip6cp->ip6c_off;
+
+ struct ip6ctlparam ip6cp1;
+
+ /*
+ * Notify the error to all possible sockets via pfctlinput2.
+ * Since the upper layer information (such as protocol type,
+ * source and destination ports) is embedded in the encrypted
+ * data and might have been cut, we can't directly call
+ * an upper layer ctlinput function. However, the pcbnotify
+ * function will consider source and destination addresses
+ * as well as the flow info value, and may be able to find
+ * some PCB that should be notified.
+ * Although pfctlinput2 will call esp6_ctlinput(), there is
+ * no possibility of an infinite loop of function calls,
+ * because we don't pass the inner IPv6 header.
+ */
+ bzero(&ip6cp1, sizeof(ip6cp1));
+ ip6cp1.ip6c_src = ip6cp->ip6c_src;
+ pfctlinput2(cmd, sa, (void *)&ip6cp1);
+
+ /*
+ * Then go to special cases that need ESP header information.
+ * XXX: We assume that when ip6 is non NULL,
+ * M and OFF are valid.
+ */
+
+ if (cmd == PRC_MSGSIZE) {
+ struct secasvar *sav;
+ u_int32_t spi;
+ int valid;
+
+ /* check header length before using m_copydata */
+ if (m->m_pkthdr.len < off + sizeof (struct esp))
+ return;
+ m_copydata(m, off + offsetof(struct esp, esp_spi),
+ sizeof(u_int32_t), (caddr_t) &spi);
+ /*
+ * Check to see if we have a valid SA corresponding to
+ * the address in the ICMP message payload.
+ */
+ sav = KEY_ALLOCSA((union sockaddr_union *)sa,
+ IPPROTO_ESP, spi);
+ valid = (sav != NULL);
+ if (sav)
+ KEY_FREESAV(&sav);
+
+ /* XXX Further validation? */
+
+ /*
+ * Depending on whether the SA is "valid" and
+ * routing table size (mtudisc_{hi,lo}wat), we will:
+ * - recalcurate the new MTU and create the
+ * corresponding routing entry, or
+ * - ignore the MTU change notification.
+ */
+ icmp6_mtudisc_update(ip6cp, valid);
+ }
+ } else {
+ /* we normally notify any pcb here */
+ }
+}
#endif /* INET6 */
OpenPOWER on IntegriCloud