Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Rework to make FAST_IPSEC PF_KEY dumps unicast and reli...
details: https://anonhg.NetBSD.org/src/rev/0dd3c5aa3bad
branches: trunk
changeset: 567011:0dd3c5aa3bad
user: jonathan <jonathan%NetBSD.org@localhost>
date: Thu May 27 19:19:00 2004 +0000
description:
Rework to make FAST_IPSEC PF_KEY dumps unicast and reliable:
Introduce new socket-layer function sbappendaddrchain() to
sys/kern/uipc_socket2.c: like sbappendaddr(), only takes a chain of
records and appends the entire chain in one pass. sbappendaddrchain()
also takes an `sbprio' argument, which indicates the caller requires
special `reliable' handling of the socket-buffer. `sbprio' is
described in sys/sys/socketvar.h, although (for now) the different
levels are not yet implemented.
Rework sys/netipsec/key.c PF_KEY DUMP responses to build a chain of
mbuf records, one record per dump response. Unicast the entire chain
to the requestor, with all-or-none semantics.
Changed files;
sys/socketvar.h kern/uipc_socket2.c netipsec/key.c
Reviewed by:
Jason Thorpe, Thor Lancelot Simon, post to tech-kern.
Todo: request pullup to 2.0 branch. Post-2.0, rework sysctl() API for
dumps to use new record-chain constructors. Actually implement
the distinct service levels in sbappendaddrchain() so we can use them
to make PF_KEY ACQUIRE messages more reliable.
diffstat:
sys/kern/uipc_socket2.c | 114 ++++++++++++++-
sys/netipsec/key.c | 355 +++++++++++++++++++++++++++++++++++------------
sys/sys/socketvar.h | 30 +++-
3 files changed, 400 insertions(+), 99 deletions(-)
diffs (truncated from 631 to 300 lines):
diff -r fb003d5f9e20 -r 0dd3c5aa3bad sys/kern/uipc_socket2.c
--- a/sys/kern/uipc_socket2.c Thu May 27 19:15:10 2004 +0000
+++ b/sys/kern/uipc_socket2.c Thu May 27 19:19:00 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_socket2.c,v 1.62 2004/04/19 03:44:46 christos Exp $ */
+/* $NetBSD: uipc_socket2.c,v 1.63 2004/05/27 19:19:00 jonathan Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.62 2004/04/19 03:44:46 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.63 2004/05/27 19:19:00 jonathan Exp $");
#include "opt_mbuftrace.h"
#include "opt_sb_max.h"
@@ -511,15 +511,22 @@
}
#endif /* SOCKBUF_DEBUG */
-#define SBLINKRECORD(sb, m0) \
+/*
+ * Link a chain of records onto a socket buffer
+ */
+#define SBLINKRECORDCHAIN(sb, m0, mlast) \
do { \
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
@@ -764,6 +771,105 @@
return (1);
}
+/*
+ * Helper for sbappendchainaddr: prepend a struct sockaddr* to
+ * an mbuf chain.
+ */
+static __inline struct mbuf *
+m_prepend_sockaddr(struct mbuf *m0, const struct sockaddr *asa)
+{
+ struct mbuf *m;
+ const int mlen = asa->sa_len;
+
+ /* only the first in each chain need be a pkthdr */
+ MGETHDR(m, M_DONTWAIT, MT_SONAME);
+ if (m == 0)
+ return (0);
+ MCLAIM(m, sb->sb_mowner);
+ KASSERT(mlen <= MLEN);
+
+ m->m_len = mlen;
+ bcopy((caddr_t)asa, mtod(m, caddr_t), mlen);
+ m->m_next = m0;
+ m->m_pkthdr.len = mlen + m0->m_pkthdr.len;
+
+ return m;
+}
+
+int
+sbappendaddrchain(struct sockbuf *sb, const struct sockaddr *asa,
+ struct mbuf *m0, int sbprio)
+{
+ int space;
+ struct mbuf *m, *n, *n0, *nlast;
+ int error;
+
+ /*
+ * XXX sbprio reserved for encoding priority of this* request:
+ * SB_PRIO_NONE --> honour normal sb limits
+ * SB_PRIO_ONESHOT_OVERFLOW --> if socket has any space,
+ * take whole chain. Intended for large requests
+ * that should be delivered atomically (all, or none).
+ * SB_PRIO_OVERDRAFT -- allow a small (2*MLEN) overflow
+ * over normal socket limits, for messages indicating
+ * buffer overflow in earlier normal/lower-priority messages
+ * SB_PRIO_BESTEFFORT --> ignore limits entirely.
+ * Intended for kernel-generated messages only.
+ * Up to generator to avoid total mbuf resource exhaustion.
+ */
+ (void)sbprio;
+
+ if (m0 && (m0->m_flags & M_PKTHDR) == 0)
+ panic("sbappendaddrchain");
+
+ space = sbspace(sb);
+
+#ifdef notyet
+ /*
+ * Enforce SB_PRIO_* limits as described above.
+ */
+#endif
+
+ n0 = NULL;
+ nlast = NULL;
+ for (m = m0; m; m = m->m_nextpkt) {
+ struct mbuf *np;
+
+ /* Prepend sockaddr to this record (m) of input chain m0 */
+ n = m_prepend_sockaddr(m, asa);
+ if (n == NULL) {
+ error = ENOBUFS;
+ goto bad;
+ }
+
+ /* Append record (asa+m) to end of new chain n0 */
+ if (n0 == NULL) {
+ n0 = n;
+ } else {
+ nlast->m_nextpkt = n;
+ }
+ /* Keep track of last record on new chain */
+ nlast = n;
+
+ for (np = n; np; np = np->m_next)
+ sballoc(sb, np);
+ }
+
+ /* Drop the entire chain of (asa+m) records onto the socket */
+ SBLINKRECORDCHAIN(sb, n0, nlast);
+ for (m = nlast; m->m_next; m = m->m_next)
+ ;
+ sb->sb_mbtail = m;
+
+ return (1);
+
+bad:
+ if (n)
+ m_freem(n);
+ return 0;
+}
+
+
int
sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control)
{
diff -r fb003d5f9e20 -r 0dd3c5aa3bad sys/netipsec/key.c
--- a/sys/netipsec/key.c Thu May 27 19:15:10 2004 +0000
+++ b/sys/netipsec/key.c Thu May 27 19:19:00 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: key.c,v 1.18 2004/05/26 23:16:25 jonathan Exp $ */
+/* $NetBSD: key.c,v 1.19 2004/05/27 19:19:00 jonathan Exp $ */
/* $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $ */
/* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.18 2004/05/26 23:16:25 jonathan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.19 2004/05/27 19:19:00 jonathan Exp $");
/*
* This code is referd to RFC 2367
@@ -385,6 +385,8 @@
const struct sadb_msghdr *));
static int key_spddump __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
+static struct mbuf * key_setspddump __P((int *errorp));
+static struct mbuf * key_setspddump_chain __P((int *errorp, int *lenp));
static struct mbuf *key_setdumpsp __P((struct secpolicy *,
u_int8_t, u_int32_t, u_int32_t));
static u_int key_getspreqmsglen __P((struct secpolicy *));
@@ -477,6 +479,8 @@
static int key_expire __P((struct secasvar *));
static int key_flush __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
+static struct mbuf *key_setdump_chain __P((u_int8_t req_satype, int *errorp,
+ int *lenp));
static int key_dump __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
static int key_promisc __P((struct socket *, struct mbuf *,
@@ -2390,6 +2394,61 @@
return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
}
+static struct sockaddr key_src = { 2, PF_KEY, };
+
+static struct mbuf *
+key_setspddump_chain(int *errorp, int *lenp)
+{
+ struct secpolicy *sp;
+ int cnt;
+ u_int dir;
+ struct mbuf *m, *n, *prev;
+ int totlen;
+
+ *lenp = 0;
+
+ /* search SPD entry and get buffer size. */
+ cnt = 0;
+ for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
+ LIST_FOREACH(sp, &sptree[dir], chain) {
+ cnt++;
+ }
+ }
+
+ if (cnt == 0) {
+ *errorp = ENOENT;
+ return (NULL);
+ }
+
+ m = NULL;
+ prev = m;
+ totlen = 0;
+ for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
+ LIST_FOREACH(sp, &sptree[dir], chain) {
+ --cnt;
+ n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, 0);
+
+ if (!n) {
+ *errorp = ENOBUFS;
+ if (m) m_freem(m);
+ return (NULL);
+ }
+
+ totlen += n->m_pkthdr.len;
+ if (!m) {
+ m = n;
+ } else {
+ prev->m_nextpkt = n;
+ }
+ prev = n;
+ }
+ }
+
+ *lenp = totlen;
+ *errorp = 0;
+ return (m);
+}
+
/*
* SADB_SPDDUMP processing
* receive
@@ -2402,44 +2461,65 @@
* m will always be freed.
*/
static int
-key_spddump(so, m, mhp)
+key_spddump(so, m0, mhp)
struct socket *so;
- struct mbuf *m;
+ struct mbuf *m0;
const struct sadb_msghdr *mhp;
{
- struct secpolicy *sp;
- int cnt;
- u_int dir;
struct mbuf *n;
+ int error, len;
+ int ok, s;
/* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
+ if (so == NULL || m0 == NULL || mhp == NULL || mhp->msg == NULL)
panic("key_spddump: NULL pointer is passed.\n");
- /* search SPD entry and get buffer size. */
- cnt = 0;
- for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
- LIST_FOREACH(sp, &sptree[dir], chain) {
- cnt++;
- }
- }
-
- if (cnt == 0)
- return key_senderror(so, m, ENOENT);
-
- for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
- LIST_FOREACH(sp, &sptree[dir], chain) {
- --cnt;
- n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt,
- mhp->msg->sadb_msg_pid);
-
- if (n)
- key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
- }
- }
-
- m_freem(m);
- return 0;
+
+ /*
+ * If the requestor has insufficient socket-buffer space
+ * for the entire chain, nobody gets any response to the DUMP.
+ * XXX For now, only the requestor ever gets anything.
+ * Moreover, if the requestor has any space at all, they receive
Home |
Main Index |
Thread Index |
Old Index