Diff below adds & exports per-TDB counters via ipsecctl(8) and adds &
exports global IPsec counters via netstat(1). The goal of this diff
is to introduce a new framework to improve monitoring & error reporting
of IPsec traffic.
Here's an example of "# ipsecctl -s sa -v":
ipcomp tunnel from 10.188.106.17 to 10.188.106.70 spi 0x00008841 comp deflate
[bundle ipcomp to 10.188.106.70 spi 0x00008841 with esp to 10.188.106.70 spi
0x10018841]
sa: cpi 0x00008841 comp deflate
state mature replay 0 flags 0x4<tunnel>
[...]
counter:
4 input packets
1442 input bytes
4232 input bytes, decompressed
"# netstat -ss" now contains a new global 'ipsec' section:
ipsec:
24 active IPsec tunnels
427 input IPsec packets
578 output IPsec packets
94368 input bytes
...
Most of the kernel bits are refactoring required to count drops. I
tried to keep the changes as small as possible. But there's room
for sharing more code.
I'm using a new SADB extension to export counters to userland.
I'm of course really interested in adding/deleting/moving more counters.
But I'd like to continue working on that in-tree as the size of the diff
is starting to be big.
As discussed with bluhm@ the '{de,un}compressed' counters might
confusing/not correctly named for AH & ESP because once there header
removed the size of the packet is (obviously) smaller.
Full diff below, if needed I can send smaller diffs to review.
Comments? Oks?
Index: sbin/ipsecctl/pfkdump.c
===================================================================
RCS file: /cvs/src/sbin/ipsecctl/pfkdump.c,v
retrieving revision 1.46
diff -u -p -r1.46 pfkdump.c
--- sbin/ipsecctl/pfkdump.c 19 Apr 2017 15:59:38 -0000 1.46
+++ sbin/ipsecctl/pfkdump.c 3 Jul 2018 06:29:27 -0000
@@ -27,6 +27,8 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/sysctl.h>
+#include <sys/queue.h>
+
#include <net/pfkeyv2.h>
#include <netinet/ip_ipsp.h>
#include <netdb.h>
@@ -40,26 +42,27 @@
#include "ipsecctl.h"
#include "pfkey.h"
-static void print_proto(struct sadb_ext *, struct sadb_msg *);
-static void print_flow(struct sadb_ext *, struct sadb_msg *);
-static void print_supp(struct sadb_ext *, struct sadb_msg *);
-static void print_prop(struct sadb_ext *, struct sadb_msg *);
-static void print_sens(struct sadb_ext *, struct sadb_msg *);
-static void print_spir(struct sadb_ext *, struct sadb_msg *);
-static void print_policy(struct sadb_ext *, struct sadb_msg *);
-static void print_sa(struct sadb_ext *, struct sadb_msg *);
-static void print_addr(struct sadb_ext *, struct sadb_msg *);
-static void print_key(struct sadb_ext *, struct sadb_msg *);
-static void print_life(struct sadb_ext *, struct sadb_msg *);
-static void print_ident(struct sadb_ext *, struct sadb_msg *);
-static void print_udpenc(struct sadb_ext *, struct sadb_msg *);
-static void print_tag(struct sadb_ext *, struct sadb_msg *);
-static void print_tap(struct sadb_ext *, struct sadb_msg *);
-static void print_satype(struct sadb_ext *, struct sadb_msg *);
+static void print_proto(struct sadb_ext *, struct sadb_msg *, int);
+static void print_flow(struct sadb_ext *, struct sadb_msg *, int);
+static void print_supp(struct sadb_ext *, struct sadb_msg *, int);
+static void print_prop(struct sadb_ext *, struct sadb_msg *, int);
+static void print_sens(struct sadb_ext *, struct sadb_msg *, int);
+static void print_spir(struct sadb_ext *, struct sadb_msg *, int);
+static void print_policy(struct sadb_ext *, struct sadb_msg *, int);
+static void print_sa(struct sadb_ext *, struct sadb_msg *, int);
+static void print_addr(struct sadb_ext *, struct sadb_msg *, int);
+static void print_key(struct sadb_ext *, struct sadb_msg *, int);
+static void print_life(struct sadb_ext *, struct sadb_msg *, int);
+static void print_ident(struct sadb_ext *, struct sadb_msg *, int);
+static void print_udpenc(struct sadb_ext *, struct sadb_msg *, int);
+static void print_tag(struct sadb_ext *, struct sadb_msg *, int);
+static void print_tap(struct sadb_ext *, struct sadb_msg *, int);
+static void print_satype(struct sadb_ext *, struct sadb_msg *, int);
+static void print_counter(struct sadb_ext *, struct sadb_msg *, int);
static struct idname *lookup(struct idname *, u_int32_t);
static char *lookup_name(struct idname *, u_int32_t);
-static void print_ext(struct sadb_ext *, struct sadb_msg *);
+static void print_ext(struct sadb_ext *, struct sadb_msg *, int);
void pfkey_print_raw(u_int8_t *, ssize_t);
static char *print_flags(uint32_t);
@@ -69,7 +72,7 @@ struct sadb_ext *extensions[SADB_EXT_MAX
struct idname {
u_int32_t id;
char *name;
- void (*func)(struct sadb_ext *, struct sadb_msg *);
+ void (*func)(struct sadb_ext *, struct sadb_msg *, int);
};
struct idname ext_types[] = {
@@ -105,6 +108,7 @@ struct idname ext_types[] = {
{ SADB_X_EXT_TAG, "tag", print_tag },
{ SADB_X_EXT_TAP, "tap", print_tap },
{ SADB_X_EXT_SATYPE2, "satype2", print_satype },
+ { SADB_X_EXT_COUNTER, "counter", print_counter },
{ 0, NULL, NULL }
};
@@ -234,7 +238,7 @@ lookup_name(struct idname *tab, u_int32_
}
static void
-print_ext(struct sadb_ext *ext, struct sadb_msg *msg)
+print_ext(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct idname *entry;
@@ -245,7 +249,7 @@ print_ext(struct sadb_ext *ext, struct s
}
printf("\t%s: ", entry->name);
if (entry->func != NULL)
- (*entry->func)(ext, msg);
+ (*entry->func)(ext, msg, opts);
else
printf("type %u len %u",
ext->sadb_ext_type, ext->sadb_ext_len);
@@ -280,7 +284,7 @@ print_flags(uint32_t flags)
}
static void
-print_sa(struct sadb_ext *ext, struct sadb_msg *msg)
+print_sa(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_sa *sa = (struct sadb_sa *)ext;
@@ -300,7 +304,7 @@ print_sa(struct sadb_ext *ext, struct sa
/* ARGSUSED1 */
static void
-print_addr(struct sadb_ext *ext, struct sadb_msg *msg)
+print_addr(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_address *addr = (struct sadb_address *)ext;
struct sockaddr *sa;
@@ -332,7 +336,7 @@ print_addr(struct sadb_ext *ext, struct
/* ARGSUSED1 */
static void
-print_key(struct sadb_ext *ext, struct sadb_msg *msg)
+print_key(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_key *key = (struct sadb_key *)ext;
u_int8_t *data;
@@ -348,7 +352,7 @@ print_key(struct sadb_ext *ext, struct s
/* ARGSUSED1 */
static void
-print_life(struct sadb_ext *ext, struct sadb_msg *msg)
+print_life(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_lifetime *life = (struct sadb_lifetime *)ext;
@@ -360,7 +364,7 @@ print_life(struct sadb_ext *ext, struct
}
static void
-print_proto(struct sadb_ext *ext, struct sadb_msg *msg)
+print_proto(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_protocol *proto = (struct sadb_protocol *)ext;
@@ -376,7 +380,7 @@ print_proto(struct sadb_ext *ext, struct
/* ARGSUSED1 */
static void
-print_flow(struct sadb_ext *ext, struct sadb_msg *msg)
+print_flow(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_protocol *proto = (struct sadb_protocol *)ext;
char *dir = "unknown";
@@ -394,7 +398,7 @@ print_flow(struct sadb_ext *ext, struct
}
static void
-print_tag(struct sadb_ext *ext, struct sadb_msg *msg)
+print_tag(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_x_tag *stag = (struct sadb_x_tag *)ext;
char *p;
@@ -404,7 +408,7 @@ print_tag(struct sadb_ext *ext, struct s
}
static void
-print_tap(struct sadb_ext *ext, struct sadb_msg *msg)
+print_tap(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_x_tap *stap = (struct sadb_x_tap *)ext;
@@ -412,13 +416,35 @@ print_tap(struct sadb_ext *ext, struct s
}
static void
-print_satype(struct sadb_ext *ext, struct sadb_msg *msg)
+print_satype(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_protocol *proto = (struct sadb_protocol *)ext;
printf("type %s", lookup_name(sa_types, proto->sadb_protocol_proto));
}
+static void
+print_counter(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
+{
+ struct sadb_x_counter *scnt = (struct sadb_x_counter *)ext;
+
+ printf("\n");
+
+#define plural(n) ((n) != 1 ? "s" : "")
+#define p(f, m) if (scnt->f || opts & IPSECCTL_OPT_VERBOSE2) \
+ printf(m, scnt->f, plural(scnt->f))
+ p(sadb_x_cnt_ipackets, "\t\t%llu input packet%s\n");
+ p(sadb_x_cnt_opackets, "\t\t%llu output packet%s\n");
+ p(sadb_x_cnt_ibytes, "\t\t%llu input byte%s\n");
+ p(sadb_x_cnt_obytes, "\t\t%llu output byte%s\n");
+ p(sadb_x_cnt_idecompbytes, "\t\t%llu input byte%s, decompressed\n");
+ p(sadb_x_cnt_ouncompbytes, "\t\t%llu output byte%s, uncompressed\n");
+ p(sadb_x_cnt_idrops, "\t\t%llu packet%s dropped on input\n");
+ p(sadb_x_cnt_odrops, "\t\t%llu packet%s dropped on output\n");
+#undef p
+#undef plural
+}
+
static char *
alg_by_ext(u_int8_t ext_type, u_int8_t id)
{
@@ -444,7 +470,7 @@ print_alg(struct sadb_alg *alg, u_int8_t
/* ARGSUSED1 */
static void
-print_supp(struct sadb_ext *ext, struct sadb_msg *msg)
+print_supp(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_supported *supported = (struct sadb_supported *)ext;
struct sadb_alg *alg;
@@ -464,7 +490,7 @@ print_supp(struct sadb_ext *ext, struct
/* ARGSUSED1 */
static void
-print_comb(struct sadb_comb *comb, struct sadb_msg *msg)
+print_comb(struct sadb_comb *comb, struct sadb_msg *msg, int opts)
{
printf("\t\tauth %s min %u max %u\n"
"\t\tenc %s min %u max %u\n"
@@ -492,7 +518,7 @@ print_comb(struct sadb_comb *comb, struc
/* ARGSUSED1 */
static void
-print_prop(struct sadb_ext *ext, struct sadb_msg *msg)
+print_prop(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_prop *prop = (struct sadb_prop *)ext;
struct sadb_comb *comb;
@@ -502,12 +528,12 @@ print_prop(struct sadb_ext *ext, struct
(size_t)((u_int8_t *)comb - (u_int8_t *)ext) <
ext->sadb_ext_len * PFKEYV2_CHUNK;
comb++)
- print_comb(comb, msg);
+ print_comb(comb, msg, opts);
}
/* ARGSUSED1 */
static void
-print_sens(struct sadb_ext *ext, struct sadb_msg *msg)
+print_sens(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_sens *sens = (struct sadb_sens *)ext;
@@ -519,7 +545,7 @@ print_sens(struct sadb_ext *ext, struct
/* ARGSUSED1 */
static void
-print_spir(struct sadb_ext *ext, struct sadb_msg *msg)
+print_spir(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_spirange *spirange = (struct sadb_spirange *)ext;
@@ -529,7 +555,7 @@ print_spir(struct sadb_ext *ext, struct
/* ARGSUSED1 */
static void
-print_ident(struct sadb_ext *ext, struct sadb_msg *msg)
+print_ident(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_ident *ident = (struct sadb_ident *)ext;
@@ -540,7 +566,7 @@ print_ident(struct sadb_ext *ext, struct
/* ARGSUSED1 */
static void
-print_policy(struct sadb_ext *ext, struct sadb_msg *msg)
+print_policy(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_x_policy *x_policy = (struct sadb_x_policy *)ext;
@@ -549,7 +575,7 @@ print_policy(struct sadb_ext *ext, struc
/* ARGSUSED1 */
static void
-print_udpenc(struct sadb_ext *ext, struct sadb_msg *msg)
+print_udpenc(struct sadb_ext *ext, struct sadb_msg *msg, int opts)
{
struct sadb_x_udpencap *x_udpencap = (struct sadb_x_udpencap *)ext;
@@ -831,7 +857,7 @@ pfkey_print_sa(struct sadb_msg *msg, int
if (opts & IPSECCTL_OPT_VERBOSE) {
for (i = 0; i <= SADB_EXT_MAX; i++)
if (extensions[i])
- print_ext(extensions[i], msg);
+ print_ext(extensions[i], msg, opts);
}
fflush(stdout);
}
@@ -855,7 +881,7 @@ pfkey_monitor_sa(struct sadb_msg *msg, i
strerror(msg->sadb_msg_errno));
for (i = 0; i <= SADB_EXT_MAX; i++)
if (extensions[i])
- print_ext(extensions[i], msg);
+ print_ext(extensions[i], msg, opts);
fflush(stdout);
}
Index: sys/net/pfkeyv2.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2.c,v
retrieving revision 1.186
diff -u -p -r1.186 pfkeyv2.c
--- sys/net/pfkeyv2.c 25 Jun 2018 09:48:17 -0000 1.186
+++ sys/net/pfkeyv2.c 3 Jul 2018 06:29:27 -0000
@@ -727,7 +727,8 @@ pfkeyv2_get(struct tdb *sa, void **heade
void *p;
/* Find how much space we need */
- i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime);
+ i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime) +
+ sizeof(struct sadb_x_counter);
if (sa->tdb_soft_allocations || sa->tdb_soft_bytes ||
sa->tdb_soft_timeout || sa->tdb_soft_first_use)
@@ -888,6 +889,9 @@ pfkeyv2_get(struct tdb *sa, void **heade
export_tap(&p, sa);
}
#endif
+
+ headers[SADB_X_EXT_COUNTER] = p;
+ export_counter(&p, sa);
rval = 0;
Index: sys/net/pfkeyv2.h
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2.h,v
retrieving revision 1.79
diff -u -p -r1.79 pfkeyv2.h
--- sys/net/pfkeyv2.h 20 Nov 2017 10:56:51 -0000 1.79
+++ sys/net/pfkeyv2.h 3 Jul 2018 06:29:27 -0000
@@ -218,6 +218,19 @@ struct sadb_x_tap {
u_int32_t sadb_x_tap_unit;
};
+struct sadb_x_counter {
+ uint16_t sadb_x_cnt_len;
+ uint16_t sadb_x_cnt_exttype;
+ uint64_t sadb_x_cnt_ipackets; /* Input IPsec packets */
+ uint64_t sadb_x_cnt_opackets; /* Output IPsec packets */
+ uint64_t sadb_x_cnt_ibytes; /* Input bytes */
+ uint64_t sadb_x_cnt_obytes; /* Output bytes */
+ uint64_t sadb_x_cnt_idrops; /* Dropped on input */
+ uint64_t sadb_x_cnt_odrops; /* Dropped on output */
+ uint64_t sadb_x_cnt_idecompbytes; /* Input bytes, decompressed */
+ uint64_t sadb_x_cnt_ouncompbytes; /* Output bytes, uncompressed */
+};
+
#ifdef _KERNEL
#define SADB_X_GETSPROTO(x) \
( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\
@@ -262,7 +275,8 @@ struct sadb_x_tap {
#define SADB_X_EXT_TAG 33
#define SADB_X_EXT_TAP 34
#define SADB_X_EXT_SATYPE2 35
-#define SADB_EXT_MAX 35
+#define SADB_X_EXT_COUNTER 36
+#define SADB_EXT_MAX 36
/* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */
#define SADB_SATYPE_UNSPEC 0
@@ -396,6 +410,7 @@ void export_udpencap(void **, struct tdb
void export_tag(void **, struct tdb *);
void export_tap(void **, struct tdb *);
void export_satype(void **, struct tdb *);
+void export_counter(void **, struct tdb *);
void import_address(struct sockaddr *, struct sadb_address *);
void import_identities(struct ipsec_ids **, int, struct sadb_ident *,
Index: sys/net/pfkeyv2_convert.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2_convert.c,v
retrieving revision 1.63
diff -u -p -r1.63 pfkeyv2_convert.c
--- sys/net/pfkeyv2_convert.c 11 Jan 2018 16:02:31 -0000 1.63
+++ sys/net/pfkeyv2_convert.c 3 Jul 2018 06:29:27 -0000
@@ -898,3 +898,21 @@ export_satype(void **p, struct tdb *tdb)
sab->sadb_protocol_proto = tdb->tdb_satype;
*p += sizeof(struct sadb_protocol);
}
+
+void
+export_counter(void **p, struct tdb *tdb)
+{
+ struct sadb_x_counter *scnt = (struct sadb_x_counter *)*p;
+
+ scnt->sadb_x_cnt_len = sizeof(struct sadb_x_counter) / sizeof(uint64_t);
+ scnt->sadb_x_cnt_exttype = SADB_X_EXT_COUNTER;
+ scnt->sadb_x_cnt_ipackets = tdb->tdb_ipackets;
+ scnt->sadb_x_cnt_opackets = tdb->tdb_opackets;
+ scnt->sadb_x_cnt_ibytes = tdb->tdb_ibytes;
+ scnt->sadb_x_cnt_obytes = tdb->tdb_obytes;
+ scnt->sadb_x_cnt_idrops = tdb->tdb_idrops;
+ scnt->sadb_x_cnt_odrops = tdb->tdb_odrops;
+ scnt->sadb_x_cnt_idecompbytes = tdb->tdb_idecompbytes;
+ scnt->sadb_x_cnt_ouncompbytes = tdb->tdb_ouncompbytes;
+ *p += sizeof(struct sadb_x_counter);
+}
Index: sys/netinet/in.h
===================================================================
RCS file: /cvs/src/sys/netinet/in.h,v
retrieving revision 1.130
diff -u -p -r1.130 in.h
--- sys/netinet/in.h 7 Jun 2018 08:46:24 -0000 1.130
+++ sys/netinet/in.h 3 Jul 2018 06:29:27 -0000
@@ -660,6 +660,7 @@ struct ip_mreq {
#define IPCTL_IPPORT_HILASTAUTO 10
#define IPCTL_IPPORT_MAXQUEUE 11
#define IPCTL_ENCDEBUG 12
+#define IPCTL_IPSEC_STATS 13
#define IPCTL_IPSEC_EXPIRE_ACQUIRE 14 /* How long to wait for key mgmt. */
#define IPCTL_IPSEC_EMBRYONIC_SA_TIMEOUT 15 /* new SA lifetime */
#define IPCTL_IPSEC_REQUIRE_PFS 16
@@ -703,7 +704,7 @@ struct ip_mreq {
{ "porthilast", CTLTYPE_INT }, \
{ "maxqueue", CTLTYPE_INT }, \
{ "encdebug", CTLTYPE_INT }, \
- { 0, 0 }, \
+ { 0, 0 /* ipsecstat */ }, \
{ "ipsec-expire-acquire", CTLTYPE_INT }, \
{ "ipsec-invalid-life", CTLTYPE_INT }, \
{ "ipsec-pfs", CTLTYPE_INT }, \
@@ -746,7 +747,7 @@ struct ip_mreq {
&ipport_hilastauto, \
&ip_maxqueue, \
NULL /* encdebug */, \
- NULL, \
+ NULL /* ipsecstat */, \
NULL /* ipsec_expire_acquire */, \
NULL /* ipsec_keep_invalid */, \
NULL /* ipsec_require_pfs */, \
Index: sys/netinet/ip_ah.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ah.c,v
retrieving revision 1.140
diff -u -p -r1.140 ip_ah.c
--- sys/netinet/ip_ah.c 9 May 2018 12:48:59 -0000 1.140
+++ sys/netinet/ip_ah.c 3 Jul 2018 06:29:27 -0000
@@ -76,8 +76,6 @@
#define DPRINTF(x)
#endif
-void ah_output_cb(struct cryptop *);
-void ah_input_cb(struct cryptop *);
int ah_massage_headers(struct mbuf **, int, int, int, int);
const unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */
@@ -531,6 +529,7 @@ ah_input(struct mbuf *m, struct tdb *tdb
u_int32_t btsx, esn;
u_int8_t hl;
int error, rplen;
+ u_int64_t ibytes;
#ifdef ENCDEBUG
char buf[INET6_ADDRSTRLEN];
#endif
@@ -607,9 +606,10 @@ ah_input(struct mbuf *m, struct tdb *tdb
}
/* Update the counters. */
- tdb->tdb_cur_bytes +=
- (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
- ahstat_add(ahs_ibytes, m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
+ ibytes = (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
+ tdb->tdb_cur_bytes += ibytes;
+ tdb->tdb_ibytes += ibytes;
+ ahstat_add(ahs_ibytes, ibytes);
/* Hard expiration. */
if (tdb->tdb_flags & TDBF_BYTES &&
@@ -686,7 +686,7 @@ ah_input(struct mbuf *m, struct tdb *tdb
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_input_cb;
+ crp->crp_callback = ipsec_input_cb;
crp->crp_sid = tdb->tdb_cryptoid;
crp->crp_opaque = (caddr_t)tc;
@@ -707,62 +707,24 @@ ah_input(struct mbuf *m, struct tdb *tdb
return error;
}
-/*
- * AH input callback, called directly by the crypto driver.
- */
-void
-ah_input_cb(struct cryptop *crp)
+int
+ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen)
{
+ struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
int roff, rplen, skip, protoff;
- unsigned char calc[AH_ALEN_MAX];
- struct mbuf *m1, *m0, *m;
- struct auth_hash *ahx;
- struct tdb_crypto *tc = NULL;
- struct tdb *tdb;
u_int32_t btsx, esn;
caddr_t ptr;
+ unsigned char calc[AH_ALEN_MAX];
+ struct mbuf *m1, *m0;
#ifdef ENCDEBUG
char buf[INET6_ADDRSTRLEN];
#endif
- tc = (struct tdb_crypto *) crp->crp_opaque;
+ NET_ASSERT_LOCKED();
+
skip = tc->tc_skip;
protoff = tc->tc_protoff;
- 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", __func__));
- ahstat_inc(ahs_notdb);
- goto baddone;
- }
-
- ahx = (struct auth_hash *) tdb->tdb_authalgxform;
-
- /* 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;
- }
-
rplen = AH_FLENGTH + sizeof(u_int32_t);
/* Copy authenticator off the packet. */
@@ -906,19 +868,14 @@ ah_input_cb(struct cryptop *crp)
m->m_pkthdr.len -= rplen + ahx->authsize;
}
- crypto_freereq(crp); /* No longer needed. */
free(tc, M_XDATA, 0);
- ipsec_common_input_cb(m, tdb, skip, protoff);
- NET_UNLOCK();
- return;
+ return ipsec_common_input_cb(m, tdb, skip, protoff);
baddone:
- NET_UNLOCK();
- droponly:
m_freem(m);
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
+ return -1;
}
/*
@@ -1176,7 +1133,7 @@ ah_output(struct mbuf *m, struct tdb *td
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;
@@ -1198,52 +1155,14 @@ ah_output(struct mbuf *m, struct tdb *td
}
/*
- * 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
@@ -1252,18 +1171,13 @@ ah_output_cb(struct cryptop *crp)
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;
}
Index: sys/netinet/ip_esp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_esp.c,v
retrieving revision 1.154
diff -u -p -r1.154 ip_esp.c
--- sys/netinet/ip_esp.c 9 May 2018 16:00:28 -0000 1.154
+++ sys/netinet/ip_esp.c 3 Jul 2018 06:29:27 -0000
@@ -69,9 +69,6 @@
#include "bpfilter.h"
-void esp_output_cb(struct cryptop *);
-void esp_input_cb(struct cryptop *);
-
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
#else
@@ -341,6 +338,7 @@ esp_input(struct mbuf *m, struct tdb *td
struct tdb_crypto *tc = NULL;
int plen, alen, hlen, error;
u_int32_t btsx, esn;
+ u_int64_t ibytes;
#ifdef ENCDEBUG
char buf[INET6_ADDRSTRLEN];
#endif
@@ -418,8 +416,10 @@ esp_input(struct mbuf *m, struct tdb *td
}
/* Update the counters */
- tdb->tdb_cur_bytes += m->m_pkthdr.len - skip - hlen - alen;
- espstat_add(esps_ibytes, m->m_pkthdr.len - skip - hlen - alen);
+ ibytes = m->m_pkthdr.len - skip - hlen - alen;
+ tdb->tdb_cur_bytes += ibytes;
+ tdb->tdb_ibytes += ibytes;
+ espstat_add(esps_ibytes, ibytes);
/* Hard expiration */
if ((tdb->tdb_flags & TDBF_BYTES) &&
@@ -492,7 +492,7 @@ esp_input(struct mbuf *m, struct tdb *td
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_input_cb;
+ crp->crp_callback = ipsec_input_cb;
crp->crp_sid = tdb->tdb_cryptoid;
crp->crp_opaque = (caddr_t)tc;
@@ -531,59 +531,26 @@ esp_input(struct mbuf *m, struct tdb *td
/*
* ESP input callback, called directly by the crypto driver.
*/
-void
-esp_input_cb(struct cryptop *crp)
+int
+esp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int clen)
{
u_int8_t lastthree[3], aalg[AH_HMAC_MAX_HASHLEN];
int hlen, roff, skip, protoff;
- struct mbuf *m1, *mo, *m;
+ struct mbuf *m1, *mo;
struct auth_hash *esph;
- struct tdb_crypto *tc;
- struct tdb *tdb;
u_int32_t btsx, esn;
caddr_t ptr;
#ifdef ENCDEBUG
char buf[INET6_ADDRSTRLEN];
#endif
- tc = (struct tdb_crypto *) crp->crp_opaque;
skip = tc->tc_skip;
protoff = tc->tc_protoff;
- 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", __func__));
- espstat_inc(esps_notdb);
- goto baddone;
- }
+ NET_ASSERT_LOCKED();
esph = (struct auth_hash *) tdb->tdb_authalgxform;
- /* 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;
- }
-
/* If authentication was performed, check now. */
if (esph != NULL) {
/* Copy the authenticator from the packet */
@@ -749,20 +716,15 @@ esp_input_cb(struct cryptop *crp)
m_copyback(m, protoff, sizeof(u_int8_t), lastthree + 2, M_NOWAIT);
/* Release the crypto descriptors */
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
/* Back to generic IPsec input processing */
- ipsec_common_input_cb(m, tdb, skip, protoff);
- NET_UNLOCK();
- return;
+ return ipsec_common_input_cb(m, tdb, skip, protoff);
baddone:
- NET_UNLOCK();
- droponly:
m_freem(m);
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
+ return -1;
}
/*
@@ -1005,7 +967,7 @@ esp_output(struct mbuf *m, struct tdb *t
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;
@@ -1044,66 +1006,20 @@ esp_output(struct mbuf *m, struct tdb *t
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)
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.337
diff -u -p -r1.337 ip_input.c
--- sys/netinet/ip_input.c 21 May 2018 15:52:22 -0000 1.337
+++ sys/netinet/ip_input.c 3 Jul 2018 06:29:27 -0000
@@ -1623,6 +1623,7 @@ ip_sysctl(int *name, u_int namelen, void
return (error);
#ifdef IPSEC
case IPCTL_ENCDEBUG:
+ case IPCTL_IPSEC_STATS:
case IPCTL_IPSEC_EXPIRE_ACQUIRE:
case IPCTL_IPSEC_EMBRYONIC_SA_TIMEOUT:
case IPCTL_IPSEC_REQUIRE_PFS:
Index: sys/netinet/ip_ipcomp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipcomp.c,v
retrieving revision 1.61
diff -u -p -r1.61 ip_ipcomp.c
--- sys/netinet/ip_ipcomp.c 12 May 2018 09:38:33 -0000 1.61
+++ sys/netinet/ip_ipcomp.c 3 Jul 2018 06:29:27 -0000
@@ -56,9 +56,6 @@
#include "bpfilter.h"
-void ipcomp_output_cb(struct cryptop *);
-void ipcomp_input_cb(struct cryptop *);
-
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
#else
@@ -169,7 +166,7 @@ ipcomp_input(struct mbuf *m, struct tdb
crp->crp_ilen = m->m_pkthdr.len - (skip + hlen);
crp->crp_flags = CRYPTO_F_IMBUF;
crp->crp_buf = (caddr_t)m;
- crp->crp_callback = ipcomp_input_cb;
+ crp->crp_callback = ipsec_input_cb;
crp->crp_sid = tdb->tdb_cryptoid;
crp->crp_opaque = (caddr_t)tc;
@@ -184,46 +181,25 @@ ipcomp_input(struct mbuf *m, struct tdb
return crypto_dispatch(crp);
}
-/*
- * IPComp input callback, called directly by the crypto driver
- */
-void
-ipcomp_input_cb(struct cryptop *crp)
+int
+ipcomp_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int
clen)
{
- int skip, protoff, roff, hlen = IPCOMP_HLENGTH, clen;
+ int skip, protoff, roff, hlen = IPCOMP_HLENGTH;
u_int8_t nproto;
- struct mbuf *m, *m1, *mo;
- struct tdb_crypto *tc;
- struct tdb *tdb;
+ u_int64_t ibytes;
+ struct mbuf *m1, *mo;
struct ipcomp *ipcomp;
caddr_t addr;
#ifdef ENCDEBUG
char buf[INET6_ADDRSTRLEN];
#endif
- tc = (struct tdb_crypto *) crp->crp_opaque;
- skip = tc->tc_skip;
- protoff = tc->tc_protoff;
-
- 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", __func__));
- ipcompstat_inc(ipcomps_notdb);
- goto baddone;
- }
+ NET_ASSERT_LOCKED();
/* update the counters */
- tdb->tdb_cur_bytes += m->m_pkthdr.len - (skip + hlen);
+ ibytes = m->m_pkthdr.len - (skip + hlen);
+ tdb->tdb_cur_bytes += ibytes;
+ tdb->tdb_ibytes += ibytes;
ipcompstat_add(ipcomps_ibytes, m->m_pkthdr.len - (skip + hlen));
/* Hard expiration */
@@ -240,24 +216,8 @@ ipcomp_input_cb(struct cryptop *crp)
tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
}
- /* 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;
- }
-
- /* Length of data after processing */
- clen = crp->crp_olen;
+ skip = tc->tc_skip;
+ protoff = tc->tc_protoff;
/* In case it's not done already, adjust the size of the mbuf chain */
m->m_pkthdr.len = clen + hlen + skip;
@@ -331,23 +291,18 @@ ipcomp_input_cb(struct cryptop *crp)
}
/* Release the crypto descriptors */
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
/* Restore the Next Protocol field */
m_copyback(m, protoff, sizeof(u_int8_t), &nproto, M_NOWAIT);
/* Back to generic IPsec input processing */
- ipsec_common_input_cb(m, tdb, skip, protoff);
- NET_UNLOCK();
- return;
+ return ipsec_common_input_cb(m, tdb, skip, protoff);
baddone:
- NET_UNLOCK();
- droponly:
m_freem(m);
- crypto_freereq(crp);
free(tc, M_XDATA, 0);
+ return -1;
}
/*
@@ -513,7 +468,7 @@ ipcomp_output(struct mbuf *m, struct tdb
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;
@@ -526,14 +481,13 @@ ipcomp_output(struct mbuf *m, struct tdb
}
/*
- * 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;
@@ -545,51 +499,13 @@ ipcomp_output_cb(struct cryptop *crp)
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 baddone;
}
/* Inject IPCOMP header */
@@ -599,7 +515,7 @@ ipcomp_output_cb(struct cryptop *crp)
"IPCA %s/%08x\n", __func__, ipsp_address(&tdb->tdb_dst, buf,
sizeof(buf)), ntohl(tdb->tdb_spi)));
ipcompstat_inc(ipcomps_wrap);
- goto baddone;
+ return -1;
}
/* Initialize the IPCOMP header */
@@ -629,22 +545,19 @@ ipcomp_output_cb(struct cryptop *crp)
ntohl(tdb->tdb_spi)));
ipcompstat_inc(ipcomps_nopf);
goto baddone;
- break;
}
/* 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;
}
Index: sys/netinet/ip_ipip.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipip.c,v
retrieving revision 1.87
diff -u -p -r1.87 ip_ipip.c
--- sys/netinet/ip_ipip.c 9 Oct 2017 08:35:38 -0000 1.87
+++ sys/netinet/ip_ipip.c 3 Jul 2018 06:29:27 -0000
@@ -331,11 +331,9 @@ int
ipip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int dummy,
int dummy2)
{
- u_int8_t tp, otos;
-
- u_int8_t itos;
+ u_int8_t tp, otos, itos;
+ u_int64_t ibytes;
struct ip *ipo;
-
#ifdef INET6
struct ip6_hdr *ip6, *ip6o;
#endif /* INET6 */
@@ -525,21 +523,20 @@ ipip_output(struct mbuf *m, struct tdb *
*mp = m;
if (tdb->tdb_dst.sa.sa_family == AF_INET) {
+ ibytes = m->m_pkthdr.len - sizeof(struct ip);
if (tdb->tdb_xform->xf_type == XF_IP4)
- tdb->tdb_cur_bytes +=
- m->m_pkthdr.len - sizeof(struct ip);
+ tdb->tdb_cur_bytes += ibytes;
- ipipstat_add(ipips_obytes, m->m_pkthdr.len - sizeof(struct ip));
+ ipipstat_add(ipips_obytes, ibytes);
}
#ifdef INET6
if (tdb->tdb_dst.sa.sa_family == AF_INET6) {
+ ibytes = m->m_pkthdr.len - sizeof(struct ip6_hdr);
if (tdb->tdb_xform->xf_type == XF_IP4)
- tdb->tdb_cur_bytes +=
- m->m_pkthdr.len - sizeof(struct ip6_hdr);
+ tdb->tdb_cur_bytes += ibytes;
- ipipstat_add(ipips_obytes,
- m->m_pkthdr.len - sizeof(struct ip6_hdr));
+ ipipstat_add(ipips_obytes, ibytes);
}
#endif /* INET6 */
Index: sys/netinet/ip_ipsp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v
retrieving revision 1.231
diff -u -p -r1.231 ip_ipsp.c
--- sys/netinet/ip_ipsp.c 19 May 2018 12:34:35 -0000 1.231
+++ sys/netinet/ip_ipsp.c 3 Jul 2018 06:29:27 -0000
@@ -708,6 +708,8 @@ puttdb(struct tdb *tdbp)
tdbsrc[hashval] = tdbp;
tdb_count++;
+ if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == TDBF_TUNNELING)
+ ipsecstat_inc(ipsec_tunnels);
ipsec_last_added = time_second;
}
@@ -775,6 +777,11 @@ tdb_unlink(struct tdb *tdbp)
tdbp->tdb_snext = NULL;
tdb_count--;
+ if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) ==
+ TDBF_TUNNELING) {
+ ipsecstat_dec(ipsec_tunnels);
+ ipsecstat_inc(ipsec_prevtunnels);
+ }
}
void
Index: sys/netinet/ip_ipsp.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipsp.h,v
retrieving revision 1.189
diff -u -p -r1.189 ip_ipsp.h
--- sys/netinet/ip_ipsp.h 20 Nov 2017 14:14:26 -0000 1.189
+++ sys/netinet/ip_ipsp.h 3 Jul 2018 06:29:27 -0000
@@ -40,14 +40,10 @@
#ifndef _NETINET_IPSP_H_
#define _NETINET_IPSP_H_
-struct m_tag;
-
/* IPSP global definitions. */
#include <sys/types.h>
-#include <sys/queue.h>
#include <netinet/in.h>
-#include <net/radix.h>
union sockaddr_union {
struct sockaddr sa;
@@ -125,9 +121,79 @@ struct sockaddr_encap {
#define IPSP_DIRECTION_IN 0x1
#define IPSP_DIRECTION_OUT 0x2
+struct ipsecstat {
+ uint64_t ipsec_tunnels; /* Number of active tunnels */
+ uint64_t ipsec_prevtunnels; /* Past number of tunnels */
+ uint64_t ipsec_ipackets; /* Input IPsec packets */
+ uint64_t ipsec_opackets; /* Output IPsec packets */
+ uint64_t ipsec_ibytes; /* Input bytes */
+ uint64_t ipsec_obytes; /* Output bytes */
+ uint64_t ipsec_idecompbytes; /* Input bytes, decompressed */
+ uint64_t ipsec_ouncompbytes; /* Output bytes, uncompressed */
+ uint64_t ipsec_idrops; /* Dropped on input */
+ uint64_t ipsec_odrops; /* Dropped on output */
+ uint64_t ipsec_crypto; /* Crypto processing failure */
+ uint64_t ipsec_notdb; /* Expired while in crypto */
+ uint64_t ipsec_noxform; /* Crypto error */
+};
+
+struct tdb_data {
+ uint64_t tdd_ipackets; /* Input IPsec packets */
+ uint64_t tdd_opackets; /* Output IPsec packets */
+ uint64_t tdd_ibytes; /* Input bytes */
+ uint64_t tdd_obytes; /* Output bytes */
+ uint64_t tdd_idrops; /* Dropped on input */
+ uint64_t tdd_odrops; /* Dropped on output */
+ uint64_t tdd_idecompbytes; /* Input bytes, decompressed */
+ uint64_t tdd_ouncompbytes; /* Output bytes, uncompressed */
+};
+
#ifdef _KERNEL
+
#include <sys/timeout.h>
#include <sys/tree.h>
+#include <sys/queue.h>
+#include <net/radix.h>
+#include <sys/percpu.h>
+
+enum ipsec_counters {
+ ipsec_tunnels,
+ ipsec_prevtunnels,
+ ipsec_ipackets,
+ ipsec_opackets,
+ ipsec_ibytes,
+ ipsec_obytes,
+ ipsec_idecompbytes,
+ ipsec_ouncompbytes,
+ ipsec_idrops,
+ ipsec_odrops,
+ ipsec_crypto,
+ ipsec_notdb,
+ ipsec_noxform,
+ ipsec_ncounters
+};
+
+extern struct cpumem *ipseccounters;
+
+static inline void
+ipsecstat_inc(enum ipsec_counters c)
+{
+ counters_inc(ipseccounters, c);
+}
+
+static inline void
+ipsecstat_dec(enum ipsec_counters c)
+{
+ counters_dec(ipseccounters, c);
+}
+
+static inline void
+ipsecstat_add(enum ipsec_counters c, uint64_t v)
+{
+ counters_add(ipseccounters, c, v);
+}
+
+struct m_tag;
#define sen_data Sen.Data
#define sen_ip_src Sen.Sip4.Src
@@ -305,6 +371,7 @@ struct tdb { /* tunnel
descriptor blo
u_int64_t tdb_last_used; /* When was this SA last used */
u_int64_t tdb_last_marked;/* Last SKIPCRYPTO status change */
+ struct tdb_data tdb_data; /* stats about this TDB */
u_int64_t tdb_cryptoid; /* Crypto session ID */
u_int32_t tdb_spi; /* SPI */
@@ -349,6 +416,14 @@ struct tdb { /* tunnel
descriptor blo
TAILQ_HEAD(tdb_policy_head, ipsec_policy) tdb_policy_head;
TAILQ_ENTRY(tdb) tdb_sync_entry;
};
+#define tdb_ipackets tdb_data.tdd_ipackets
+#define tdb_opackets tdb_data.tdd_opackets
+#define tdb_ibytes tdb_data.tdd_ibytes
+#define tdb_obytes tdb_data.tdd_obytes
+#define tdb_idrops tdb_data.tdd_idrops
+#define tdb_odrops tdb_data.tdd_odrops
+#define tdb_idecompbytes tdb_data.tdd_idecompbytes
+#define tdb_ouncompbytes tdb_data.tdd_ouncompbytes
struct tdb_ident {
@@ -424,6 +499,7 @@ extern int ipsec_exp_first_use; /* seco
* Names for IPsec sysctl objects
*/
#define IPSEC_ENCDEBUG IPCTL_ENCDEBUG
/* 12 */
+#define IPSEC_STATS IPCTL_IPSEC_STATS
/* 13 */
#define IPSEC_EXPIRE_ACQUIRE IPCTL_IPSEC_EXPIRE_ACQUIRE /* 14 */
#define IPSEC_EMBRYONIC_SA_TIMEOUT IPCTL_IPSEC_EMBRYONIC_SA_TIMEOUT/* 15 */
#define IPSEC_REQUIRE_PFS IPCTL_IPSEC_REQUIRE_PFS /* 16 */
@@ -451,7 +527,7 @@ extern int ipsec_exp_first_use; /* seco
NULL, \
NULL, \
&encdebug, \
- NULL, \
+ NULL, /* ipsecstat */ \
&ipsec_expire_acquire, \
&ipsec_keep_invalid, \
&ipsec_require_pfs, \
@@ -482,6 +558,8 @@ extern struct comp_algo comp_algo_deflat
extern TAILQ_HEAD(ipsec_policy_head, ipsec_policy) ipsec_policy_head;
+struct cryptop;
+
/* Misc. */
#ifdef ENCDEBUG
const char *ipsp_address(union sockaddr_union *, char *, socklen_t);
@@ -524,7 +602,10 @@ int ah_attach(void);
int ah_init(struct tdb *, struct xformsw *, struct ipsecinit *);
int ah_zeroize(struct tdb *);
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);
@@ -540,7 +621,10 @@ int esp_attach(void);
int esp_init(struct tdb *, struct xformsw *, struct ipsecinit *);
int esp_zeroize(struct tdb *);
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);
@@ -555,7 +639,10 @@ int ipcomp_attach(void);
int ipcomp_init(struct tdb *, struct xformsw *, struct ipsecinit *);
int ipcomp_zeroize(struct tdb *);
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
@@ -592,7 +679,9 @@ void ipsp_ids_free(struct ipsec_ids *);
void ipsec_init(void);
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_common_input_cb(struct mbuf *, struct tdb *, 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 *);
void ipsec_adjust_mtu(struct mbuf *, u_int32_t);
Index: sys/netinet/ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.346
diff -u -p -r1.346 ip_output.c
--- sys/netinet/ip_output.c 21 Mar 2018 14:42:41 -0000 1.346
+++ sys/netinet/ip_output.c 3 Jul 2018 06:29:27 -0000
@@ -564,6 +564,7 @@ ip_output_ipsec_send(struct tdb *tdb, st
struct ifnet *encif;
#endif
struct ip *ip;
+ int error;
#if NPF > 0
/*
@@ -633,7 +634,12 @@ ip_output_ipsec_send(struct tdb *tdb, st
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);
+ tdb->tdb_odrops++;
+ }
+ return error;
}
#endif /* IPSEC */
Index: sys/netinet/ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.163
diff -u -p -r1.163 ipsec_input.c
--- sys/netinet/ipsec_input.c 14 May 2018 15:24:23 -0000 1.163
+++ sys/netinet/ipsec_input.c 3 Jul 2018 06:29:27 -0000
@@ -77,6 +77,9 @@
#include <net/if_enc.h>
+#include <crypto/cryptodev.h>
+#include <crypto/xform.h>
+
#include "bpfilter.h"
void ipsec_common_ctlinput(u_int, int, struct sockaddr *, void *, int);
@@ -112,6 +115,7 @@ int *ipcompctl_vars[IPCOMPCTL_MAXID] = I
struct cpumem *espcounters;
struct cpumem *ahcounters;
struct cpumem *ipcompcounters;
+struct cpumem *ipseccounters;
char ipsec_def_enc[20];
char ipsec_def_auth[20];
@@ -122,6 +126,7 @@ int *ipsecctl_vars[IPSEC_MAXID] = IPSECC
int esp_sysctl_espstat(void *, size_t *, void *);
int ah_sysctl_ahstat(void *, size_t *, void *);
int ipcomp_sysctl_ipcompstat(void *, size_t *, void *);
+int ipsec_sysctl_ipsecstat(void *, size_t *, void *);
void
ipsec_init(void)
@@ -129,6 +134,7 @@ ipsec_init(void)
espcounters = counters_alloc(esps_ncounters);
ahcounters = counters_alloc(ahs_ncounters);
ipcompcounters = counters_alloc(ipcomps_ncounters);
+ ipseccounters = counters_alloc(ipsec_ncounters);
strlcpy(ipsec_def_enc, IPSEC_DEFAULT_DEF_ENC, sizeof(ipsec_def_enc));
strlcpy(ipsec_def_auth, IPSEC_DEFAULT_DEF_AUTH, sizeof(ipsec_def_auth));
@@ -167,6 +173,8 @@ ipsec_common_input(struct mbuf *m, int s
NET_ASSERT_LOCKED();
+ ipsecstat_inc(ipsec_ipackets);
+ ipsecstat_add(ipsec_ibytes, m->m_pkthdr.len);
IPSEC_ISTAT(esps_input, ahs_input, ipcomps_input);
if (m == NULL) {
@@ -317,23 +325,110 @@ ipsec_common_input(struct mbuf *m, int s
tdbp->tdb_soft_first_use);
}
+ tdbp->tdb_ipackets++;
+ tdbp->tdb_ibytes += m->m_pkthdr.len;
+
/*
* Call appropriate transform and return -- callback takes care of
* everything else.
*/
error = (*(tdbp->tdb_xform->xf_input))(m, tdbp, skip, protoff);
+ if (error) {
+ ipsecstat_inc(ipsec_idrops);
+ tdbp->tdb_idrops++;
+ }
return error;
drop:
+ ipsecstat_inc(ipsec_idrops);
+ if (tdbp != NULL)
+ tdbp->tdb_idrops++;
m_freem(m);
return error;
}
+void
+ipsec_input_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 clen, error;
+
+ 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", __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;
+ }
+
+ /* Length of data after processing */
+ clen = crp->crp_olen;
+
+ /* Release the crypto descriptors */
+ crypto_freereq(crp);
+
+ switch (tdb->tdb_sproto) {
+ case IPPROTO_ESP:
+ error = esp_input_cb(tdb, tc, m, clen);
+ break;
+ case IPPROTO_AH:
+ error = ah_input_cb(tdb, tc, m, clen);
+ break;
+ case IPPROTO_IPCOMP:
+ error = ipcomp_input_cb(tdb, tc, m, clen);
+ break;
+ default:
+ panic("%s: unknown/unsupported security protocol %d",
+ __func__, tdb->tdb_sproto);
+ }
+
+ NET_UNLOCK();
+ if (error) {
+ ipsecstat_inc(ipsec_idrops);
+ tdb->tdb_idrops++;
+ }
+ return;
+
+ baddone:
+ NET_UNLOCK();
+ droponly:
+ ipsecstat_inc(ipsec_idrops);
+ if (tdb != NULL)
+ tdb->tdb_idrops++;
+ free(tc, M_XDATA, 0);
+ m_freem(m);
+ crypto_freereq(crp);
+}
+
/*
* IPsec input callback, called by the transform callback. Takes care of
* filtering and other sanity checks on the processed packet.
*/
-void
+int
ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff)
{
int af, sproto;
@@ -364,7 +459,7 @@ ipsec_common_input_cb(struct mbuf *m, st
if (m == NULL) {
/* The called routine will print a message if necessary */
IPSEC_ISTAT(esps_badkcr, ahs_badkcr, ipcomps_badkcr);
- return;
+ return -1;
}
/* Fix IPv4 header */
@@ -374,7 +469,7 @@ ipsec_common_input_cb(struct mbuf *m, st
__func__, ipsp_address(&tdbp->tdb_dst,
buf, sizeof(buf)), ntohl(tdbp->tdb_spi)));
IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops);
- return;
+ return -1;
}
ip = mtod(m, struct ip *);
@@ -389,7 +484,7 @@ ipsec_common_input_cb(struct mbuf *m, st
m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return;
+ return -1;
}
/* ipn will now contain the inner IPv4 header */
m_copydata(m, skip, sizeof(struct ip),
@@ -403,7 +498,7 @@ ipsec_common_input_cb(struct mbuf *m, st
m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return;
+ return -1;
}
/* ip6n will now contain the inner IPv6 header. */
m_copydata(m, skip, sizeof(struct ip6_hdr),
@@ -424,7 +519,7 @@ ipsec_common_input_cb(struct mbuf *m, st
buf, sizeof(buf)), ntohl(tdbp->tdb_spi)));
IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops);
- return;
+ return -1;
}
ip6 = mtod(m, struct ip6_hdr *);
@@ -439,7 +534,7 @@ ipsec_common_input_cb(struct mbuf *m, st
m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return;
+ return -1;
}
/* ipn will now contain the inner IPv4 header */
m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
@@ -451,7 +546,7 @@ ipsec_common_input_cb(struct mbuf *m, st
m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return;
+ return -1;
}
/* ip6n will now contain the inner IPv6 header. */
m_copydata(m, skip, sizeof(struct ip6_hdr),
@@ -475,7 +570,7 @@ ipsec_common_input_cb(struct mbuf *m, st
m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return;
+ return -1;
}
cksum = 0;
m_copyback(m, skip + offsetof(struct udphdr, uh_sum),
@@ -494,7 +589,7 @@ ipsec_common_input_cb(struct mbuf *m, st
m_freem(m);
IPSEC_ISTAT(esps_hdrops, ahs_hdrops,
ipcomps_hdrops);
- return;
+ return -1;
}
cksum = 0;
m_copyback(m, skip + offsetof(struct tcphdr, th_sum),
@@ -524,7 +619,7 @@ ipsec_common_input_cb(struct mbuf *m, st
m_freem(m);
DPRINTF(("%s: failed to get tag\n", __func__));
IPSEC_ISTAT(esps_hdrops, ahs_hdrops, ipcomps_hdrops);
- return;
+ return -1;
}
tdbi = (struct tdb_ident *)(mtag + 1);
@@ -566,6 +661,9 @@ ipsec_common_input_cb(struct mbuf *m, st
if (tdbp->tdb_flags & TDBF_TUNNELING)
m->m_flags |= M_TUNNEL;
+ ipsecstat_add(ipsec_idecompbytes, m->m_pkthdr.len);
+ tdbp->tdb_idecompbytes += m->m_pkthdr.len;
+
#if NBPFILTER > 0
if ((encif = enc_getif(tdbp->tdb_rdomain, tdbp->tdb_tap)) != NULL) {
encif->if_ipackets++;
@@ -597,20 +695,21 @@ ipsec_common_input_cb(struct mbuf *m, st
/* This is the enc0 interface unless for ipcomp. */
if ((ifp = if_get(m->m_pkthdr.ph_ifidx)) == NULL) {
m_freem(m);
- return;
+ return -1;
}
if (pf_test(af, PF_IN, ifp, &m) != PF_PASS) {
if_put(ifp);
m_freem(m);
- return;
+ return -1;
}
if_put(ifp);
if (m == NULL)
- return;
+ return -1;
}
#endif
/* Call the appropriate IPsec transform callback. */
ip_deliver(&m, &skip, prot, af);
+ return 0;
#undef IPSEC_ISTAT
}
@@ -639,6 +738,8 @@ ipsec_sysctl(int *name, u_int namelen, v
ipsec_def_comp, sizeof(ipsec_def_comp));
NET_UNLOCK();
return (error);
+ case IPCTL_IPSEC_STATS:
+ return (ipsec_sysctl_ipsecstat(oldp, oldlenp, newp));
default:
if (name[0] < IPSEC_MAXID) {
NET_LOCK();
@@ -760,6 +861,18 @@ ipcomp_sysctl_ipcompstat(void *oldp, siz
ipcomps_ncounters);
return (sysctl_rdstruct(oldp, oldlenp, newp, &ipcompstat,
sizeof(ipcompstat)));
+}
+
+int
+ipsec_sysctl_ipsecstat(void *oldp, size_t *oldlenp, void *newp)
+{
+ struct ipsecstat ipsecstat;
+
+ CTASSERT(sizeof(ipsecstat) == (ipsec_ncounters * sizeof(uint64_t)));
+ memset(&ipsecstat, 0, sizeof ipsecstat);
+ counters_read(ipseccounters, (uint64_t *)&ipsecstat, ipsec_ncounters);
+ return (sysctl_rdstruct(oldp, oldlenp, newp, &ipsecstat,
+ sizeof(ipsecstat)));
}
/* IPv4 AH wrapper. */
Index: sys/netinet/ipsec_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_output.c,v
retrieving revision 1.72
diff -u -p -r1.72 ipsec_output.c
--- sys/netinet/ipsec_output.c 4 Jun 2018 12:13:01 -0000 1.72
+++ sys/netinet/ipsec_output.c 3 Jul 2018 06:29:27 -0000
@@ -46,6 +46,8 @@
#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
@@ -358,6 +360,9 @@ ipsp_process_packet(struct mbuf *m, stru
goto drop;
}
+ ipsecstat_add(ipsec_ouncompbytes, m->m_pkthdr.len);
+ tdb->tdb_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) {
@@ -376,6 +381,85 @@ ipsp_process_packet(struct mbuf *m, stru
}
/*
+ * 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);
+ tdb->tdb_odrops++;
+ }
+ return;
+
+ baddone:
+ NET_UNLOCK();
+ droponly:
+ if (tdb != NULL)
+ tdb->tdb_odrops++;
+ 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.
*/
@@ -492,6 +576,11 @@ ipsp_process_done(struct mbuf *m, struct
tdbi->rdomain = tdb->tdb_rdomain;
m_tag_prepend(m, mtag);
+
+ ipsecstat_inc(ipsec_opackets);
+ ipsecstat_add(ipsec_obytes, m->m_pkthdr.len);
+ tdb->tdb_opackets++;
+ tdb->tdb_obytes += m->m_pkthdr.len;
/* If there's another (bundled) TDB to apply, do so. */
if (tdb->tdb_onext)
Index: sys/netinet6/ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.237
diff -u -p -r1.237 ip6_output.c
--- sys/netinet6/ip6_output.c 27 Mar 2018 15:03:52 -0000 1.237
+++ sys/netinet6/ip6_output.c 3 Jul 2018 06:29:27 -0000
@@ -2765,6 +2765,7 @@ ip6_output_ipsec_send(struct tdb *tdb, s
#if NPF > 0
struct ifnet *encif;
#endif
+ int error;
#if NPF > 0
if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL ||
@@ -2786,6 +2787,11 @@ ip6_output_ipsec_send(struct tdb *tdb, s
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);
+ tdb->tdb_odrops++;
+ }
+ return error;
}
#endif /* IPSEC */
Index: sys/sys/percpu.h
===================================================================
RCS file: /cvs/src/sys/sys/percpu.h,v
retrieving revision 1.7
diff -u -p -r1.7 percpu.h
--- sys/sys/percpu.h 23 Feb 2017 00:15:12 -0000 1.7
+++ sys/sys/percpu.h 3 Jul 2018 06:29:27 -0000
@@ -151,6 +151,17 @@ counters_inc(struct cpumem *cm, unsigned
}
static inline void
+counters_dec(struct cpumem *cm, unsigned int c)
+{
+ struct counters_ref ref;
+ uint64_t *counters;
+
+ counters = counters_enter(&ref, cm);
+ counters[c]--;
+ counters_leave(&ref, cm);
+}
+
+static inline void
counters_add(struct cpumem *cm, unsigned int c, uint64_t v)
{
struct counters_ref ref;
Index: usr.bin/netstat/inet.c
===================================================================
RCS file: /cvs/src/usr.bin/netstat/inet.c,v
retrieving revision 1.162
diff -u -p -r1.162 inet.c
--- usr.bin/netstat/inet.c 7 Nov 2017 16:51:23 -0000 1.162
+++ usr.bin/netstat/inet.c 3 Jul 2018 06:29:27 -0000
@@ -1010,6 +1010,42 @@ etherip_stats(char *name)
}
/*
+ * Dump IPsec statistics structure.
+ */
+void
+ipsec_stats(char *name)
+{
+ struct ipsecstat ipsecstat;
+ int mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_IPSEC_STATS };
+ size_t len = sizeof(ipsecstat);
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
+ &ipsecstat, &len, NULL, 0) == -1) {
+ if (errno != ENOPROTOOPT)
+ warn("%s", name);
+ return;
+ }
+
+ printf("%s:\n", name);
+#define p(f, m) if (ipsecstat.f || sflag <= 1) \
+ printf(m, ipsecstat.f, plural(ipsecstat.f))
+ p(ipsec_tunnels, "\t%llu active IPsec tunnel%s\n");
+ p(ipsec_prevtunnels, "\t%llu previous IPsec tunnel%s\n");
+ p(ipsec_ipackets, "\t%llu input IPsec packet%s\n");
+ p(ipsec_opackets, "\t%llu output IPsec packet%s\n");
+ p(ipsec_ibytes, "\t%llu input byte%s\n");
+ p(ipsec_obytes, "\t%llu output byte%s\n");
+ p(ipsec_idecompbytes, "\t%llu input byte%s, decompressed\n");
+ p(ipsec_ouncompbytes, "\t%llu output byte%s, uncompressed\n");
+ p(ipsec_idrops, "\t%llu packet%s dropped on input\n");
+ p(ipsec_odrops, "\t%llu packet%s dropped on output\n");
+ p(ipsec_crypto, "\t%llu packet%s that failed crypto processing\n");
+ p(ipsec_noxform, "\t%llu packet%s for which no XFORM was set in TDB
received\n");
+ p(ipsec_notdb, "\t%llu packet%s for which no TDB was found\n");
+#undef p
+}
+
+/*
* Dump ESP statistics structure.
*/
void
Index: usr.bin/netstat/main.c
===================================================================
RCS file: /cvs/src/usr.bin/netstat/main.c,v
retrieving revision 1.112
diff -u -p -r1.112 main.c
--- usr.bin/netstat/main.c 12 Aug 2017 03:21:02 -0000 1.112
+++ usr.bin/netstat/main.c 3 Jul 2018 06:29:27 -0000
@@ -77,6 +77,7 @@ struct protox {
{ ipip_stats, "ipencap", 0 },
{ tcp_stats, "tcp", IPPROTO_TCP },
{ udp_stats, "udp", IPPROTO_UDP },
+ { ipsec_stats, "ipsec", 0 },
{ esp_stats, "esp", 0 },
{ ah_stats, "ah", 0 },
{ etherip_stats,"etherip", 0 },
Index: usr.bin/netstat/netstat.h
===================================================================
RCS file: /cvs/src/usr.bin/netstat/netstat.h,v
retrieving revision 1.71
diff -u -p -r1.71 netstat.h
--- usr.bin/netstat/netstat.h 12 Aug 2017 03:21:02 -0000 1.71
+++ usr.bin/netstat/netstat.h 3 Jul 2018 06:29:27 -0000
@@ -92,6 +92,7 @@ void icmp_stats(char *);
void igmp_stats(char *);
void pim_stats(char *);
void ah_stats(char *);
+void ipsec_stats(char *);
void esp_stats(char *);
void ipip_stats(char *);
void carp_stats (char *);