dropped packets in the output path.
While here fix a memory leak when compression is not needed w/ IPcomp.
ok markus@
-/* $OpenBSD: ip_ah.c,v 1.141 2018/07/11 09:07:59 mpi Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.142 2018/07/12 15:51:50 mpi Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
#define DPRINTF(x)
#endif
-void ah_output_cb(struct cryptop *);
int ah_massage_headers(struct mbuf **, int, int, int, int);
const unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */
crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
crp->crp_flags = CRYPTO_F_IMBUF;
crp->crp_buf = (caddr_t)m;
- crp->crp_callback = ah_output_cb;
+ crp->crp_callback = ipsec_output_cb;
crp->crp_sid = tdb->tdb_cryptoid;
crp->crp_opaque = (caddr_t)tc;
}
/*
- * AH output callback, called directly from the crypto handler.
+ * AH output callback.
*/
-void
-ah_output_cb(struct cryptop *crp)
+int
+ah_output_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int ilen,
+ int olen)
{
- int skip;
- struct tdb_crypto *tc = NULL;
- struct tdb *tdb = NULL;
- struct mbuf *m;
- caddr_t ptr;
-
- tc = (struct tdb_crypto *) crp->crp_opaque;
- skip = tc->tc_skip;
- ptr = (caddr_t) (tc + 1);
-
- m = (struct mbuf *) crp->crp_buf;
- if (m == NULL) {
- /* Shouldn't happen... */
- DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
- ahstat_inc(ahs_crypto);
- goto droponly;
- }
-
- NET_LOCK();
-
- tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto);
- if (tdb == NULL) {
- DPRINTF(("%s: TDB is expired while in crypto\n", __func__));
- ahstat_inc(ahs_notdb);
- goto baddone;
- }
-
- /* Check for crypto errors. */
- if (crp->crp_etype) {
- if (crp->crp_etype == EAGAIN) {
- /* Reset the session ID */
- if (tdb->tdb_cryptoid != 0)
- tdb->tdb_cryptoid = crp->crp_sid;
- NET_UNLOCK();
- crypto_dispatch(crp);
- return;
- }
- DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
- ahstat_inc(ahs_noxform);
- goto baddone;
- }
+ int skip = tc->tc_skip;
+ caddr_t ptr = (caddr_t) (tc + 1);
/*
* Copy original headers (with the new protocol number) back
m_copyback(m, 0, skip, ptr, M_NOWAIT);
/* No longer needed. */
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
- if (ipsp_process_done(m, tdb))
+ /* Call the IPsec input callback. */
+ if (ipsp_process_done(m, tdb)) {
ahstat_inc(ahs_outfail);
- NET_UNLOCK();
- return;
+ return -1;
+ }
- baddone:
- NET_UNLOCK();
- droponly:
- m_freem(m);
- crypto_freereq(crp);
- free(tc, M_XDATA, 0);
+ return 0;
}
-/* $OpenBSD: ip_esp.c,v 1.156 2018/07/11 09:07:59 mpi Exp $ */
+/* $OpenBSD: ip_esp.c,v 1.157 2018/07/12 15:51:50 mpi Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
#include "bpfilter.h"
-void esp_output_cb(struct cryptop *);
-
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
#else
crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
crp->crp_flags = CRYPTO_F_IMBUF;
crp->crp_buf = (caddr_t)m;
- crp->crp_callback = esp_output_cb;
+ crp->crp_callback = ipsec_output_cb;
crp->crp_opaque = (caddr_t)tc;
crp->crp_sid = tdb->tdb_cryptoid;
return error;
}
-/*
- * ESP output callback, called directly by the crypto driver.
- */
-void
-esp_output_cb(struct cryptop *crp)
+int
+esp_output_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int ilen,
+ int olen)
{
- struct tdb_crypto *tc;
- struct tdb *tdb;
- struct mbuf *m;
-
- tc = (struct tdb_crypto *) crp->crp_opaque;
-
- m = (struct mbuf *) crp->crp_buf;
- if (m == NULL) {
- /* Shouldn't happen... */
- DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
- espstat_inc(esps_crypto);
- goto droponly;
- }
-
- NET_LOCK();
-
- tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto);
- if (tdb == NULL) {
- DPRINTF(("%s: TDB is expired while in crypto\n", __func__));
- espstat_inc(esps_notdb);
- goto baddone;
- }
-
- /* Check for crypto errors. */
- if (crp->crp_etype) {
- if (crp->crp_etype == EAGAIN) {
- /* Reset the session ID */
- if (tdb->tdb_cryptoid != 0)
- tdb->tdb_cryptoid = crp->crp_sid;
- NET_UNLOCK();
- crypto_dispatch(crp);
- return;
- }
- DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
- espstat_inc(esps_noxform);
- goto baddone;
- }
-
/* Release crypto descriptors. */
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
/* Call the IPsec input callback. */
- if (ipsp_process_done(m, tdb))
+ if (ipsp_process_done(m, tdb)) {
espstat_inc(esps_outfail);
- NET_UNLOCK();
- return;
+ return -1;
+ }
- baddone:
- NET_UNLOCK();
- droponly:
- m_freem(m);
- crypto_freereq(crp);
- free(tc, M_XDATA, 0);
+ return 0;
}
#define SEEN_SIZE howmany(TDB_REPLAYMAX, 32)
-/* $OpenBSD: ip_ipcomp.c,v 1.62 2018/07/11 09:07:59 mpi Exp $ */
+/* $OpenBSD: ip_ipcomp.c,v 1.63 2018/07/12 15:51:50 mpi Exp $ */
/*
* Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
#include "bpfilter.h"
-void ipcomp_output_cb(struct cryptop *);
-
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
#else
crp->crp_ilen = m->m_pkthdr.len; /* Total input length */
crp->crp_flags = CRYPTO_F_IMBUF;
crp->crp_buf = (caddr_t)m;
- crp->crp_callback = ipcomp_output_cb;
+ crp->crp_callback = ipsec_output_cb;
crp->crp_opaque = (caddr_t)tc;
crp->crp_sid = tdb->tdb_cryptoid;
}
/*
- * IPComp output callback, called directly from the crypto driver
+ * IPComp output callback.
*/
-void
-ipcomp_output_cb(struct cryptop *crp)
+int
+ipcomp_output_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m,
+ int ilen, int olen)
{
- struct tdb_crypto *tc;
- struct tdb *tdb;
- struct mbuf *m, *mo;
+ struct mbuf *mo;
int skip, rlen, roff;
u_int16_t cpi;
struct ip *ip;
char buf[INET6_ADDRSTRLEN];
#endif
- tc = (struct tdb_crypto *) crp->crp_opaque;
skip = tc->tc_skip;
- rlen = crp->crp_ilen - skip;
-
- m = (struct mbuf *) crp->crp_buf;
- if (m == NULL) {
- /* Shouldn't happen... */
- DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
- ipcompstat_inc(ipcomps_crypto);
- goto droponly;
- }
-
- NET_LOCK();
-
- tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto);
- if (tdb == NULL) {
- DPRINTF(("%s: TDB expired while in crypto\n", __func__));
- ipcompstat_inc(ipcomps_notdb);
- goto baddone;
- }
-
- /* Check for crypto errors. */
- if (crp->crp_etype) {
- if (crp->crp_etype == EAGAIN) {
- /* Reset the session ID */
- if (tdb->tdb_cryptoid != 0)
- tdb->tdb_cryptoid = crp->crp_sid;
- NET_UNLOCK();
- crypto_dispatch(crp);
- return;
- }
- DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
- ipcompstat_inc(ipcomps_noxform);
- goto baddone;
- }
+ rlen = ilen - skip;
/* Check sizes. */
- if (rlen < crp->crp_olen) {
+ if (rlen < olen) {
/* Compression was useless, we have lost time. */
ipcompstat_inc(ipcomps_minlen); /* misnomer, but like to count */
- crypto_freereq(crp);
- if (ipsp_process_done(m, tdb))
- ipcompstat_inc(ipcomps_outfail);
- NET_UNLOCK();
- return;
+ goto skiphdr;
}
/* Inject IPCOMP header */
ntohl(tdb->tdb_spi)));
ipcompstat_inc(ipcomps_nopf);
goto baddone;
- break;
}
+ skiphdr:
/* Release the crypto descriptor. */
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
- if (ipsp_process_done(m, tdb))
+ if (ipsp_process_done(m, tdb)) {
ipcompstat_inc(ipcomps_outfail);
- NET_UNLOCK();
- return;
+ return -1;
+ }
+ return 0;
baddone:
- NET_UNLOCK();
- droponly:
m_freem(m);
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
+ return -1;
}
-/* $OpenBSD: ip_ipsp.h,v 1.191 2018/07/11 09:07:59 mpi Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.192 2018/07/12 15:51:50 mpi Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
int ah_input(struct mbuf *, struct tdb *, int, int);
int ah_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int);
int ah_output(struct mbuf *, struct tdb *, struct mbuf **, int, int);
+int ah_output_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int,
+ int);
int ah_sysctl(int *, u_int, void *, size_t *, void *, size_t);
int ah4_input(struct mbuf **, int *, int, int);
int esp_input(struct mbuf *, struct tdb *, int, int);
int esp_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int);
int esp_output(struct mbuf *, struct tdb *, struct mbuf **, int, int);
+int esp_output_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int,
+ int);
int esp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
int esp4_input(struct mbuf **, int *, int, int);
int ipcomp_input(struct mbuf *, struct tdb *, int, int);
int ipcomp_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int);
int ipcomp_output(struct mbuf *, struct tdb *, struct mbuf **, int, int);
+int ipcomp_output_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int,
+ int);
int ipcomp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
int ipcomp4_input(struct mbuf **, int *, int, int);
#ifdef INET6
int ipsec_sysctl(int *, u_int, void *, size_t *, void *, size_t);
int ipsec_common_input(struct mbuf *, int, int, int, int, int);
void ipsec_input_cb(struct cryptop *);
+void ipsec_output_cb(struct cryptop *);
int ipsec_common_input_cb(struct mbuf *, struct tdb *, int, int);
int ipsec_delete_policy(struct ipsec_policy *);
ssize_t ipsec_hdrsz(struct tdb *);
-/* $OpenBSD: ip_output.c,v 1.346 2018/03/21 14:42:41 bluhm Exp $ */
+/* $OpenBSD: ip_output.c,v 1.347 2018/07/12 15:51:50 mpi Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
struct ifnet *encif;
#endif
struct ip *ip;
+ int error;
#if NPF > 0
/*
m->m_flags &= ~(M_MCAST | M_BCAST);
/* Callee frees mbuf */
- return ipsp_process_packet(m, tdb, AF_INET, 0);
+ error = ipsp_process_packet(m, tdb, AF_INET, 0);
+ if (error)
+ ipsecstat_inc(ipsec_odrops);
+ return error;
}
#endif /* IPSEC */
-/* $OpenBSD: ipsec_output.c,v 1.72 2018/06/04 12:13:01 bluhm Exp $ */
+/* $OpenBSD: ipsec_output.c,v 1.73 2018/07/12 15:51:50 mpi Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
*
#include <netinet/ip_ah.h>
#include <netinet/ip_esp.h>
#include <netinet/ip_ipcomp.h>
+
+#include <crypto/cryptodev.h>
#include <crypto/xform.h>
#ifdef ENCDEBUG
goto drop;
}
+ ipsecstat_add(ipsec_ouncompbytes, m->m_pkthdr.len);
+
/* Non expansion policy for IPCOMP */
if (tdb->tdb_sproto == IPPROTO_IPCOMP) {
if ((m->m_pkthdr.len - hlen) < tdb->tdb_compalgxform->minlen) {
return error;
}
+/*
+ * IPsec output callback, called directly by the crypto driver.
+ */
+void
+ipsec_output_cb(struct cryptop *crp)
+{
+ struct tdb_crypto *tc = (struct tdb_crypto *) crp->crp_opaque;
+ struct mbuf *m = (struct mbuf *) crp->crp_buf;
+ struct tdb *tdb;
+ int error, ilen, olen;
+
+ if (m == NULL) {
+ DPRINTF(("%s: bogus returned buffer from crypto\n", __func__));
+ ipsecstat_inc(ipsec_crypto);
+ goto droponly;
+ }
+
+ NET_LOCK();
+ tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto);
+ if (tdb == NULL) {
+ DPRINTF(("%s: TDB is expired while in crypto\n", __func__));
+ ipsecstat_inc(ipsec_notdb);
+ goto baddone;
+ }
+
+ /* Check for crypto errors. */
+ if (crp->crp_etype) {
+ if (crp->crp_etype == EAGAIN) {
+ /* Reset the session ID */
+ if (tdb->tdb_cryptoid != 0)
+ tdb->tdb_cryptoid = crp->crp_sid;
+ NET_UNLOCK();
+ crypto_dispatch(crp);
+ return;
+ }
+ DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
+ ipsecstat_inc(ipsec_noxform);
+ goto baddone;
+ }
+
+ olen = crp->crp_olen;
+ ilen = crp->crp_ilen;
+
+ /* Release crypto descriptors. */
+ crypto_freereq(crp);
+
+ switch (tdb->tdb_sproto) {
+ case IPPROTO_ESP:
+ error = esp_output_cb(tdb, tc, m, ilen, olen);
+ break;
+ case IPPROTO_AH:
+ error = ah_output_cb(tdb, tc, m, ilen, olen);
+ break;
+ case IPPROTO_IPCOMP:
+ error = ipcomp_output_cb(tdb, tc, m, ilen, olen);
+ break;
+ default:
+ panic("%s: unknown/unsupported security protocol %d",
+ __func__, tdb->tdb_sproto);
+ }
+
+ NET_UNLOCK();
+ if (error)
+ ipsecstat_inc(ipsec_odrops);
+ return;
+
+ baddone:
+ NET_UNLOCK();
+ droponly:
+ m_freem(m);
+ free(tc, M_XDATA, 0);
+ crypto_freereq(crp);
+ ipsecstat_inc(ipsec_odrops);
+}
+
/*
* Called by the IPsec output transform callbacks, to transmit the packet
* or do further processing, as necessary.
return ipsp_process_packet(m, tdb->tdb_onext,
tdb->tdb_dst.sa.sa_family, 0);
+ ipsecstat_inc(ipsec_opackets);
+ ipsecstat_add(ipsec_obytes, m->m_pkthdr.len);
+
#if NPF > 0
/* Add pf tag if requested. */
pf_tag_packet(m, tdb->tdb_tag, -1);
-/* $OpenBSD: ip6_output.c,v 1.237 2018/03/27 15:03:52 dhill Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.238 2018/07/12 15:51:50 mpi Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
#if NPF > 0
struct ifnet *encif;
#endif
+ int error;
#if NPF > 0
if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL ||
m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
/* Callee frees mbuf */
- return ipsp_process_packet(m, tdb, AF_INET6, tunalready);
+ error = ipsp_process_packet(m, tdb, AF_INET6, tunalready);
+ if (error)
+ ipsecstat_inc(ipsec_odrops);
+ return error;
}
#endif /* IPSEC */