summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoritojun <itojun@NetBSD.org>2003-09-08 06:51:53 +0000
committeritojun <itojun@NetBSD.org>2003-09-08 06:51:53 +0000
commit8ca90bd4e4ea537a4470ab03eacc51f68bdfa40f (patch)
treeb769efe5a7fef8da81c50c4639946c967cd50a8f
parent140fe23a05ca652b72cf93da4acdbd3b8fd7908a (diff)
add /kern/ipsecsa and /kern/ipsecsp, which can be inspected by setkey(8).
it allows easier access to ipsecsa/sp. it works around problem where setkey -D does not work with large number of ipsec SAs due to socket buffer size.
-rw-r--r--sbin/mount_kernfs/mount_kernfs.823
-rw-r--r--sys/lkm/vfs/miscfs/kernfs/Makefile4
-rw-r--r--sys/miscfs/kernfs/files.kernfs3
-rw-r--r--sys/miscfs/kernfs/kernfs.h93
-rw-r--r--sys/miscfs/kernfs/kernfs_subr.c438
-rw-r--r--sys/miscfs/kernfs/kernfs_vfsops.c102
-rw-r--r--sys/miscfs/kernfs/kernfs_vnops.c753
-rw-r--r--sys/netkey/key.c65
-rw-r--r--sys/netkey/key.h6
9 files changed, 1177 insertions, 310 deletions
diff --git a/sbin/mount_kernfs/mount_kernfs.8 b/sbin/mount_kernfs/mount_kernfs.8
index c71054ddc99..407521cfe9a 100644
--- a/sbin/mount_kernfs/mount_kernfs.8
+++ b/sbin/mount_kernfs/mount_kernfs.8
@@ -1,4 +1,4 @@
-.\" $NetBSD: mount_kernfs.8,v 1.13 2003/08/07 10:04:28 agc Exp $
+.\" $NetBSD: mount_kernfs.8,v 1.14 2003/09/08 06:52:00 itojun Exp $
.\"
.\" Copyright (c) 1992, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
@@ -33,7 +33,7 @@
.\"
.\" @(#)mount_kernfs.8 8.2 (Berkeley) 3/27/94
.\"
-.Dd March 27, 1994
+.Dd September 8, 2003
.Dt MOUNT_KERNFS 8
.Os
.Sh NAME
@@ -83,6 +83,20 @@ The hostname can be changed by writing to this file.
A trailing newline will be stripped from the hostname being written.
.It Pa hz
the frequency of the system clock (decimal ASCII).
+.It Pa ipsecsa
+the directory contains IPsec security associations (SA) in
+.Dv PF_KEY
+format.
+Filenames are SPI in decimal number.
+The content of files can be inspected by using
+.Xr setkey 8 .
+.It Pa ipsecsp
+the directory contains IPsec security policies in
+.Dv PF_KEY
+format.
+Filenames are security policy ID in decimal number.
+The content of files can be inspected by using
+.Xr setkey 8 .
.It Pa loadavg
the 1, 5 and 15 minute load average in kernel fixed-point format.
The final integer is the fix-point scaling factor.
@@ -124,9 +138,11 @@ can be generated by running:
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
+.Xr ipsec 4 ,
.Xr fstab 5 ,
.Xr dmesg 8 ,
.Xr mount 8 ,
+.Xr setkey 8 ,
.Xr syslogd 8
.Sh HISTORY
The
@@ -135,3 +151,6 @@ utility first appeared in
.Bx 4.4 .
.Sh BUGS
This filesystem may not be NFS-exported.
+.Pp
+.Xr lkm 4
+version does not support IPsec-related files/directories.
diff --git a/sys/lkm/vfs/miscfs/kernfs/Makefile b/sys/lkm/vfs/miscfs/kernfs/Makefile
index 20d484becad..0d5157ff545 100644
--- a/sys/lkm/vfs/miscfs/kernfs/Makefile
+++ b/sys/lkm/vfs/miscfs/kernfs/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.10 2001/12/12 12:06:48 lukem Exp $
+# $NetBSD: Makefile,v 1.11 2003/09/08 06:51:59 itojun Exp $
.include "../Makefile.inc"
@@ -7,6 +7,6 @@
KMOD= kernfs
SRCS= lkminit_vfs.c
-SRCS+= kernfs_vfsops.c kernfs_vnops.c
+SRCS+= kernfs_vfsops.c kernfs_vnops.c kernfs_subr.c
.include <bsd.kmod.mk>
diff --git a/sys/miscfs/kernfs/files.kernfs b/sys/miscfs/kernfs/files.kernfs
index 089f915688a..30aa8921f1c 100644
--- a/sys/miscfs/kernfs/files.kernfs
+++ b/sys/miscfs/kernfs/files.kernfs
@@ -1,6 +1,7 @@
-# $NetBSD: files.kernfs,v 1.1 2002/04/16 23:14:07 thorpej Exp $
+# $NetBSD: files.kernfs,v 1.2 2003/09/08 06:51:53 itojun Exp $
deffs fs_kernfs.h KERNFS # XXX
+file miscfs/kernfs/kernfs_subr.c kernfs
file miscfs/kernfs/kernfs_vfsops.c kernfs
file miscfs/kernfs/kernfs_vnops.c kernfs
diff --git a/sys/miscfs/kernfs/kernfs.h b/sys/miscfs/kernfs/kernfs.h
index f0bfd79294b..f0cc001ae75 100644
--- a/sys/miscfs/kernfs/kernfs.h
+++ b/sys/miscfs/kernfs/kernfs.h
@@ -1,4 +1,4 @@
-/* $NetBSD: kernfs.h,v 1.17 2003/08/07 16:32:37 agc Exp $ */
+/* $NetBSD: kernfs.h,v 1.18 2003/09/08 06:51:53 itojun Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -37,36 +37,87 @@
#define _PATH_KERNFS "/kern" /* Default mountpoint */
#ifdef _KERNEL
-struct kernfs_mount {
- struct vnode *kf_root; /* Root node */
-};
+#include <sys/queue.h>
+
+/*
+ * The different types of node in a kernfs filesystem
+ */
+typedef enum {
+ Pkern, /* the filesystem itself (.) */
+ Proot, /* the filesystem root (..) */
+ Pnull, /* none aplicable */
+ Ptime, /* boottime */
+ Pint, /* integer */
+ Pstring, /* string */
+ Phostname, /* hostname */
+ Pavenrun, /* loadavg */
+ Pdevice, /* device file (rootdev/rrootdev) */
+ Pmsgbuf, /* msgbuf */
+ Pipsecsadir, /* ipsec security association (top dir) */
+ Pipsecspdir, /* ipsec security policy (top dir) */
+ Pipsecsa, /* ipsec security association entry */
+ Pipsecsp, /* ipsec security policy entry */
+} kfstype;
+/*
+ * control data for the kern file system.
+ */
struct kern_target {
- u_char kt_type;
- u_char kt_namlen;
- const char *kt_name;
- void *kt_data;
-#define KTT_NULL 1
-#define KTT_TIME 5
-#define KTT_INT 17
-#define KTT_STRING 31
-#define KTT_HOSTNAME 47
-#define KTT_AVENRUN 53
-#define KTT_DEVICE 71
-#define KTT_MSGBUF 89
- u_char kt_tag;
- u_char kt_vtype;
- mode_t kt_mode;
+ u_char kt_type;
+ u_char kt_namlen;
+ const char *kt_name;
+ void *kt_data;
+ kfstype kt_tag;
+ u_char kt_vtype;
+ mode_t kt_mode;
};
struct kernfs_node {
- const struct kern_target *kf_kt;
+ LIST_ENTRY(kernfs_node) kfs_hash; /* hash chain */
+ TAILQ_ENTRY(kernfs_node) kfs_list; /* flat list */
+ struct vnode *kfs_vnode; /* vnode associated with this pfsnode */
+ kfstype kfs_type; /* type of procfs node */
+ mode_t kfs_mode; /* mode bits for stat() */
+ long kfs_fileno; /* unique file id */
+ u_int32_t kfs_value; /* SA id or SP id (Pint) */
+ const struct kern_target *kfs_kt;
+ void *kfs_v; /* pointer to secasvar/secpolicy/mbuf */
+ long kfs_cookie; /* fileno cookie */
+};
+
+struct kernfs_mount {
+ TAILQ_HEAD(, kernfs_node) nodelist;
+ long fileno_cookie;
};
+#define UIO_MX 32
+
+#define KERNFS_FILENO(kt, typ, cookie) \
+ ((kt) ? 2 + ((kt) - &kern_targets[0]) \
+ : (((cookie) << 6) | ((typ) + nkern_targets)))
+
#define VFSTOKERNFS(mp) ((struct kernfs_mount *)((mp)->mnt_data))
-#define VTOKERN(vp) ((struct kernfs_node *)(vp)->v_data)
+#define VTOKERN(vp) ((struct kernfs_node *)(vp)->v_data)
+#define KERNFSTOV(kfs) ((kfs)->kfs_vnode)
+extern const struct kern_target kern_targets[];
+extern int nkern_targets;
extern int (**kernfs_vnodeop_p) __P((void *));
extern struct vfsops kernfs_vfsops;
extern dev_t rrootdev;
+
+struct secasvar;
+struct secpolicy;
+
+int kernfs_root __P((struct mount *, struct vnode **));
+
+void kernfs_hashinit __P((void));
+void kernfs_hashreinit __P((void));
+void kernfs_hashdone __P((void));
+int kernfs_freevp __P((struct vnode *));
+int kernfs_allocvp __P((struct mount *, struct vnode **, kfstype,
+ const struct kern_target *, u_int32_t));
+
+void kernfs_revoke_sa __P((struct secasvar *));
+void kernfs_revoke_sp __P((struct secpolicy *));
#endif /* _KERNEL */
diff --git a/sys/miscfs/kernfs/kernfs_subr.c b/sys/miscfs/kernfs/kernfs_subr.c
new file mode 100644
index 00000000000..920eb880ccd
--- /dev/null
+++ b/sys/miscfs/kernfs/kernfs_subr.c
@@ -0,0 +1,438 @@
+/* $NetBSD: kernfs_subr.c,v 1.1 2003/09/08 06:51:53 itojun Exp $ */
+
+/*
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kernfs_subr.c 8.6 (Berkeley) 5/14/95
+ */
+
+/*
+ * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved.
+ * Copyright (c) 1993 Jan-Simon Pendry
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kernfs_subr.c 8.6 (Berkeley) 5/14/95
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: kernfs_subr.c,v 1.1 2003/09/08 06:51:53 itojun Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_ipsec.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/mount.h>
+
+#include <miscfs/kernfs/kernfs.h>
+
+#ifdef IPSEC
+#include <sys/mbuf.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet6/ipsec.h>
+#include <netkey/keydb.h>
+#include <netkey/key.h>
+#endif
+
+void kernfs_hashins __P((struct kernfs_node *));
+void kernfs_hashrem __P((struct kernfs_node *));
+struct vnode *kernfs_hashget __P((kfstype, struct mount *, u_int32_t));
+
+static LIST_HEAD(kfs_hashhead, kernfs_node) *kfs_hashtbl;
+static u_long kfs_ihash; /* size of hash table - 1 */
+#define KFSVALUEHASH(v) ((v) & kfs_ihash)
+
+static struct lock kfs_hashlock;
+static struct simplelock kfs_hash_slock;
+
+#define ISSET(t, f) ((t) & (f))
+
+/*
+ * allocate a kfsnode/vnode pair. the vnode is
+ * referenced, and locked.
+ *
+ * the kfs_type, kfs_value and mount point uniquely
+ * identify a kfsnode. the mount point is needed
+ * because someone might mount this filesystem
+ * twice.
+ *
+ * all kfsnodes are maintained on a singly-linked
+ * list. new nodes are only allocated when they cannot
+ * be found on this list. entries on the list are
+ * removed when the vfs reclaim entry is called.
+ *
+ * a single lock is kept for the entire list. this is
+ * needed because the getnewvnode() function can block
+ * waiting for a vnode to become free, in which case there
+ * may be more than one process trying to get the same
+ * vnode. this lock is only taken if we are going to
+ * call getnewvnode, since the kernel itself is single-threaded.
+ *
+ * if an entry is found on the list, then call vget() to
+ * take a reference. this is done because there may be
+ * zero references to it and so it needs to removed from
+ * the vnode free list.
+ */
+int
+kernfs_allocvp(mp, vpp, kfs_type, kt, value)
+ struct mount *mp;
+ struct vnode **vpp;
+ kfstype kfs_type;
+ const struct kern_target *kt;
+ u_int32_t value;
+{
+ struct kernfs_node *kfs = NULL, *kfsp;
+ struct vnode *vp = NULL;
+ int error;
+ long *cookie;
+
+ do {
+ if ((*vpp = kernfs_hashget(kfs_type, mp, value)) != NULL)
+ return (0);
+ } while (lockmgr(&kfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
+
+ if (kfs_type == Pdevice) {
+ /* /kern/rootdev = look for device and obey */
+ /* /kern/rrootdev = look for device and obey */
+ dev_t *dp;
+ struct vnode *fvp;
+
+#ifdef DIAGNOSTIC
+ if (!kt)
+ panic("kernfs: kt == NULL for Pdevice");
+#endif
+ dp = kt->kt_data;
+ loop:
+ if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) {
+ lockmgr(&kfs_hashlock, LK_RELEASE, NULL);
+ return (ENOENT);
+ }
+ vp = fvp;
+ if (vget(fvp, LK_EXCLUSIVE))
+ goto loop;
+ *vpp = vp;
+ lockmgr(&kfs_hashlock, LK_RELEASE, NULL);
+ return (0);
+ }
+
+ if ((error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &vp)) != 0) {
+ *vpp = NULL;
+ lockmgr(&kfs_hashlock, LK_RELEASE, NULL);
+ return (error);
+ }
+
+ MALLOC(kfs, void *, sizeof(struct kernfs_node), M_TEMP, M_WAITOK);
+ memset(kfs, 0, sizeof(*kfs));
+ vp->v_data = kfs;
+ cookie = &(VFSTOKERNFS(mp)->fileno_cookie);
+again:
+ TAILQ_FOREACH(kfsp, &VFSTOKERNFS(mp)->nodelist, kfs_list) {
+ if (kfsp->kfs_cookie == *cookie) {
+ (*cookie) ++;
+ goto again;
+ }
+ if (TAILQ_NEXT(kfsp, kfs_list)) {
+ if (kfsp->kfs_cookie < *cookie &&
+ *cookie < TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie)
+ break;
+ if (kfsp->kfs_cookie + 1 <
+ TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie) {
+ *cookie = kfsp->kfs_cookie + 1;
+ break;
+ }
+ }
+ }
+
+ kfs->kfs_cookie = *cookie;
+
+ if (kfsp)
+ TAILQ_INSERT_AFTER(&VFSTOKERNFS(mp)->nodelist, kfsp, kfs,
+ kfs_list);
+ else
+ TAILQ_INSERT_TAIL(&VFSTOKERNFS(mp)->nodelist, kfs, kfs_list);
+
+ kfs->kfs_type = kfs_type;
+ kfs->kfs_vnode = vp;
+ kfs->kfs_fileno = KERNFS_FILENO(kt, kfs_type, kfs->kfs_cookie);
+ kfs->kfs_value = value;
+ kfs->kfs_kt = kt;
+
+ switch (kfs_type) {
+ case Pkern: /* /kern = dr-xr-xr-x */
+ kfs->kfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
+ vp->v_type = VDIR;
+ vp->v_flag = VROOT;
+ break;
+
+ case Pnull: /* /kern/?? = -r--r--r-- */
+ case Ptime: /* /kern/time = -r--r--r-- */
+ case Pint: /* /kern/?? = -r--r--r-- */
+ case Pstring: /* /kern/?? = -r--r--r-- */
+ case Pavenrun: /* /kern/loadavg = -r--r--r-- */
+ case Pmsgbuf: /* /kern/msgbuf = -r--r--r-- */
+ kfs->kfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
+ vp->v_type = VREG;
+ break;
+
+ case Pipsecsadir: /* /kern/ipsecsa = dr-x------ */
+ case Pipsecspdir: /* /kern/ipsecsp = dr-x------ */
+ kfs->kfs_mode = S_IRUSR|S_IXUSR;
+ vp->v_type = VDIR;
+ break;
+
+ case Pipsecsa: /* /kern/ipsecsa/N = -r-------- */
+ case Pipsecsp: /* /kern/ipsecsp/N = -r-------- */
+ kfs->kfs_mode = S_IRUSR;
+ vp->v_type = VREG;
+ break;
+
+ case Phostname: /* /kern/hostname = -rw------- */
+ kfs->kfs_mode = S_IRUSR|S_IWUSR;
+ vp->v_type = VREG;
+ break;
+
+ default:
+ panic("kernfs_allocvp");
+ }
+
+ kernfs_hashins(kfs);
+ uvm_vnp_setsize(vp, 0);
+ lockmgr(&kfs_hashlock, LK_RELEASE, NULL);
+
+ *vpp = vp;
+ return (0);
+}
+
+int
+kernfs_freevp(vp)
+ struct vnode *vp;
+{
+ struct kernfs_node *kfs = VTOKERN(vp);
+
+ kernfs_hashrem(kfs);
+ TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list);
+
+ FREE(vp->v_data, M_TEMP);
+ vp->v_data = 0;
+ return (0);
+}
+
+/*
+ * Initialize kfsnode hash table.
+ */
+void
+kernfs_hashinit()
+{
+
+ lockinit(&kfs_hashlock, PINOD, "kfs_hashlock", 0, 0);
+ kfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT,
+ M_WAITOK, &kfs_ihash);
+ simple_lock_init(&kfs_hash_slock);
+}
+
+void
+kernfs_hashreinit()
+{
+ struct kernfs_node *pp;
+ struct kfs_hashhead *oldhash, *hash;
+ u_long i, oldmask, mask, val;
+
+ hash = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, M_WAITOK,
+ &mask);
+
+ simple_lock(&kfs_hash_slock);
+ oldhash = kfs_hashtbl;
+ oldmask = kfs_ihash;
+ kfs_hashtbl = hash;
+ kfs_ihash = mask;
+ for (i = 0; i <= oldmask; i++) {
+ while ((pp = LIST_FIRST(&oldhash[i])) != NULL) {
+ LIST_REMOVE(pp, kfs_hash);
+ val = KFSVALUEHASH(pp->kfs_value);
+ LIST_INSERT_HEAD(&hash[val], pp, kfs_hash);
+ }
+ }
+ simple_unlock(&kfs_hash_slock);
+ hashdone(oldhash, M_UFSMNT);
+}
+
+/*
+ * Free kfsnode hash table.
+ */
+void
+kernfs_hashdone()
+{
+
+ hashdone(kfs_hashtbl, M_UFSMNT);
+}
+
+struct vnode *
+kernfs_hashget(type, mp, value)
+ kfstype type;
+ struct mount *mp;
+ u_int32_t value;
+{
+ struct kfs_hashhead *ppp;
+ struct kernfs_node *pp;
+ struct vnode *vp;
+
+loop:
+ simple_lock(&kfs_hash_slock);
+ ppp = &kfs_hashtbl[KFSVALUEHASH(value)];
+ LIST_FOREACH(pp, ppp, kfs_hash) {
+ vp = KERNFSTOV(pp);
+ if (pp->kfs_type == type && vp->v_mount == mp &&
+ pp->kfs_value == value) {
+ simple_lock(&vp->v_interlock);
+ simple_unlock(&kfs_hash_slock);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
+ goto loop;
+ return (vp);
+ }
+ }
+ simple_unlock(&kfs_hash_slock);
+ return (NULL);
+}
+
+/*
+ * Insert the kfsnode into the hash table and lock it.
+ */
+void
+kernfs_hashins(pp)
+ struct kernfs_node *pp;
+{
+ struct kfs_hashhead *ppp;
+
+ /* lock the kfsnode, then put it on the appropriate hash list */
+ lockmgr(&pp->kfs_vnode->v_lock, LK_EXCLUSIVE, (struct simplelock *)0);
+
+ simple_lock(&kfs_hash_slock);
+ ppp = &kfs_hashtbl[KFSVALUEHASH(pp->kfs_value)];
+ LIST_INSERT_HEAD(ppp, pp, kfs_hash);
+ simple_unlock(&kfs_hash_slock);
+}
+
+/*
+ * Remove the kfsnode from the hash table.
+ */
+void
+kernfs_hashrem(pp)
+ struct kernfs_node *pp;
+{
+ simple_lock(&kfs_hash_slock);
+ LIST_REMOVE(pp, kfs_hash);
+ simple_unlock(&kfs_hash_slock);
+}
+
+#ifdef IPSEC
+void
+kernfs_revoke_sa(sav)
+ struct secasvar *sav;
+{
+ struct kernfs_node *kfs, *pnext;
+ struct vnode *vp;
+ struct kfs_hashhead *ppp;
+ struct mbuf *m;
+
+ ppp = &kfs_hashtbl[KFSVALUEHASH(ntohl(sav->spi))];
+ for (kfs = LIST_FIRST(ppp); kfs; kfs = pnext) {
+ vp = KERNFSTOV(kfs);
+ pnext = LIST_NEXT(kfs, kfs_hash);
+ if (vp->v_usecount > 0 && kfs->kfs_type == Pipsecsa &&
+ kfs->kfs_value == ntohl(sav->spi)) {
+ m = key_setdumpsa_spi(sav->spi);
+ if (!m)
+ VOP_REVOKE(vp, REVOKEALL);
+ else
+ m_freem(m);
+ break;
+ }
+ }
+}
+
+void
+kernfs_revoke_sp(sp)
+ struct secpolicy *sp;
+{
+ struct kernfs_node *kfs, *pnext;
+ struct vnode *vp;
+ struct kfs_hashhead *ppp;
+
+ ppp = &kfs_hashtbl[KFSVALUEHASH(sp->id)];
+ for (kfs = LIST_FIRST(ppp); kfs; kfs = pnext) {
+ vp = KERNFSTOV(kfs);
+ pnext = LIST_NEXT(kfs, kfs_hash);
+ if (vp->v_usecount > 0 && kfs->kfs_type == Pipsecsa &&
+ kfs->kfs_value == sp->id)
+ VOP_REVOKE(vp, REVOKEALL);
+ }
+}
+#endif
diff --git a/sys/miscfs/kernfs/kernfs_vfsops.c b/sys/miscfs/kernfs/kernfs_vfsops.c
index ccdb925f87e..9d1195a9bc8 100644
--- a/sys/miscfs/kernfs/kernfs_vfsops.c
+++ b/sys/miscfs/kernfs/kernfs_vfsops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kernfs_vfsops.c,v 1.53 2003/08/07 16:32:37 agc Exp $ */
+/* $NetBSD: kernfs_vfsops.c,v 1.54 2003/09/08 06:51:54 itojun Exp $ */
/*
* Copyright (c) 1992, 1993, 1995
@@ -39,9 +39,9 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.53 2003/08/07 16:32:37 agc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.54 2003/09/08 06:51:54 itojun Exp $");
-#if defined(_KERNEL_OPT)
+#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
#endif
@@ -53,6 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.53 2003/08/07 16:32:37 agc Exp $
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/malloc.h>
+#include <sys/syslog.h>
#include <miscfs/specfs/specdev.h>
#include <miscfs/kernfs/kernfs.h>
@@ -62,13 +63,13 @@ MALLOC_DEFINE(M_KERNFSMNT, "kernfs mount", "kernfs mount structures");
dev_t rrootdev = NODEV;
void kernfs_init __P((void));
+void kernfs_reinit __P((void));
void kernfs_done __P((void));
void kernfs_get_rrootdev __P((void));
int kernfs_mount __P((struct mount *, const char *, void *,
struct nameidata *, struct proc *));
int kernfs_start __P((struct mount *, int, struct proc *));
int kernfs_unmount __P((struct mount *, int, struct proc *));
-int kernfs_root __P((struct mount *, struct vnode **));
int kernfs_statfs __P((struct mount *, struct statfs *, struct proc *));
int kernfs_quotactl __P((struct mount *, int, uid_t, caddr_t,
struct proc *));
@@ -87,6 +88,13 @@ kernfs_init()
#ifdef _LKM
malloc_type_attach(M_KERNFSMNT);
#endif
+ kernfs_hashinit();
+}
+
+void
+kernfs_reinit()
+{
+ kernfs_hashreinit();
}
void
@@ -95,6 +103,7 @@ kernfs_done()
#ifdef _LKM
malloc_type_detach(M_KERNFSMNT);
#endif
+ kernfs_hashdone();
}
void
@@ -111,13 +120,8 @@ kernfs_get_rrootdev()
if (rootdev == NODEV)
return;
rrootdev = devsw_blk2chr(rootdev);
- if (rrootdev != NODEV) {
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_mount: rootdev = %u.%u; rrootdev = %u.%u\n",
- major(rootdev), minor(rootdev), major(rrootdev), minor(rrootdev));
-#endif
+ if (rrootdev != NODEV)
return;
- }
rrootdev = NODEV;
printf("kernfs_get_rrootdev: no raw root device\n");
}
@@ -135,11 +139,11 @@ kernfs_mount(mp, path, data, ndp, p)
{
int error = 0;
struct kernfs_mount *fmp;
- struct vnode *rvp;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_mount(mp = %p)\n", mp);
-#endif
+ if (UIO_MX & (UIO_MX - 1)) {
+ log(LOG_ERR, "kernfs: invalid directory entry size");
+ return (EINVAL);
+ }
if (mp->mnt_flag & MNT_GETARGS)
return 0;
@@ -149,27 +153,17 @@ kernfs_mount(mp, path, data, ndp, p)
if (mp->mnt_flag & MNT_UPDATE)
return (EOPNOTSUPP);
- error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp);
- if (error)
- return (error);
-
MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
M_KERNFSMNT, M_WAITOK);
- rvp->v_type = VDIR;
- rvp->v_flag |= VROOT;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_mount: root vp = %p\n", rvp);
-#endif
- fmp->kf_root = rvp;
- mp->mnt_flag |= MNT_LOCAL;
+ memset(fmp, 0, sizeof(*fmp));
+ TAILQ_INIT(&fmp->nodelist);
+
mp->mnt_data = fmp;
+ mp->mnt_flag |= MNT_LOCAL;
vfs_getnewfsid(mp);
error = set_statfs_info(path, UIO_USERSPACE, "kernfs", UIO_SYSSPACE,
mp, p);
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
-#endif
kernfs_get_rrootdev();
return error;
@@ -193,36 +187,13 @@ kernfs_unmount(mp, mntflags, p)
{
int error;
int flags = 0;
- struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
-
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_unmount(mp = %p)\n", mp);
-#endif
- if (mntflags & MNT_FORCE)
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- /*
- * Clear out buffer cache. I don't think we
- * ever get anything cached at this level at the
- * moment, but who knows...
- */
- if (rootvp->v_usecount > 1)
- return (EBUSY);
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_unmount: calling vflush\n");
-#endif
- if ((error = vflush(mp, rootvp, flags)) != 0)
+ if ((error = vflush(mp, 0, flags)) != 0)
return (error);
-#ifdef KERNFS_DIAGNOSTIC
- vprint("kernfs root", rootvp);
-#endif
- /*
- * Clean out the old root vnode for reuse.
- */
- vrele(rootvp);
- vgone(rootvp);
/*
* Finally, throw away the kernfs_mount structure
*/
@@ -236,20 +207,9 @@ kernfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- struct vnode *vp;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_root(mp = %p)\n", mp);
-#endif
-
- /*
- * Return locked reference to root.
- */
- vp = VFSTOKERNFS(mp)->kf_root;
- VREF(vp);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- *vpp = vp;
- return (0);
+ /* setup "." */
+ return (kernfs_allocvp(mp, vpp, Pkern, &kern_targets[0], 0));
}
int
@@ -271,17 +231,13 @@ kernfs_statfs(mp, sbp, p)
struct proc *p;
{
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_statfs(mp = %p)\n", mp);
-#endif
-
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
sbp->f_blocks = 2; /* 1K to keep df happy */
sbp->f_bfree = 0;
sbp->f_bavail = 0;
- sbp->f_files = 0;
- sbp->f_ffree = 0;
+ sbp->f_files = 1024; /* XXX lie */
+ sbp->f_ffree = 128; /* XXX lie */
#ifdef COMPAT_09
sbp->f_type = 7;
#else
@@ -383,7 +339,7 @@ struct vfsops kernfs_vfsops = {
kernfs_fhtovp,
kernfs_vptofh,
kernfs_init,
- NULL,
+ kernfs_reinit,
kernfs_done,
kernfs_sysctl,
NULL, /* vfs_mountroot */
diff --git a/sys/miscfs/kernfs/kernfs_vnops.c b/sys/miscfs/kernfs/kernfs_vnops.c
index 86622034d38..a6bfc217855 100644
--- a/sys/miscfs/kernfs/kernfs_vnops.c
+++ b/sys/miscfs/kernfs/kernfs_vnops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kernfs_vnops.c,v 1.89 2003/08/07 16:32:37 agc Exp $ */
+/* $NetBSD: kernfs_vnops.c,v 1.90 2003/09/08 06:51:54 itojun Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -39,7 +39,11 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.89 2003/08/07 16:32:37 agc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.90 2003/09/08 06:51:54 itojun Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_ipsec.h"
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -60,6 +64,14 @@ __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.89 2003/08/07 16:32:37 agc Exp $"
#include <miscfs/genfs/genfs.h>
#include <miscfs/kernfs/kernfs.h>
+#ifdef IPSEC
+#include <sys/mbuf.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet6/ipsec.h>
+#include <netkey/key.h>
+#endif
+
#include <uvm/uvm_extern.h>
#define KSTRING 256 /* Largest I/O available via this filesystem */
@@ -68,41 +80,65 @@ __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.89 2003/08/07 16:32:37 agc Exp $"
#define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH)
#define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+#define UDIR_MODE (S_IRUSR|S_IXUSR)
+#define N(s) sizeof(s)-1, s
const struct kern_target kern_targets[] = {
/* NOTE: The name must be less than UIO_MX-16 chars in length */
-#define N(s) sizeof(s)-1, s
/* name data tag type ro/rw */
- { DT_DIR, N("."), 0, KTT_NULL, VDIR, DIR_MODE },
- { DT_DIR, N(".."), 0, KTT_NULL, VDIR, DIR_MODE },
- { DT_REG, N("boottime"), &boottime.tv_sec, KTT_INT, VREG, READ_MODE },
+ { DT_DIR, N("."), 0, Pkern, VDIR, DIR_MODE },
+ { DT_DIR, N(".."), 0, Proot, VDIR, DIR_MODE },
+ { DT_REG, N("boottime"), &boottime.tv_sec, Pint, VREG, READ_MODE },
/* XXX cast away const */
{ DT_REG, N("copyright"), (void *)copyright,
- KTT_STRING, VREG, READ_MODE },
- { DT_REG, N("hostname"), 0, KTT_HOSTNAME, VREG, WRITE_MODE },
- { DT_REG, N("hz"), &hz, KTT_INT, VREG, READ_MODE },
- { DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE },
- { DT_REG, N("msgbuf"), 0, KTT_MSGBUF, VREG, READ_MODE },
- { DT_REG, N("pagesize"), &uvmexp.pagesize, KTT_INT, VREG, READ_MODE },
- { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE },
+ Pstring, VREG, READ_MODE },
+ { DT_REG, N("hostname"), 0, Phostname, VREG, WRITE_MODE },
+ { DT_REG, N("hz"), &hz, Pint, VREG, READ_MODE },
+#ifdef IPSEC
+ { DT_DIR, N("ipsecsa"), 0, Pipsecsadir, VDIR, UDIR_MODE },
+ { DT_DIR, N("ipsecsp"), 0, Pipsecspdir, VDIR, UDIR_MODE },
+#endif
+ { DT_REG, N("loadavg"), 0, Pavenrun, VREG, READ_MODE },
+ { DT_REG, N("msgbuf"), 0, Pmsgbuf, VREG, READ_MODE },
+ { DT_REG, N("pagesize"), &uvmexp.pagesize, Pint, VREG, READ_MODE },
+ { DT_REG, N("physmem"), &physmem, Pint, VREG, READ_MODE },
#if 0
- { DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE },
+ { DT_DIR, N("root"), 0, Pnull, VDIR, DIR_MODE },
#endif
- { DT_BLK, N("rootdev"), &rootdev, KTT_DEVICE, VBLK, READ_MODE },
- { DT_CHR, N("rrootdev"), &rrootdev, KTT_DEVICE, VCHR, READ_MODE },
- { DT_REG, N("time"), 0, KTT_TIME, VREG, READ_MODE },
+ { DT_BLK, N("rootdev"), &rootdev, Pdevice, VBLK, READ_MODE },
+ { DT_CHR, N("rrootdev"), &rrootdev, Pdevice, VCHR, READ_MODE },
+ { DT_REG, N("time"), 0, Ptime, VREG, READ_MODE },
/* XXX cast away const */
{ DT_REG, N("version"), (void *)version,
- KTT_STRING, VREG, READ_MODE },
-#undef N
+ Pstring, VREG, READ_MODE },
+};
+#ifdef IPSEC
+const struct kern_target ipsecsa_targets[] = {
+/* NOTE: The name must be less than UIO_MX-16 chars in length */
+ /* name data tag type ro/rw */
+ { DT_DIR, N("."), 0, Pipsecsadir, VDIR, DIR_MODE },
+ { DT_DIR, N(".."), 0, Pkern, VDIR, DIR_MODE },
+};
+const struct kern_target ipsecsp_targets[] = {
+/* NOTE: The name must be less than UIO_MX-16 chars in length */
+ /* name data tag type ro/rw */
+ { DT_DIR, N("."), 0, Pipsecspdir, VDIR, DIR_MODE },
+ { DT_DIR, N(".."), 0, Pkern, VDIR, DIR_MODE },
};
-static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
+#endif
+#undef N
+int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
+#ifdef IPSEC
+int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
+int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
+#endif
+
int kernfs_lookup __P((void *));
#define kernfs_create genfs_eopnotsupp
#define kernfs_mknod genfs_eopnotsupp
-#define kernfs_open genfs_nullop
-#define kernfs_close genfs_nullop
+int kernfs_open __P((void *));
+int kernfs_close __P((void *));
int kernfs_access __P((void *));
int kernfs_getattr __P((void *));
int kernfs_setattr __P((void *));
@@ -141,8 +177,8 @@ int kernfs_pathconf __P((void *));
#define kernfs_bwrite genfs_eopnotsupp
#define kernfs_putpages genfs_putpages
-static int kernfs_xread __P((const struct kern_target *, int, char **, size_t, size_t *));
-static int kernfs_xwrite __P((const struct kern_target *, char *, size_t));
+static int kernfs_xread __P((struct kernfs_node *, int, char **, size_t, size_t *));
+static int kernfs_xwrite __P((const struct kernfs_node *, char *, size_t));
int (**kernfs_vnodeop_p) __P((void *));
const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
@@ -195,38 +231,44 @@ const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
{ &kernfs_vnodeop_p, kernfs_vnodeop_entries };
static int
-kernfs_xread(kt, off, bufp, len, wrlen)
- const struct kern_target *kt;
+kernfs_xread(kfs, off, bufp, len, wrlen)
+ struct kernfs_node *kfs;
int off;
char **bufp;
size_t len;
size_t *wrlen;
{
+ const struct kern_target *kt;
+#ifdef IPSEC
+ struct mbuf *m;
+#endif
+
+ kt = kfs->kfs_kt;
- switch (kt->kt_tag) {
- case KTT_TIME: {
+ switch (kfs->kfs_type) {
+ case Ptime: {
struct timeval tv;
microtime(&tv);
- sprintf(*bufp, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
+ snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
break;
}
- case KTT_INT: {
+ case Pint: {
int *ip = kt->kt_data;
- sprintf(*bufp, "%d\n", *ip);
+ snprintf(*bufp, len, "%d\n", *ip);
break;
}
- case KTT_STRING: {
+ case Pstring: {
char *cp = kt->kt_data;
*bufp = cp;
break;
}
- case KTT_MSGBUF: {
+ case Pmsgbuf: {
long n;
/*
@@ -260,26 +302,79 @@ kernfs_xread(kt, off, bufp, len, wrlen)
return (0);
}
- case KTT_HOSTNAME: {
+ case Phostname: {
char *cp = hostname;
int xlen = hostnamelen;
- if (xlen >= (len-2))
+ if (xlen >= (len - 2))
return (EINVAL);
memcpy(*bufp, cp, xlen);
(*bufp)[xlen] = '\n';
(*bufp)[xlen+1] = '\0';
+ len = strlen(*bufp);
break;
}
- case KTT_AVENRUN:
+ case Pavenrun:
averunnable.fscale = FSCALE;
- sprintf(*bufp, "%d %d %d %ld\n",
+ snprintf(*bufp, len, "%d %d %d %ld\n",
averunnable.ldavg[0], averunnable.ldavg[1],
averunnable.ldavg[2], averunnable.fscale);
break;
+#ifdef IPSEC
+ case Pipsecsa:
+ /*
+ * Note that SA configuration could be changed during the
+ * read operation, resulting in garbled output.
+ */
+ m = key_setdumpsa_spi(htonl(kfs->kfs_value));
+ if (!m)
+ return (ENOBUFS);
+ if (off >= m->m_pkthdr.len) {
+ *wrlen = 0;
+ m_freem(m);
+ return (0);
+ }
+ if (len > m->m_pkthdr.len - off)
+ len = m->m_pkthdr.len - off;
+ m_copydata(m, off, len, *bufp);
+ *wrlen = len;
+ m_freem(m);
+ return (0);
+
+ case Pipsecsp:
+ /*
+ * Note that SP configuration could be changed during the
+ * read operation, resulting in garbled output.
+ */
+ if (!kfs->kfs_v) {
+ struct secpolicy *sp;
+
+ sp = key_getspbyid(kfs->kfs_value);
+ if (sp)
+ kfs->kfs_v = sp;
+ else
+ return (ENOENT);
+ }
+ m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
+ SADB_X_SPDGET, 0, 0);
+ if (!m)
+ return (ENOBUFS);
+ if (off >= m->m_pkthdr.len) {
+ *wrlen = 0;
+ m_freem(m);
+ return (0);
+ }
+ if (len > m->m_pkthdr.len - off)
+ len = m->m_pkthdr.len - off;
+ m_copydata(m, off, len, *bufp);
+ *wrlen = len;
+ m_freem(m);
+ return (0);
+#endif
+
default:
*wrlen = 0;
return (0);
@@ -296,14 +391,14 @@ kernfs_xread(kt, off, bufp, len, wrlen)
}
static int
-kernfs_xwrite(kt, buf, len)
- const struct kern_target *kt;
+kernfs_xwrite(kfs, buf, len)
+ const struct kernfs_node *kfs;
char *buf;
size_t len;
{
- switch (kt->kt_tag) {
- case KTT_HOSTNAME:
+ switch (kfs->kfs_type) {
+ case Phostname:
if (buf[len-1] == '\n')
--len;
memcpy(hostname, buf, len);
@@ -334,14 +429,12 @@ kernfs_lookup(v)
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
const char *pname = cnp->cn_nameptr;
+ const struct kernfs_node *kfs;
const struct kern_target *kt;
- struct vnode *fvp;
int error, i, wantpunlock;
-
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_lookup(%p)\n", ap);
- printf("kernfs_lookup(dp = %p, vpp = %p, cnp = %p)\n", dvp, vpp, ap->a_cnp);
- printf("kernfs_lookup(%s)\n", pname);
+#ifdef IPSEC
+ char *ep;
+ u_int32_t id;
#endif
*vpp = NULLVP;
@@ -356,73 +449,158 @@ kernfs_lookup(v)
return (0);
}
- /*
- * This code only supports a flat directory, so we don't
- * need to worry about ..
- */
-
-#if 0
- if (cnp->cn_namelen == 4 && memcmp(pname, "root", 4) == 0) {
- *vpp = rootdir;
- VREF(rootdir);
- vn_lock(rootdir, LK_SHARED | LK_RETRY);
- return (0);
- }
-#endif
-
wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
+ kfs = VTOKERN(dvp);
+ switch (kfs->kfs_type) {
+ case Pkern:
+ /*
+ * Shouldn't get here with .. in the root node.
+ */
+ if (cnp->cn_flags & ISDOTDOT)
+ return (EIO);
+
+ for (i = 0; i < nkern_targets; i++) {
+ kt = &kern_targets[i];
+ if (cnp->cn_namelen == kt->kt_namlen &&
+ memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
+ goto found;
+ }
+ break;
- for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) {
- if (cnp->cn_namelen == kt->kt_namlen &&
- memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
- goto found;
- }
+ found:
+ error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
+ if ((error == 0) && wantpunlock) {
+ VOP_UNLOCK(dvp, 0);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ return (error);
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_lookup: i = %d, failed", i);
-#endif
+#ifdef IPSEC
+ case Pipsecsadir:
+ for (i = 0; i < nipsecsa_targets; i++) {
+ kt = &ipsecsa_targets[i];
+ if (cnp->cn_namelen == kt->kt_namlen &&
+ memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) {
+ error = kernfs_allocvp(dvp->v_mount, vpp,
+ kt->kt_tag, kt, 0);
+ if ((error == 0) && wantpunlock) {
+ VOP_UNLOCK(dvp, 0);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ return (error);
+ }
+ }
- return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
+ ep = NULL;
+ id = strtoul(pname, &ep, 10);
+ if (!ep || *ep || ep == pname)
+ break;
-found:
- if (kt->kt_tag == KTT_DEVICE) {
- dev_t *dp = kt->kt_data;
- loop:
- if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) {
- return (ENOENT);
+ error = kernfs_allocvp(dvp->v_mount, vpp, Pipsecsa, NULL, id);
+ if ((error == 0) && wantpunlock) {
+ VOP_UNLOCK(dvp, 0);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ return (error);
+
+ case Pipsecspdir:
+ for (i = 0; i < nipsecsp_targets; i++) {
+ kt = &ipsecsp_targets[i];
+ if (cnp->cn_namelen == kt->kt_namlen &&
+ memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) {
+ error = kernfs_allocvp(dvp->v_mount, vpp,
+ kt->kt_tag, kt, 0);
+ if ((error == 0) && wantpunlock) {
+ VOP_UNLOCK(dvp, 0);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ return (error);
+ }
}
- *vpp = fvp;
- if (vget(fvp, LK_EXCLUSIVE))
- goto loop;
- if (wantpunlock) {
+
+ ep = NULL;
+ id = strtoul(pname, &ep, 10);
+ if (!ep || *ep || ep == pname)
+ break;
+
+ error = kernfs_allocvp(dvp->v_mount, vpp, Pipsecsp, NULL, id);
+ if ((error == 0) && wantpunlock) {
VOP_UNLOCK(dvp, 0);
cnp->cn_flags |= PDIRUNLOCK;
}
- return (0);
+ return (error);
+#endif
+
+ default:
+ return (ENOTDIR);
}
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_lookup: allocate new vnode\n");
+ return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
+}
+
+int
+kernfs_open(v)
+ void *v;
+{
+ struct vop_open_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap = v;
+ struct kernfs_node *kfs = VTOKERN(ap->a_vp);
+#ifdef IPSEC
+ struct mbuf *m;
+ struct secpolicy *sp;
#endif
- error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);
- if (error) {
- return (error);
+
+ switch (kfs->kfs_type) {
+#ifdef IPSEC
+ case Pipsecsa:
+ m = key_setdumpsa_spi(htonl(kfs->kfs_value));
+ if (m) {
+ m_freem(m);
+ return (0);
+ } else
+ return (ENOENT);
+
+ case Pipsecsp:
+ sp = key_getspbyid(kfs->kfs_value);
+ if (sp) {
+ kfs->kfs_v = sp;
+ return (0);
+ } else
+ return (ENOENT);
+#endif
+
+ default:
+ return (0);
}
+}
- MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP,
- M_WAITOK);
- VTOKERN(fvp)->kf_kt = kt;
- fvp->v_type = kt->kt_vtype;
- vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY);
- *vpp = fvp;
+int
+kernfs_close(v)
+ void *v;
+{
+ struct vop_close_args /* {
+ struct vnode *a_vp;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap = v;
+ struct kernfs_node *kfs = VTOKERN(ap->a_vp);
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_lookup: newvp = %p\n", fvp);
+ switch (kfs->kfs_type) {
+#ifdef IPSEC
+ case Pipsecsp:
+ key_freesp((struct secpolicy *)kfs->kfs_v);
+ break;
#endif
- if (wantpunlock) {
- VOP_UNLOCK(dvp, 0);
- cnp->cn_flags |= PDIRUNLOCK;
+
+ default:
+ break;
}
+
return (0);
}
@@ -436,18 +614,14 @@ kernfs_access(v)
struct ucred *a_cred;
struct proc *a_p;
} */ *ap = v;
- struct vnode *vp = ap->a_vp;
- mode_t mode;
+ struct vattr va;
+ int error;
- if (vp->v_flag & VROOT) {
- mode = DIR_MODE;
- } else {
- const struct kern_target *kt = VTOKERN(vp)->kf_kt;
- mode = kt->kt_mode;
- }
+ if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)
+ return (error);
- return (vaccess(vp->v_type, mode, (uid_t)0, (gid_t)0, ap->a_mode,
- ap->a_cred));
+ return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
+ ap->a_mode, ap->a_cred));
}
int
@@ -460,16 +634,19 @@ kernfs_getattr(v)
struct ucred *a_cred;
struct proc *a_p;
} */ *ap = v;
- struct vnode *vp = ap->a_vp;
+ struct kernfs_node *kfs = VTOKERN(ap->a_vp);
struct vattr *vap = ap->a_vap;
int error = 0;
char strbuf[KSTRING], *buf;
+ size_t nread, total;
- memset((caddr_t) vap, 0, sizeof(*vap));
- vattr_null(vap);
+ VATTR_NULL(vap);
+ vap->va_type = ap->a_vp->v_type;
vap->va_uid = 0;
vap->va_gid = 0;
- vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
+ vap->va_mode = kfs->kfs_mode;
+ vap->va_fileid = kfs->kfs_fileno;
+ vap->va_flags = 0;
vap->va_size = 0;
vap->va_blocksize = DEV_BSIZE;
/*
@@ -484,38 +661,53 @@ kernfs_getattr(v)
vap->va_rdev = 0;
vap->va_bytes = 0;
- if (vp->v_flag & VROOT) {
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_getattr: stat rootdir\n");
-#endif
- vap->va_type = VDIR;
- vap->va_mode = DIR_MODE;
- vap->va_nlink = 2;
- vap->va_fileid = 2;
- vap->va_size = DEV_BSIZE;
- } else {
- const struct kern_target *kt = VTOKERN(vp)->kf_kt;
- size_t nread, total;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_getattr: stat target %s\n", kt->kt_name);
+ switch (kfs->kfs_type) {
+ case Pkern:
+ vap->va_nlink = 4;
+ vap->va_bytes = vap->va_size = DEV_BSIZE;
+ break;
+
+ case Proot:
+ vap->va_nlink = 1;
+ vap->va_bytes = vap->va_size = DEV_BSIZE;
+ break;
+
+ case Pnull:
+ case Ptime:
+ case Pint:
+ case Pstring:
+ case Phostname:
+ case Pavenrun:
+ case Pdevice:
+ case Pmsgbuf:
+#ifdef IPSEC
+ case Pipsecsa:
+ case Pipsecsp:
#endif
- vap->va_type = kt->kt_vtype;
- vap->va_mode = kt->kt_mode;
vap->va_nlink = 1;
- vap->va_fileid = 1 + (kt - kern_targets);
total = 0;
do {
buf = strbuf;
- error = kernfs_xread(kt, total, &buf,
- sizeof(strbuf), &nread);
+ error = kernfs_xread(kfs, total, &buf,
+ sizeof(strbuf), &nread);
total += nread;
} while (error == 0 && nread != 0);
- vap->va_size = total;
- }
+ vap->va_bytes = vap->va_size = total;
+ break;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_getattr: return error %d\n", error);
+#ifdef IPSEC
+ case Pipsecsadir:
+ case Pipsecspdir:
+ vap->va_nlink = 2;
+ vap->va_bytes = vap->va_size = DEV_BSIZE;
+ break;
#endif
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
return (error);
}
@@ -524,6 +716,7 @@ int
kernfs_setattr(v)
void *v;
{
+
/*
* Silently ignore attribute changes.
* This allows for open with truncate to have no
@@ -543,26 +736,19 @@ kernfs_read(v)
int a_ioflag;
struct ucred *a_cred;
} */ *ap = v;
- struct vnode *vp = ap->a_vp;
struct uio *uio = ap->a_uio;
- const struct kern_target *kt;
+ struct kernfs_node *kfs = VTOKERN(ap->a_vp);
char strbuf[KSTRING], *buf;
off_t off;
size_t len;
int error;
- if (vp->v_type == VDIR)
+ if (ap->a_vp->v_type == VDIR)
return (EOPNOTSUPP);
- kt = VTOKERN(vp)->kf_kt;
-
-#ifdef KERNFS_DIAGNOSTIC
- printf("kern_read %s\n", kt->kt_name);
-#endif
-
off = uio->uio_offset;
buf = strbuf;
- if ((error = kernfs_xread(kt, off, &buf, sizeof(strbuf), &len)) == 0)
+ if ((error = kernfs_xread(kfs, off, &buf, sizeof(strbuf), &len)) == 0)
error = uiomove(buf, len, uio);
return (error);
}
@@ -577,17 +763,11 @@ kernfs_write(v)
int a_ioflag;
struct ucred *a_cred;
} */ *ap = v;
- struct vnode *vp = ap->a_vp;
+ struct kernfs_node *kfs = VTOKERN(ap->a_vp);
struct uio *uio = ap->a_uio;
- const struct kern_target *kt;
int error, xlen;
char strbuf[KSTRING];
- if (vp->v_type == VDIR)
- return (EOPNOTSUPP);
-
- kt = VTOKERN(vp)->kf_kt;
-
if (uio->uio_offset != 0)
return (EINVAL);
@@ -600,7 +780,7 @@ kernfs_write(v)
strbuf[xlen] = '\0';
xlen = strlen(strbuf);
- return (kernfs_xwrite(kt, strbuf, xlen));
+ return (kernfs_xwrite(kfs, strbuf, xlen));
}
int
@@ -617,14 +797,16 @@ kernfs_readdir(v)
} */ *ap = v;
struct uio *uio = ap->a_uio;
struct dirent d;
+ struct kernfs_node *kfs = VTOKERN(ap->a_vp);
const struct kern_target *kt;
off_t i;
int error;
off_t *cookies = NULL;
- int ncookies = 0, nc = 0;
-
- if (ap->a_vp->v_type != VDIR)
- return (ENOTDIR);
+ int ncookies = 0, n;
+#ifdef IPSEC
+ struct secasvar *sav, *sav2;
+ struct secpolicy *sp;
+#endif
if (uio->uio_resid < UIO_MX)
return (EINVAL);
@@ -633,50 +815,204 @@ kernfs_readdir(v)
error = 0;
i = uio->uio_offset;
-
- if (i >= nkern_targets)
- return 0;
-
- memset((caddr_t)&d, 0, UIO_MX);
+ memset(&d, 0, sizeof(d));
d.d_reclen = UIO_MX;
+ ncookies = uio->uio_resid / UIO_MX;
- if (ap->a_ncookies) {
- nc = uio->uio_resid / UIO_MX;
- nc = min(nc, (nkern_targets - i));
- cookies = malloc(nc * sizeof(off_t), M_TEMP, M_WAITOK);
- *ap->a_cookies = cookies;
- }
+ switch (kfs->kfs_type) {
+ case Pkern:
+ if (i >= nkern_targets)
+ return (0);
- for (kt = &kern_targets[i];
- uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) {
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_readdir: i = %d\n", (int)i);
-#endif
+ if (ap->a_ncookies) {
+ ncookies = min(ncookies, (nkern_targets - i));
+ cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
+ M_WAITOK);
+ *ap->a_cookies = cookies;
+ }
+
+ n = 0;
+ for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
+ kt = &kern_targets[i];
+ d.d_namlen = kt->kt_namlen;
+ if (i < 2)
+ d.d_fileno = KERNFS_FILENO(&kern_targets[0],
+ kern_targets[0].kt_tag, 0);
+ else
+ d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
+ memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
+ d.d_type = kt->kt_type;
+ if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
+ break;
+ if (cookies)
+ *cookies++ = i + 1;
+ n++;
+ }
+ ncookies = n;
+ break;
+
+ case Proot:
+ if (i >= 2)
+ return 0;
+
+ if (ap->a_ncookies) {
+ ncookies = min(ncookies, (2 - i));
+ cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
+ M_WAITOK);
+ *ap->a_cookies = cookies;
+ }
+
+ n = 0;
+ for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
+ kt = &kern_targets[i];
+ d.d_namlen = kt->kt_namlen;
+ d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
+ memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
+ d.d_type = kt->kt_type;
+ if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
+ break;
+ if (cookies)
+ *cookies++ = i + 1;
+ n++;
+ }
+ ncookies = n;
+ break;
+
+#ifdef IPSEC
+ case Pipsecsadir:
+ /* count SA in the system */
+ n = 0;
+ TAILQ_FOREACH(sav, &satailq, tailq) {
+ for (sav2 = TAILQ_FIRST(&satailq);
+ sav2 != sav;
+ sav2 = TAILQ_NEXT(sav2, tailq)) {
+ if (sav->spi == sav2->spi) {
+ /* multiple SA with same SPI */
+ break;
+ }
+ }
+ if (sav == sav2 || sav->spi != sav2->spi)
+ n++;
+ }
- if (kt->kt_tag == KTT_DEVICE) {
- dev_t *dp = kt->kt_data;
- struct vnode *fvp;
+ if (i >= nipsecsa_targets + n)
+ return (0);
+
+ if (ap->a_ncookies) {
+ ncookies = min(ncookies, (n - i));
+ cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
+ M_WAITOK);
+ *ap->a_cookies = cookies;
+ }
- if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
+ n = 0;
+ for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
+ kt = &ipsecsa_targets[i];
+ d.d_namlen = kt->kt_namlen;
+ d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
+ memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
+ d.d_type = kt->kt_type;
+ if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
+ break;
+ if (cookies)
+ *cookies++ = i + 1;
+ n++;
+ }
+ if (error) {
+ ncookies = n;
+ break;
+ }
+
+ TAILQ_FOREACH(sav, &satailq, tailq) {
+ for (sav2 = TAILQ_FIRST(&satailq);
+ sav2 != sav;
+ sav2 = TAILQ_NEXT(sav2, tailq)) {
+ if (sav->spi == sav2->spi) {
+ /* multiple SA with same SPI */
+ break;
+ }
+ }
+ if (sav != sav2 && sav->spi == sav2->spi)
continue;
+ if (uio->uio_resid < UIO_MX)
+ break;
+ d.d_fileno = KERNFS_FILENO(kfs->kfs_kt, kfs->kfs_type,
+ kfs->kfs_cookie);
+ d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
+ "%u", ntohl(sav->spi));
+ d.d_type = DT_REG;
+ if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
+ break;
+ if (cookies)
+ *cookies++ = i + 1;
+ n++;
+ i++;
}
+ ncookies = n;
+ break;
+
+ case Pipsecspdir:
+ /* count SP in the system */
+ n = 0;
+ TAILQ_FOREACH(sp, &sptailq, tailq)
+ n++;
- d.d_fileno = i + 3;
- d.d_namlen = kt->kt_namlen;
- memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
- d.d_type = kt->kt_type;
+ if (i >= 2 + n)
+ return (0);
+
+ if (ap->a_ncookies) {
+ ncookies = min(ncookies, (n - i));
+ cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
+ M_WAITOK);
+ *ap->a_cookies = cookies;
+ }
- if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
+ n = 0;
+ for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
+ kt = &ipsecsp_targets[i];
+ d.d_namlen = kt->kt_namlen;
+ d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
+ memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
+ d.d_type = kt->kt_type;
+ if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
+ break;
+ if (cookies)
+ *cookies++ = i + 1;
+ n++;
+ }
+ if (error) {
+ ncookies = n;
break;
- if (cookies) {
- *cookies++ = i + 1;
- ncookies++;
}
+
+ TAILQ_FOREACH(sp, &sptailq, tailq) {
+ if (uio->uio_resid < UIO_MX)
+ break;
+ d.d_fileno = KERNFS_FILENO(kfs->kfs_kt, kfs->kfs_type,
+ kfs->kfs_cookie);
+ d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
+ "%u", sp->id);
+ d.d_type = DT_REG;
+ if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
+ break;
+ if (cookies)
+ *cookies++ = i + 1;
+ n++;
+ i++;
+ }
+ ncookies = n;
+ break;
+#endif
+
+ default:
+ error = ENOTDIR;
+ break;
}
if (ap->a_ncookies) {
if (error) {
- free(*ap->a_cookies, M_TEMP);
+ if (cookies)
+ free(*ap->a_cookies, M_TEMP);
*ap->a_ncookies = 0;
*ap->a_cookies = NULL;
} else
@@ -696,16 +1032,37 @@ kernfs_inactive(v)
struct proc *a_p;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
-
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_inactive(%p)\n", vp);
+ const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
+#ifdef IPSEC
+ struct mbuf *m;
+ struct secpolicy *sp;
#endif
- /*
- * Clear out the v_type field to avoid
- * nasty things happening in vgone().
- */
+
VOP_UNLOCK(vp, 0);
- vp->v_type = VNON;
+ switch (kfs->kfs_type) {
+#ifdef IPSEC
+ case Pipsecsa:
+ m = key_setdumpsa_spi(htonl(kfs->kfs_value));
+ if (m)
+ m_freem(m);
+ else {
+ /* should never happen as we hold a refcnt */
+ vgone(vp);
+ }
+ break;
+ case Pipsecsp:
+ sp = key_getspbyid(kfs->kfs_value);
+ if (sp)
+ key_freesp(sp);
+ else {
+ /* should never happen as we hold a refcnt */
+ vgone(vp);
+ }
+ break;
+#endif
+ default:
+ break;
+ }
return (0);
}
@@ -716,16 +1073,8 @@ kernfs_reclaim(v)
struct vop_reclaim_args /* {
struct vnode *a_vp;
} */ *ap = v;
- struct vnode *vp = ap->a_vp;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_reclaim(%p)\n", vp);
-#endif
- if (vp->v_data) {
- FREE(vp->v_data, M_TEMP);
- vp->v_data = 0;
- }
- return (0);
+ return (kernfs_freevp(ap->a_vp));
}
/*
diff --git a/sys/netkey/key.c b/sys/netkey/key.c
index f0072a887c4..a2d4410abd0 100644
--- a/sys/netkey/key.c
+++ b/sys/netkey/key.c
@@ -1,5 +1,5 @@
-/* $NetBSD: key.c,v 1.92 2003/09/08 01:55:09 itojun Exp $ */
-/* $KAME: key.c,v 1.308 2003/09/07 20:35:59 itojun Exp $ */
+/* $NetBSD: key.c,v 1.93 2003/09/08 06:51:56 itojun Exp $ */
+/* $KAME: key.c,v 1.310 2003/09/08 02:23:44 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -35,10 +35,11 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.92 2003/09/08 01:55:09 itojun Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.93 2003/09/08 06:51:56 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
+#include "fs_kernfs.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -91,6 +92,10 @@ __KERNEL_RCSID(0, "$NetBSD: key.c,v 1.92 2003/09/08 01:55:09 itojun Exp $");
#endif
#include <netinet6/ipcomp.h>
+#ifdef KERNFS
+#include <miscfs/kernfs/kernfs.h>
+#endif
+
#include <machine/stdarg.h>
#include "rnd.h"
@@ -312,7 +317,6 @@ static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int));
static void key_delsav __P((struct secasvar *));
static void key_delsp __P((struct secpolicy *));
static struct secpolicy *key_getsp __P((struct secpolicyindex *, int));
-static struct secpolicy *key_getspbyid __P((u_int32_t));
static u_int32_t key_newreqid __P((void));
static struct mbuf *key_gather_mbuf __P((struct mbuf *,
const struct sadb_msghdr *, int, int, ...));
@@ -328,8 +332,6 @@ static int key_spdflush __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
static int key_spddump __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
-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 *));
static int key_spdexpire __P((struct secpolicy *));
static struct secashead *key_newsah __P((struct secasindex *));
@@ -969,6 +971,10 @@ key_delsp(sp)
s = splsoftnet(); /*called from softclock()*/
+#ifdef KERNFS
+ kernfs_revoke_sp(sp);
+#endif
+
{
struct ipsecrequest *isr = sp->req, *nextisr;
@@ -1027,7 +1033,7 @@ key_getsp(spidx, dir)
* OUT: NULL : not found
* others : found, pointer to a SP.
*/
-static struct secpolicy *
+struct secpolicy *
key_getspbyid(id)
u_int32_t id;
{
@@ -2199,7 +2205,7 @@ key_spddump(so, m, mhp)
return 0;
}
-static struct mbuf *
+struct mbuf *
key_setdumpsp(sp, type, seq, pid)
struct secpolicy *sp;
u_int8_t type;
@@ -6548,6 +6554,49 @@ key_dump(so, m, mhp)
return 0;
}
+struct mbuf *
+key_setdumpsa_spi(spi)
+ u_int32_t spi;
+{
+ struct mbuf *m, *n;
+ struct secasvar *sav;
+ u_int8_t satype;
+ int cnt;
+
+ cnt = 0;
+ LIST_FOREACH(sav, &spihash[spi % SPIHASHSIZE], spihash) {
+ if (sav->spi != spi)
+ continue;
+ cnt++;
+ }
+
+ if (cnt == 0)
+ return NULL;
+
+ m = NULL;
+ LIST_FOREACH(sav, &spihash[spi % SPIHASHSIZE], spihash) {
+ if (sav->spi != spi)
+ continue;
+ satype = key_proto2satype(sav->sah->saidx.proto);
+ n = key_setdumpsa(sav, SADB_DUMP, satype, --cnt, 0);
+ if (!m)
+ m = n;
+ else if (n)
+ m_cat(m, n);
+ }
+
+ if (!m)
+ return NULL;
+
+ if ((m->m_flags & M_PKTHDR) != 0) {
+ m->m_pkthdr.len = 0;
+ for (n = m; n; n = n->m_next)
+ m->m_pkthdr.len += n->m_len;
+ }
+
+ return m;
+}
+
/*
* SADB_X_PROMISC processing
*
diff --git a/sys/netkey/key.h b/sys/netkey/key.h
index 9d10b1c8076..c9f414370b5 100644
--- a/sys/netkey/key.h
+++ b/sys/netkey/key.h
@@ -1,4 +1,4 @@
-/* $NetBSD: key.h,v 1.15 2003/09/07 15:59:38 itojun Exp $ */
+/* $NetBSD: key.h,v 1.16 2003/09/08 06:51:59 itojun Exp $ */
/* $KAME: key.h,v 1.32 2003/09/07 05:25:20 itojun Exp $ */
/*
@@ -56,6 +56,7 @@ extern int key_checkrequest
__P((struct ipsecrequest *isr, struct secasindex *));
extern struct secasvar *key_allocsa __P((u_int, caddr_t, caddr_t,
u_int, u_int32_t));
+extern struct secpolicy *key_getspbyid __P((u_int32_t));
extern void key_freesp __P((struct secpolicy *));
extern void key_freesav __P((struct secasvar *));
extern struct secpolicy *key_newsp __P((u_int32_t));
@@ -67,9 +68,12 @@ extern int key_cmpspidx_exactly
extern int key_cmpspidx_withmask
__P((struct secpolicyindex *, struct secpolicyindex *));
extern int key_spdacquire __P((struct secpolicy *));
+extern struct mbuf *key_setdumpsp __P((struct secpolicy *,
+ u_int8_t, u_int32_t, u_int32_t));
extern void key_timehandler __P((void *));
extern void key_randomfill __P((void *, size_t));
extern void key_freereg __P((struct socket *));
+struct mbuf *key_setdumpsa_spi __P((u_int32_t));
extern int key_parse __P((struct mbuf *, struct socket *));
extern void key_init __P((void));
extern int key_checktunnelsanity __P((struct secasvar *, u_int,