summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Smith <mgsmith@netgate.com>2015-11-18 10:31:09 -0600
committerMatt Smith <mgsmith@netgate.com>2015-11-18 10:31:09 -0600
commitc1175cbf5395ed38605ca10bbcff1a545092aea0 (patch)
tree7823b503e976673da6e3bba227b3eeaa974cb9f2
parent03919d956ae4183a36e37e4dba34f3eee738abde (diff)
downloadFreeBSD-src-c1175cbf5395ed38605ca10bbcff1a545092aea0.zip
FreeBSD-src-c1175cbf5395ed38605ca10bbcff1a545092aea0.tar.gz
Importing pfSense patch ipsec-oneshot-dump.diff
-rw-r--r--sys/kern/uipc_sockbuf.c75
-rw-r--r--sys/netipsec/key.c42
-rw-r--r--sys/netipsec/keysock.c17
-rw-r--r--sys/netipsec/keysock.h1
-rw-r--r--sys/sys/sockbuf.h4
5 files changed, 116 insertions, 23 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index b66ea60..aac2ec7 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -439,15 +439,18 @@ sblastmbufchk(struct sockbuf *sb, const char *file, int line)
}
#endif /* SOCKBUF_DEBUG */
-#define SBLINKRECORD(sb, m0) do { \
+#define SBLINKRECORDCHAIN(sb, m0, mlast) do { \
SOCKBUF_LOCK_ASSERT(sb); \
if ((sb)->sb_lastrecord != NULL) \
(sb)->sb_lastrecord->m_nextpkt = (m0); \
else \
(sb)->sb_mb = (m0); \
- (sb)->sb_lastrecord = (m0); \
+ (sb)->sb_lastrecord = (mlast); \
} while (/*CONSTCOND*/0)
+#define SBLINKRECORD(sb, m0) \
+ SBLINKRECORDCHAIN(sb, m0, m0)
+
/*
* Append mbuf chain m to the last record in the socket buffer sb. The
* additional space associated the mbuf chain is recorded in sb. Empty mbufs
@@ -716,6 +719,74 @@ sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa,
}
int
+sbappendaddrchain_locked(sb, asa, m0)
+ struct sockbuf *sb;
+ const struct sockaddr *asa;
+ struct mbuf *m0;
+{
+ struct mbuf *m, *n, *n0, *nlast, *np;
+
+ SOCKBUF_LOCK_ASSERT(sb);
+
+#if MSIZE <= 256
+ if (asa->sa_len > MLEN)
+ return (0);
+#endif
+
+ n0 = np = nlast = NULL;
+ for (m = m0; m; m = m->m_nextpkt) {
+ MGET(n, M_DONTWAIT, MT_SONAME);
+ if (n == NULL)
+ goto outofmem;
+ n->m_len = asa->sa_len;
+ bcopy(asa, mtod(n, caddr_t), asa->sa_len);
+ n->m_next = m;
+
+ if (n0 == NULL)
+ n0 = n;
+ else
+ nlast->m_nextpkt = n;
+ nlast = n;
+
+ for (np = n; np->m_next; np = np->m_next)
+ sballoc(sb, np);
+ sballoc(sb, np);
+ }
+
+ SBLINKRECORDCHAIN(sb, n0, nlast);
+
+ sb->sb_mbtail = np;
+ SBLASTMBUFCHK(sb);
+
+ SBLASTRECORDCHK(sb);
+ return (1);
+
+outofmem:
+ while ((n = n0) != NULL) {
+ for (np = n; np; np = np->m_next)
+ sbfree(sb, np);
+
+ n0 = n->m_nextpkt;
+ m_free(n);
+ }
+ return (0);
+}
+
+int
+sbappendaddrchain(sb, asa, m0)
+ struct sockbuf *sb;
+ const struct sockaddr *asa;
+ struct mbuf *m0;
+{
+ int retval;
+
+ SOCKBUF_LOCK(sb);
+ retval = sbappendaddrchain_locked(sb, asa, m0);
+ SOCKBUF_UNLOCK(sb);
+ return (retval);
+}
+
+int
sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
struct mbuf *control)
{
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 4d6aa05..7df97e7 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -2466,7 +2466,7 @@ key_spddump(so, m, mhp)
struct secpolicy *sp;
int cnt;
u_int dir;
- struct mbuf *n;
+ struct mbuf *n, *rh, *rt;
IPSEC_ASSERT(so != NULL, ("null socket"));
IPSEC_ASSERT(m != NULL, ("null mbuf"));
@@ -2487,20 +2487,30 @@ key_spddump(so, m, mhp)
return key_senderror(so, m, ENOENT);
}
+ rh = rt = NULL;
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
LIST_FOREACH(sp, &V_sptree[dir], chain) {
--cnt;
n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt,
mhp->msg->sadb_msg_pid);
+ if (!n) {
+ SPTREE_UNLOCK();
+ m_freem(rh);
+ return key_senderror(so, m, ENOBUFS);
+ }
+
+ if (rt)
+ rt->m_nextpkt = n;
+ else
+ rh = n;
+ rt = n;
- if (n)
- key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
}
}
SPTREE_UNLOCK();
m_freem(m);
- return 0;
+ return key_sendup_mbuf(so, rh, KEY_SENDUP_ONESHOT);
}
static struct mbuf *
@@ -3387,7 +3397,7 @@ static struct mbuf *
key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype,
u_int32_t seq, u_int32_t pid)
{
- struct mbuf *result = NULL, *tres = NULL, *m;
+ struct mbuf *result = NULL, *m;
int i;
int dumporder[] = {
SADB_EXT_SA, SADB_X_EXT_SA2,
@@ -3409,7 +3419,7 @@ key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype,
goto fail;
result = m;
- for (i = sizeof(dumporder)/sizeof(dumporder[0]) - 1; i >= 0; i--) {
+ for (i = 0; i < sizeof(dumporder)/sizeof(dumporder[0]); i++) {
m = NULL;
switch (dumporder[i]) {
case SADB_EXT_SA:
@@ -3527,13 +3537,9 @@ key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype,
if (!m)
goto fail;
- if (tres)
- m_cat(m, tres);
- tres = m;
-
+ m_cat(result, m);
}
- m_cat(result, tres);
if (result->m_len < sizeof(struct sadb_msg)) {
result = m_pullup(result, sizeof(struct sadb_msg));
if (result == NULL)
@@ -3551,7 +3557,6 @@ key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype,
fail:
m_freem(result);
- m_freem(tres);
return NULL;
}
@@ -7137,7 +7142,7 @@ key_dump(so, m, mhp)
u_int8_t state;
int cnt;
struct sadb_msg *newmsg;
- struct mbuf *n;
+ struct mbuf *rh, *rt, *n;
IPSEC_ASSERT(so != NULL, ("null socket"));
IPSEC_ASSERT(m != NULL, ("null mbuf"));
@@ -7176,6 +7181,7 @@ key_dump(so, m, mhp)
/* send this to the userland, one at a time. */
newmsg = NULL;
+ rh = rt = NULL;
LIST_FOREACH(sah, &V_sahtree, chain) {
if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC
&& proto != sah->saidx.proto)
@@ -7184,6 +7190,7 @@ key_dump(so, m, mhp)
/* map proto to satype */
if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
SAHTREE_UNLOCK();
+ m_freem(rh);
ipseclog((LOG_DEBUG, "%s: there was invalid proto in "
"SAD.\n", __func__));
return key_senderror(so, m, EINVAL);
@@ -7198,16 +7205,21 @@ key_dump(so, m, mhp)
--cnt, mhp->msg->sadb_msg_pid);
if (!n) {
SAHTREE_UNLOCK();
+ m_freem(rh);
return key_senderror(so, m, ENOBUFS);
}
- key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
+ if (rt)
+ rt->m_nextpkt = n;
+ else
+ rh = n;
+ rt = n;
}
}
}
SAHTREE_UNLOCK();
m_freem(m);
- return 0;
+ return key_sendup_mbuf(so, rh, KEY_SENDUP_ONESHOT);
}
/*
diff --git a/sys/netipsec/keysock.c b/sys/netipsec/keysock.c
index 5a6b84a..2d01867 100644
--- a/sys/netipsec/keysock.c
+++ b/sys/netipsec/keysock.c
@@ -300,6 +300,16 @@ key_sendup_mbuf(so, m, target)
msg = mtod(m, struct sadb_msg *);
PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
}
+ if (target == KEY_SENDUP_ONESHOT) {
+ rp = sotorawcb(so);
+ if (!sbappendaddrchain(&rp->rcb_socket->so_rcv,
+ (struct sockaddr *) &key_src, m)) {
+ m_freem(m);
+ error = ENOBUFS;
+ }
+ sorwakeup(rp->rcb_socket);
+ return error;
+ }
mtx_lock(&rawcb_mtx);
LIST_FOREACH(rp, &V_rawcb_list, list)
{
@@ -355,12 +365,7 @@ key_sendup_mbuf(so, m, target)
return ENOBUFS;
}
- if ((error = key_sendup0(rp, n, 0)) != 0) {
- m_freem(m);
- mtx_unlock(&rawcb_mtx);
- return error;
- }
-
+ key_sendup0(rp, n, 0);
n = NULL;
}
diff --git a/sys/netipsec/keysock.h b/sys/netipsec/keysock.h
index e40f9c3..7b8fb81 100644
--- a/sys/netipsec/keysock.h
+++ b/sys/netipsec/keysock.h
@@ -61,6 +61,7 @@ struct pfkeystat {
#define KEY_SENDUP_ONE 0
#define KEY_SENDUP_ALL 1
#define KEY_SENDUP_REGISTERED 2
+#define KEY_SENDUP_ONESHOT 3
#ifdef _KERNEL
#include <sys/counter.h>
diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h
index 877b530..6b22d37 100644
--- a/sys/sys/sockbuf.h
+++ b/sys/sys/sockbuf.h
@@ -122,6 +122,10 @@ struct sockbuf {
void sbappend(struct sockbuf *sb, struct mbuf *m);
void sbappend_locked(struct sockbuf *sb, struct mbuf *m);
+int sbappendaddrchain(struct sockbuf *sb, const struct sockaddr *asa,
+ struct mbuf *m0);
+int sbappendaddrchain_locked(struct sockbuf *sb, const struct sockaddr *asa,
+ struct mbuf *m0);
void sbappendstream(struct sockbuf *sb, struct mbuf *m);
void sbappendstream_locked(struct sockbuf *sb, struct mbuf *m);
int sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa,
OpenPOWER on IntegriCloud