diff options
author | Renato Botelho <renato@netgate.com> | 2015-08-17 13:53:27 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2015-08-17 13:53:27 -0300 |
commit | d3b775b3db2819bebcac765dca33db7f8f5143c7 (patch) | |
tree | 016f0040db13d31ac4b832e67a967c9b7119c8c3 /sys | |
parent | fce52da9925f213a049387e0accff1daa3ed0b20 (diff) | |
download | FreeBSD-src-d3b775b3db2819bebcac765dca33db7f8f5143c7.zip FreeBSD-src-d3b775b3db2819bebcac765dca33db7f8f5143c7.tar.gz |
Importing pfSense patch ipsec-oneshot-dump.diff
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/uipc_sockbuf.c | 75 | ||||
-rw-r--r-- | sys/netipsec/key.c | 42 | ||||
-rw-r--r-- | sys/netipsec/keysock.c | 17 | ||||
-rw-r--r-- | sys/netipsec/keysock.h | 1 | ||||
-rw-r--r-- | sys/sys/sockbuf.h | 4 |
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, |