summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2015-08-17 13:53:27 -0300
committerRenato Botelho <renato@netgate.com>2015-08-17 13:53:27 -0300
commitd3b775b3db2819bebcac765dca33db7f8f5143c7 (patch)
tree016f0040db13d31ac4b832e67a967c9b7119c8c3
parentfce52da9925f213a049387e0accff1daa3ed0b20 (diff)
downloadFreeBSD-src-d3b775b3db2819bebcac765dca33db7f8f5143c7.zip
FreeBSD-src-d3b775b3db2819bebcac765dca33db7f8f5143c7.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 0c67347..d4f965a 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 17bbab6..3d709ed 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -2434,7 +2434,7 @@ key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *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"));
@@ -2455,20 +2455,30 @@ key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *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 *
@@ -3333,7 +3343,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,
@@ -3355,7 +3365,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:
@@ -3473,13 +3483,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)
@@ -3497,7 +3503,6 @@ key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype,
fail:
m_freem(result);
- m_freem(tres);
return NULL;
}
@@ -7058,7 +7063,7 @@ key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *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"));
@@ -7097,6 +7102,7 @@ key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *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)
@@ -7105,6 +7111,7 @@ key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *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);
@@ -7119,16 +7126,21 @@ key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *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 4b55e05..fa9f839 100644
--- a/sys/netipsec/keysock.c
+++ b/sys/netipsec/keysock.c
@@ -284,6 +284,16 @@ key_sendup_mbuf(struct socket *so, struct mbuf *m, int 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)
{
@@ -339,12 +349,7 @@ key_sendup_mbuf(struct socket *so, struct mbuf *m, int 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 86de261..944c94b 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 a31a4d3..456e2c9 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