No empty .Rs/.Re
[netbsd-mini2440.git] / sys / miscfs / kernfs / kernfs_vnops.c
blobf98b07a4eaa90428913a7472cee662495fba9246
1 /* $NetBSD: kernfs_vnops.c,v 1.138 2009/07/03 21:17:41 elad Exp $ */
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software donated to Berkeley by
8 * Jan-Simon Pendry.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
34 * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95
38 * Kernel parameter filesystem (/kern)
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.138 2009/07/03 21:17:41 elad Exp $");
44 #ifdef _KERNEL_OPT
45 #include "opt_ipsec.h"
46 #endif
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/vmmeter.h>
52 #include <sys/time.h>
53 #include <sys/proc.h>
54 #include <sys/vnode.h>
55 #include <sys/malloc.h>
56 #include <sys/file.h>
57 #include <sys/stat.h>
58 #include <sys/mount.h>
59 #include <sys/namei.h>
60 #include <sys/buf.h>
61 #include <sys/dirent.h>
62 #include <sys/msgbuf.h>
64 #include <miscfs/genfs/genfs.h>
65 #include <miscfs/kernfs/kernfs.h>
67 #ifdef IPSEC
68 #include <sys/mbuf.h>
69 #include <net/route.h>
70 #include <netinet/in.h>
71 #include <netinet6/ipsec.h>
72 #include <netkey/key.h>
73 #endif
75 #include <uvm/uvm_extern.h>
77 #define KSTRING 256 /* Largest I/O available via this filesystem */
78 #define UIO_MX 32
80 #define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH)
81 #define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
82 #define UREAD_MODE (S_IRUSR)
83 #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
84 #define UDIR_MODE (S_IRUSR|S_IXUSR)
86 #define N(s) sizeof(s)-1, s
87 const struct kern_target kern_targets[] = {
88 /* NOTE: The name must be less than UIO_MX-16 chars in length */
89 /* name data tag type ro/rw */
90 { DT_DIR, N("."), 0, KFSkern, VDIR, DIR_MODE },
91 { DT_DIR, N(".."), 0, KFSroot, VDIR, DIR_MODE },
92 { DT_REG, N("boottime"), &boottime.tv_sec, KFSint, VREG, READ_MODE },
93 /* XXXUNCONST */
94 { DT_REG, N("copyright"), __UNCONST(copyright),
95 KFSstring, VREG, READ_MODE },
96 { DT_REG, N("hostname"), 0, KFShostname, VREG, WRITE_MODE },
97 { DT_REG, N("hz"), &hz, KFSint, VREG, READ_MODE },
98 #ifdef IPSEC
99 { DT_DIR, N("ipsecsa"), 0, KFSipsecsadir, VDIR, UDIR_MODE },
100 { DT_DIR, N("ipsecsp"), 0, KFSipsecspdir, VDIR, UDIR_MODE },
101 #endif
102 { DT_REG, N("loadavg"), 0, KFSavenrun, VREG, READ_MODE },
103 { DT_REG, N("msgbuf"), 0, KFSmsgbuf, VREG, READ_MODE },
104 { DT_REG, N("pagesize"), &uvmexp.pagesize, KFSint, VREG, READ_MODE },
105 { DT_REG, N("physmem"), &physmem, KFSint, VREG, READ_MODE },
106 #if 0
107 { DT_DIR, N("root"), 0, KFSnull, VDIR, DIR_MODE },
108 #endif
109 { DT_BLK, N("rootdev"), &rootdev, KFSdevice, VBLK, READ_MODE },
110 { DT_CHR, N("rrootdev"), &rrootdev, KFSdevice, VCHR, READ_MODE },
111 { DT_REG, N("time"), 0, KFStime, VREG, READ_MODE },
112 /* XXXUNCONST */
113 { DT_REG, N("version"), __UNCONST(version),
114 KFSstring, VREG, READ_MODE },
116 const struct kern_target subdir_targets[] = {
117 /* NOTE: The name must be less than UIO_MX-16 chars in length */
118 /* name data tag type ro/rw */
119 { DT_DIR, N("."), 0, KFSsubdir, VDIR, DIR_MODE },
120 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
122 #ifdef IPSEC
123 const struct kern_target ipsecsa_targets[] = {
124 /* NOTE: The name must be less than UIO_MX-16 chars in length */
125 /* name data tag type ro/rw */
126 { DT_DIR, N("."), 0, KFSipsecsadir, VDIR, DIR_MODE },
127 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
129 const struct kern_target ipsecsp_targets[] = {
130 /* NOTE: The name must be less than UIO_MX-16 chars in length */
131 /* name data tag type ro/rw */
132 { DT_DIR, N("."), 0, KFSipsecspdir, VDIR, DIR_MODE },
133 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
135 const struct kern_target ipsecsa_kt =
136 { DT_DIR, N(""), 0, KFSipsecsa, VREG, UREAD_MODE };
137 const struct kern_target ipsecsp_kt =
138 { DT_DIR, N(""), 0, KFSipsecsp, VREG, UREAD_MODE };
139 #endif
140 #undef N
141 SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
142 SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
143 int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
144 const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
145 #ifdef IPSEC
146 int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
147 int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
148 int nkern_dirs = 4; /* 2 extra subdirs */
149 #else
150 int nkern_dirs = 2;
151 #endif
153 int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
154 int kernfs_try_xread(kfstype, const struct kernfs_node *, char **,
155 size_t, int);
156 int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
157 size_t, int);
159 static int kernfs_default_xread(void *v);
160 static int kernfs_default_xwrite(void *v);
161 static int kernfs_default_fileop_getattr(void *);
163 /* must include all fileop's */
164 const struct kernfs_fileop kernfs_default_fileops[] = {
165 { .kf_fileop = KERNFS_XREAD },
166 { .kf_fileop = KERNFS_XWRITE },
167 { .kf_fileop = KERNFS_FILEOP_OPEN },
168 { .kf_fileop = KERNFS_FILEOP_GETATTR,
169 .kf_vop = kernfs_default_fileop_getattr },
170 { .kf_fileop = KERNFS_FILEOP_IOCTL },
171 { .kf_fileop = KERNFS_FILEOP_CLOSE },
172 { .kf_fileop = KERNFS_FILEOP_READ,
173 .kf_vop = kernfs_default_xread },
174 { .kf_fileop = KERNFS_FILEOP_WRITE,
175 .kf_vop = kernfs_default_xwrite },
178 int kernfs_lookup(void *);
179 #define kernfs_create genfs_eopnotsupp
180 #define kernfs_mknod genfs_eopnotsupp
181 int kernfs_open(void *);
182 int kernfs_close(void *);
183 int kernfs_access(void *);
184 int kernfs_getattr(void *);
185 int kernfs_setattr(void *);
186 int kernfs_read(void *);
187 int kernfs_write(void *);
188 #define kernfs_fcntl genfs_fcntl
189 int kernfs_ioctl(void *);
190 #define kernfs_poll genfs_poll
191 #define kernfs_revoke genfs_revoke
192 #define kernfs_fsync genfs_nullop
193 #define kernfs_seek genfs_nullop
194 #define kernfs_remove genfs_eopnotsupp
195 int kernfs_link(void *);
196 #define kernfs_rename genfs_eopnotsupp
197 #define kernfs_mkdir genfs_eopnotsupp
198 #define kernfs_rmdir genfs_eopnotsupp
199 int kernfs_symlink(void *);
200 int kernfs_readdir(void *);
201 #define kernfs_readlink genfs_eopnotsupp
202 #define kernfs_abortop genfs_abortop
203 int kernfs_inactive(void *);
204 int kernfs_reclaim(void *);
205 #define kernfs_lock genfs_lock
206 #define kernfs_unlock genfs_unlock
207 #define kernfs_bmap genfs_badop
208 #define kernfs_strategy genfs_badop
209 int kernfs_print(void *);
210 #define kernfs_islocked genfs_islocked
211 int kernfs_pathconf(void *);
212 #define kernfs_advlock genfs_einval
213 #define kernfs_bwrite genfs_eopnotsupp
214 #define kernfs_putpages genfs_putpages
216 static int kernfs_xread(struct kernfs_node *, int, char **,
217 size_t, size_t *);
218 static int kernfs_xwrite(const struct kernfs_node *, char *, size_t);
220 int (**kernfs_vnodeop_p)(void *);
221 const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
222 { &vop_default_desc, vn_default_error },
223 { &vop_lookup_desc, kernfs_lookup }, /* lookup */
224 { &vop_create_desc, kernfs_create }, /* create */
225 { &vop_mknod_desc, kernfs_mknod }, /* mknod */
226 { &vop_open_desc, kernfs_open }, /* open */
227 { &vop_close_desc, kernfs_close }, /* close */
228 { &vop_access_desc, kernfs_access }, /* access */
229 { &vop_getattr_desc, kernfs_getattr }, /* getattr */
230 { &vop_setattr_desc, kernfs_setattr }, /* setattr */
231 { &vop_read_desc, kernfs_read }, /* read */
232 { &vop_write_desc, kernfs_write }, /* write */
233 { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */
234 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
235 { &vop_poll_desc, kernfs_poll }, /* poll */
236 { &vop_revoke_desc, kernfs_revoke }, /* revoke */
237 { &vop_fsync_desc, kernfs_fsync }, /* fsync */
238 { &vop_seek_desc, kernfs_seek }, /* seek */
239 { &vop_remove_desc, kernfs_remove }, /* remove */
240 { &vop_link_desc, kernfs_link }, /* link */
241 { &vop_rename_desc, kernfs_rename }, /* rename */
242 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
243 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
244 { &vop_symlink_desc, kernfs_symlink }, /* symlink */
245 { &vop_readdir_desc, kernfs_readdir }, /* readdir */
246 { &vop_readlink_desc, kernfs_readlink }, /* readlink */
247 { &vop_abortop_desc, kernfs_abortop }, /* abortop */
248 { &vop_inactive_desc, kernfs_inactive }, /* inactive */
249 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
250 { &vop_lock_desc, kernfs_lock }, /* lock */
251 { &vop_unlock_desc, kernfs_unlock }, /* unlock */
252 { &vop_bmap_desc, kernfs_bmap }, /* bmap */
253 { &vop_strategy_desc, kernfs_strategy }, /* strategy */
254 { &vop_print_desc, kernfs_print }, /* print */
255 { &vop_islocked_desc, kernfs_islocked }, /* islocked */
256 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */
257 { &vop_advlock_desc, kernfs_advlock }, /* advlock */
258 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
259 { &vop_putpages_desc, kernfs_putpages }, /* putpages */
260 { NULL, NULL }
262 const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
263 { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
265 static inline int
266 kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
268 if (a->kf_type < b->kf_type)
269 return -1;
270 if (a->kf_type > b->kf_type)
271 return 1;
272 if (a->kf_fileop < b->kf_fileop)
273 return -1;
274 if (a->kf_fileop > b->kf_fileop)
275 return 1;
276 return (0);
279 SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
280 SPLAY_INITIALIZER(kfsfileoptree);
281 SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
282 SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
284 kfstype
285 kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
287 static u_char nextfreetype = KFSlasttype;
288 struct kernfs_fileop *dkf, *fkf, skf;
289 int i;
291 /* XXX need to keep track of dkf's memory if we support
292 deallocating types */
293 dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
294 memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
296 for (i = 0; i < sizeof(kernfs_default_fileops) /
297 sizeof(kernfs_default_fileops[0]); i++) {
298 dkf[i].kf_type = nextfreetype;
299 SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
302 for (i = 0; i < nkf; i++) {
303 skf.kf_type = nextfreetype;
304 skf.kf_fileop = kf[i].kf_fileop;
305 if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
306 fkf->kf_vop = kf[i].kf_vop;
309 return nextfreetype++;
313 kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
315 struct kernfs_fileop *kf, skf;
317 skf.kf_type = type;
318 skf.kf_fileop = fileop;
319 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
320 if (kf->kf_vop)
321 return kf->kf_vop(v);
322 return error;
326 kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp,
327 size_t len, int error)
329 struct kernfs_fileop *kf, skf;
331 skf.kf_type = type;
332 skf.kf_fileop = KERNFS_XREAD;
333 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
334 if (kf->kf_xread)
335 return kf->kf_xread(kfs, bfp, len);
336 return error;
340 kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,
341 size_t len, int error)
343 struct kernfs_fileop *kf, skf;
345 skf.kf_type = type;
346 skf.kf_fileop = KERNFS_XWRITE;
347 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
348 if (kf->kf_xwrite)
349 return kf->kf_xwrite(kfs, bf, len);
350 return error;
354 kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
356 struct kernfs_subdir *ks, *parent;
358 if (pkt == NULL) {
359 SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
360 nkern_targets++;
361 if (dkt->dkt_kt.kt_vtype == VDIR)
362 nkern_dirs++;
363 } else {
364 parent = (struct kernfs_subdir *)pkt->kt_data;
365 SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
366 parent->ks_nentries++;
367 if (dkt->dkt_kt.kt_vtype == VDIR)
368 parent->ks_dirs++;
370 if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
371 ks = malloc(sizeof(struct kernfs_subdir),
372 M_TEMP, M_WAITOK);
373 SIMPLEQ_INIT(&ks->ks_entries);
374 ks->ks_nentries = 2; /* . and .. */
375 ks->ks_dirs = 2;
376 ks->ks_parent = pkt ? pkt : &kern_targets[0];
377 dkt->dkt_kt.kt_data = ks;
379 return 0;
382 static int
383 kernfs_xread(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen)
385 const struct kern_target *kt;
386 #ifdef IPSEC
387 struct mbuf *m;
388 #endif
389 int err;
391 kt = kfs->kfs_kt;
393 switch (kfs->kfs_type) {
394 case KFStime: {
395 struct timeval tv;
397 microtime(&tv);
398 snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec,
399 (long)tv.tv_usec);
400 break;
403 case KFSint: {
404 int *ip = kt->kt_data;
406 snprintf(*bufp, len, "%d\n", *ip);
407 break;
410 case KFSstring: {
411 char *cp = kt->kt_data;
413 *bufp = cp;
414 break;
417 case KFSmsgbuf: {
418 long n;
421 * deal with cases where the message buffer has
422 * become corrupted.
424 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
425 msgbufenabled = 0;
426 return (ENXIO);
430 * Note that reads of /kern/msgbuf won't necessarily yield
431 * consistent results, if the message buffer is modified
432 * while the read is in progress. The worst that can happen
433 * is that incorrect data will be read. There's no way
434 * that this can crash the system unless the values in the
435 * message buffer header are corrupted, but that'll cause
436 * the system to die anyway.
438 if (off >= msgbufp->msg_bufs) {
439 *wrlen = 0;
440 return (0);
442 n = msgbufp->msg_bufx + off;
443 if (n >= msgbufp->msg_bufs)
444 n -= msgbufp->msg_bufs;
445 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
446 *bufp = msgbufp->msg_bufc + n;
447 *wrlen = len;
448 return (0);
451 case KFShostname: {
452 char *cp = hostname;
453 size_t xlen = hostnamelen;
455 if (xlen >= (len - 2))
456 return (EINVAL);
458 memcpy(*bufp, cp, xlen);
459 (*bufp)[xlen] = '\n';
460 (*bufp)[xlen+1] = '\0';
461 len = strlen(*bufp);
462 break;
465 case KFSavenrun:
466 averunnable.fscale = FSCALE;
467 snprintf(*bufp, len, "%d %d %d %ld\n",
468 averunnable.ldavg[0], averunnable.ldavg[1],
469 averunnable.ldavg[2], averunnable.fscale);
470 break;
472 #ifdef IPSEC
473 case KFSipsecsa:
474 if (key_setdumpsa_spi == NULL)
475 return 0;
477 * Note that SA configuration could be changed during the
478 * read operation, resulting in garbled output.
480 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
481 if (!m)
482 return (ENOBUFS);
483 if (off >= m->m_pkthdr.len) {
484 *wrlen = 0;
485 m_freem(m);
486 return (0);
488 if (len > m->m_pkthdr.len - off)
489 len = m->m_pkthdr.len - off;
490 m_copydata(m, off, len, *bufp);
491 *wrlen = len;
492 m_freem(m);
493 return (0);
495 case KFSipsecsp:
497 * Note that SP configuration could be changed during the
498 * read operation, resulting in garbled output.
500 if (key_getspbyid == NULL)
501 return 0;
502 if (!kfs->kfs_v) {
503 struct secpolicy *sp;
505 sp = key_getspbyid(kfs->kfs_value);
506 if (sp)
507 kfs->kfs_v = sp;
508 else
509 return (ENOENT);
511 m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
512 SADB_X_SPDGET, 0, 0);
513 if (!m)
514 return (ENOBUFS);
515 if (off >= m->m_pkthdr.len) {
516 *wrlen = 0;
517 m_freem(m);
518 return (0);
520 if (len > m->m_pkthdr.len - off)
521 len = m->m_pkthdr.len - off;
522 m_copydata(m, off, len, *bufp);
523 *wrlen = len;
524 m_freem(m);
525 return (0);
526 #endif
528 default:
529 err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len,
530 EOPNOTSUPP);
531 if (err)
532 return err;
535 len = strlen(*bufp);
536 if (len <= off)
537 *wrlen = 0;
538 else {
539 *bufp += off;
540 *wrlen = len - off;
542 return (0);
545 static int
546 kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len)
549 switch (kfs->kfs_type) {
550 case KFShostname:
551 if (bf[len-1] == '\n')
552 --len;
553 memcpy(hostname, bf, len);
554 hostname[len] = '\0';
555 hostnamelen = (size_t) len;
556 return (0);
558 default:
559 return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO);
565 * vp is the current namei directory
566 * ndp is the name to locate in that directory...
569 kernfs_lookup(void *v)
571 struct vop_lookup_args /* {
572 struct vnode * a_dvp;
573 struct vnode ** a_vpp;
574 struct componentname * a_cnp;
575 } */ *ap = v;
576 struct componentname *cnp = ap->a_cnp;
577 struct vnode **vpp = ap->a_vpp;
578 struct vnode *dvp = ap->a_dvp;
579 const char *pname = cnp->cn_nameptr;
580 const struct kernfs_node *kfs;
581 const struct kern_target *kt;
582 const struct dyn_kern_target *dkt;
583 const struct kernfs_subdir *ks;
584 int error, i;
585 #ifdef IPSEC
586 char *ep;
587 u_int32_t id;
588 #endif
590 *vpp = NULLVP;
592 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
593 return (EROFS);
595 if (cnp->cn_namelen == 1 && *pname == '.') {
596 *vpp = dvp;
597 vref(dvp);
598 return (0);
601 kfs = VTOKERN(dvp);
602 switch (kfs->kfs_type) {
603 case KFSkern:
605 * Shouldn't get here with .. in the root node.
607 if (cnp->cn_flags & ISDOTDOT)
608 return (EIO);
610 for (i = 0; i < static_nkern_targets; i++) {
611 kt = &kern_targets[i];
612 if (cnp->cn_namelen == kt->kt_namlen &&
613 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
614 goto found;
616 SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
617 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
618 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
619 kt = &dkt->dkt_kt;
620 goto found;
623 break;
625 found:
626 error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
627 return (error);
629 case KFSsubdir:
630 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
631 if (cnp->cn_flags & ISDOTDOT) {
632 kt = ks->ks_parent;
633 goto found;
636 SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
637 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
638 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
639 kt = &dkt->dkt_kt;
640 goto found;
643 break;
645 #ifdef IPSEC
646 case KFSipsecsadir:
647 if (cnp->cn_flags & ISDOTDOT) {
648 kt = &kern_targets[0];
649 goto found;
652 for (i = 2; i < nipsecsa_targets; i++) {
653 kt = &ipsecsa_targets[i];
654 if (cnp->cn_namelen == kt->kt_namlen &&
655 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
656 goto found;
659 ep = NULL;
660 id = strtoul(pname, &ep, 10);
661 if (!ep || *ep || ep == pname)
662 break;
664 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
665 return (error);
667 case KFSipsecspdir:
668 if (cnp->cn_flags & ISDOTDOT) {
669 kt = &kern_targets[0];
670 goto found;
673 for (i = 2; i < nipsecsp_targets; i++) {
674 kt = &ipsecsp_targets[i];
675 if (cnp->cn_namelen == kt->kt_namlen &&
676 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
677 goto found;
680 ep = NULL;
681 id = strtoul(pname, &ep, 10);
682 if (!ep || *ep || ep == pname)
683 break;
685 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
686 return (error);
687 #endif
689 default:
690 return (ENOTDIR);
693 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
697 kernfs_open(void *v)
699 struct vop_open_args /* {
700 struct vnode *a_vp;
701 int a_mode;
702 kauth_cred_t a_cred;
703 } */ *ap = v;
704 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
705 #ifdef IPSEC
706 struct mbuf *m;
707 struct secpolicy *sp;
708 #endif
710 switch (kfs->kfs_type) {
711 #ifdef IPSEC
712 case KFSipsecsa:
713 if (key_setdumpsa_spi == NULL)
714 return 0;
715 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
716 if (m) {
717 m_freem(m);
718 return (0);
719 } else
720 return (ENOENT);
722 case KFSipsecsp:
723 if (key_getspbyid == NULL)
724 return 0;
725 sp = key_getspbyid(kfs->kfs_value);
726 if (sp) {
727 kfs->kfs_v = sp;
728 return (0);
729 } else
730 return (ENOENT);
731 #endif
733 default:
734 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
735 v, 0);
740 kernfs_close(void *v)
742 struct vop_close_args /* {
743 struct vnode *a_vp;
744 int a_fflag;
745 kauth_cred_t a_cred;
746 } */ *ap = v;
747 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
749 switch (kfs->kfs_type) {
750 #ifdef IPSEC
751 case KFSipsecsp:
752 if (key_freesp == NULL)
753 return 0;
754 key_freesp((struct secpolicy *)kfs->kfs_v);
755 break;
756 #endif
758 default:
759 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
760 v, 0);
763 return (0);
766 static int
767 kernfs_check_possible(struct vnode *vp, mode_t mode)
770 return 0;
773 static int
774 kernfs_check_permitted(struct vattr *va, mode_t mode, kauth_cred_t cred)
777 return genfs_can_access(va->va_type, va->va_mode, va->va_uid, va->va_gid,
778 mode, cred);
782 kernfs_access(void *v)
784 struct vop_access_args /* {
785 struct vnode *a_vp;
786 int a_mode;
787 kauth_cred_t a_cred;
788 } */ *ap = v;
789 struct vattr va;
790 int error;
792 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0)
793 return (error);
795 error = kernfs_check_possible(ap->a_vp, ap->a_mode);
796 if (error)
797 return error;
799 error = kernfs_check_permitted(&va, ap->a_mode, ap->a_cred);
801 return error;
804 static int
805 kernfs_default_fileop_getattr(void *v)
807 struct vop_getattr_args /* {
808 struct vnode *a_vp;
809 struct vattr *a_vap;
810 kauth_cred_t a_cred;
811 } */ *ap = v;
812 struct vattr *vap = ap->a_vap;
814 vap->va_nlink = 1;
815 vap->va_bytes = vap->va_size = 0;
817 return 0;
821 kernfs_getattr(void *v)
823 struct vop_getattr_args /* {
824 struct vnode *a_vp;
825 struct vattr *a_vap;
826 kauth_cred_t a_cred;
827 } */ *ap = v;
828 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
829 struct kernfs_subdir *ks;
830 struct vattr *vap = ap->a_vap;
831 int error = 0;
832 char strbuf[KSTRING], *bf;
833 size_t nread, total;
835 vattr_null(vap);
836 vap->va_type = ap->a_vp->v_type;
837 vap->va_uid = 0;
838 vap->va_gid = 0;
839 vap->va_mode = kfs->kfs_mode;
840 vap->va_fileid = kfs->kfs_fileno;
841 vap->va_flags = 0;
842 vap->va_size = 0;
843 vap->va_blocksize = DEV_BSIZE;
844 /* Make all times be current TOD, except for the "boottime" node. */
845 if (kfs->kfs_kt->kt_namlen == 8 &&
846 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
847 vap->va_ctime = boottime;
848 } else {
849 getnanotime(&vap->va_ctime);
851 vap->va_atime = vap->va_mtime = vap->va_ctime;
852 vap->va_gen = 0;
853 vap->va_flags = 0;
854 vap->va_rdev = 0;
855 vap->va_bytes = 0;
857 switch (kfs->kfs_type) {
858 case KFSkern:
859 vap->va_nlink = nkern_dirs;
860 vap->va_bytes = vap->va_size = DEV_BSIZE;
861 break;
863 case KFSroot:
864 vap->va_nlink = 1;
865 vap->va_bytes = vap->va_size = DEV_BSIZE;
866 break;
868 case KFSsubdir:
869 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
870 vap->va_nlink = ks->ks_dirs;
871 vap->va_bytes = vap->va_size = DEV_BSIZE;
872 break;
874 case KFSnull:
875 case KFStime:
876 case KFSint:
877 case KFSstring:
878 case KFShostname:
879 case KFSavenrun:
880 case KFSdevice:
881 case KFSmsgbuf:
882 #ifdef IPSEC
883 case KFSipsecsa:
884 case KFSipsecsp:
885 #endif
886 vap->va_nlink = 1;
887 total = 0;
888 do {
889 bf = strbuf;
890 error = kernfs_xread(kfs, total, &bf,
891 sizeof(strbuf), &nread);
892 total += nread;
893 } while (error == 0 && nread != 0);
894 vap->va_bytes = vap->va_size = total;
895 break;
897 #ifdef IPSEC
898 case KFSipsecsadir:
899 case KFSipsecspdir:
900 vap->va_nlink = 2;
901 vap->va_bytes = vap->va_size = DEV_BSIZE;
902 break;
903 #endif
905 default:
906 error = kernfs_try_fileop(kfs->kfs_type,
907 KERNFS_FILEOP_GETATTR, v, EINVAL);
908 break;
911 return (error);
914 /*ARGSUSED*/
916 kernfs_setattr(void *v)
920 * Silently ignore attribute changes.
921 * This allows for open with truncate to have no
922 * effect until some data is written. I want to
923 * do it this way because all writes are atomic.
925 return (0);
929 kernfs_default_xread(void *v)
931 struct vop_read_args /* {
932 struct vnode *a_vp;
933 struct uio *a_uio;
934 int a_ioflag;
935 kauth_cred_t a_cred;
936 } */ *ap = v;
937 struct uio *uio = ap->a_uio;
938 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
939 char strbuf[KSTRING], *bf;
940 int off;
941 size_t len;
942 int error;
944 if (ap->a_vp->v_type == VDIR)
945 return (EOPNOTSUPP);
947 off = (int)uio->uio_offset;
948 /* Don't allow negative offsets */
949 if (off < 0)
950 return EINVAL;
952 bf = strbuf;
953 if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
954 error = uiomove(bf, len, uio);
955 return (error);
959 kernfs_read(void *v)
961 struct vop_read_args /* {
962 struct vnode *a_vp;
963 struct uio *a_uio;
964 int a_ioflag;
965 struct ucred *a_cred;
966 } */ *ap = v;
967 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
969 if (kfs->kfs_type < KFSlasttype) {
970 /* use default function */
971 return kernfs_default_xread(v);
973 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v,
974 EOPNOTSUPP);
977 static int
978 kernfs_default_xwrite(void *v)
980 struct vop_write_args /* {
981 struct vnode *a_vp;
982 struct uio *a_uio;
983 int a_ioflag;
984 kauth_cred_t a_cred;
985 } */ *ap = v;
986 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
987 struct uio *uio = ap->a_uio;
988 int error;
989 size_t xlen;
990 char strbuf[KSTRING];
992 if (uio->uio_offset != 0)
993 return (EINVAL);
995 xlen = min(uio->uio_resid, KSTRING-1);
996 if ((error = uiomove(strbuf, xlen, uio)) != 0)
997 return (error);
999 if (uio->uio_resid != 0)
1000 return (EIO);
1002 strbuf[xlen] = '\0';
1003 xlen = strlen(strbuf);
1004 return (kernfs_xwrite(kfs, strbuf, xlen));
1008 kernfs_write(void *v)
1010 struct vop_write_args /* {
1011 struct vnode *a_vp;
1012 struct uio *a_uio;
1013 int a_ioflag;
1014 kauth_cred_t a_cred;
1015 } */ *ap = v;
1016 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1018 if (kfs->kfs_type < KFSlasttype) {
1019 /* use default function */
1020 return kernfs_default_xwrite(v);
1022 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v,
1023 EOPNOTSUPP);
1027 kernfs_ioctl(void *v)
1029 struct vop_ioctl_args /* {
1030 const struct vnodeop_desc *a_desc;
1031 struct vnode *a_vp;
1032 u_long a_command;
1033 void *a_data;
1034 int a_fflag;
1035 kauth_cred_t a_cred;
1036 } */ *ap = v;
1037 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1039 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
1040 EPASSTHROUGH);
1043 static int
1044 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
1045 u_int32_t value, struct vop_readdir_args *ap)
1047 struct kernfs_node *kfs;
1048 struct vnode *vp;
1049 int error;
1051 if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
1052 value)) != 0)
1053 return error;
1054 if (kt->kt_tag == KFSdevice) {
1055 struct vattr va;
1057 error = VOP_GETATTR(vp, &va, ap->a_cred);
1058 if (error != 0) {
1059 return error;
1061 d->d_fileno = va.va_fileid;
1062 } else {
1063 kfs = VTOKERN(vp);
1064 d->d_fileno = kfs->kfs_fileno;
1066 vput(vp);
1067 return 0;
1070 static int
1071 kernfs_setdirentfileno(struct dirent *d, off_t entry,
1072 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
1073 const struct kern_target *kt, struct vop_readdir_args *ap)
1075 const struct kern_target *ikt;
1076 int error;
1078 switch (entry) {
1079 case 0:
1080 d->d_fileno = thisdir_kfs->kfs_fileno;
1081 return 0;
1082 case 1:
1083 ikt = parent_kt;
1084 break;
1085 default:
1086 ikt = kt;
1087 break;
1089 if (ikt != thisdir_kfs->kfs_kt) {
1090 if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
1091 return error;
1092 } else
1093 d->d_fileno = thisdir_kfs->kfs_fileno;
1094 return 0;
1098 kernfs_readdir(void *v)
1100 struct vop_readdir_args /* {
1101 struct vnode *a_vp;
1102 struct uio *a_uio;
1103 kauth_cred_t a_cred;
1104 int *a_eofflag;
1105 off_t **a_cookies;
1106 int a_*ncookies;
1107 } */ *ap = v;
1108 struct uio *uio = ap->a_uio;
1109 struct dirent d;
1110 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1111 const struct kern_target *kt;
1112 const struct dyn_kern_target *dkt = NULL;
1113 const struct kernfs_subdir *ks;
1114 off_t i, j;
1115 int error;
1116 off_t *cookies = NULL;
1117 int ncookies = 0, n;
1118 #ifdef IPSEC
1119 struct secasvar *sav, *sav2;
1120 struct secpolicy *sp;
1121 #endif
1123 if (uio->uio_resid < UIO_MX)
1124 return (EINVAL);
1125 if (uio->uio_offset < 0)
1126 return (EINVAL);
1128 error = 0;
1129 i = uio->uio_offset;
1130 memset(&d, 0, sizeof(d));
1131 d.d_reclen = UIO_MX;
1132 ncookies = uio->uio_resid / UIO_MX;
1134 switch (kfs->kfs_type) {
1135 case KFSkern:
1136 if (i >= nkern_targets)
1137 return (0);
1139 if (ap->a_ncookies) {
1140 ncookies = min(ncookies, (nkern_targets - i));
1141 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1142 M_WAITOK);
1143 *ap->a_cookies = cookies;
1146 n = 0;
1147 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1148 if (i < static_nkern_targets)
1149 kt = &kern_targets[i];
1150 else {
1151 if (dkt == NULL) {
1152 dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
1153 for (j = static_nkern_targets; j < i &&
1154 dkt != NULL; j++)
1155 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1156 if (j != i)
1157 break;
1158 } else {
1159 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1161 if (dkt == NULL)
1162 break;
1163 kt = &dkt->dkt_kt;
1165 if (kt->kt_tag == KFSdevice) {
1166 dev_t *dp = kt->kt_data;
1167 struct vnode *fvp;
1169 if (*dp == NODEV ||
1170 !vfinddev(*dp, kt->kt_vtype, &fvp))
1171 continue;
1173 d.d_namlen = kt->kt_namlen;
1174 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1175 &kern_targets[0], kt, ap)) != 0)
1176 break;
1177 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1178 d.d_type = kt->kt_type;
1179 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1180 break;
1181 if (cookies)
1182 *cookies++ = i + 1;
1183 n++;
1185 ncookies = n;
1186 break;
1188 case KFSroot:
1189 if (i >= 2)
1190 return 0;
1192 if (ap->a_ncookies) {
1193 ncookies = min(ncookies, (2 - i));
1194 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1195 M_WAITOK);
1196 *ap->a_cookies = cookies;
1199 n = 0;
1200 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1201 kt = &kern_targets[i];
1202 d.d_namlen = kt->kt_namlen;
1203 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
1204 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1205 d.d_type = kt->kt_type;
1206 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1207 break;
1208 if (cookies)
1209 *cookies++ = i + 1;
1210 n++;
1212 ncookies = n;
1213 break;
1215 case KFSsubdir:
1216 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
1217 if (i >= ks->ks_nentries)
1218 return (0);
1220 if (ap->a_ncookies) {
1221 ncookies = min(ncookies, (ks->ks_nentries - i));
1222 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1223 M_WAITOK);
1224 *ap->a_cookies = cookies;
1227 dkt = SIMPLEQ_FIRST(&ks->ks_entries);
1228 for (j = 0; j < i && dkt != NULL; j++)
1229 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1230 n = 0;
1231 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
1232 if (i < 2)
1233 kt = &subdir_targets[i];
1234 else {
1235 /* check if ks_nentries lied to us */
1236 if (dkt == NULL)
1237 break;
1238 kt = &dkt->dkt_kt;
1239 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1241 if (kt->kt_tag == KFSdevice) {
1242 dev_t *dp = kt->kt_data;
1243 struct vnode *fvp;
1245 if (*dp == NODEV ||
1246 !vfinddev(*dp, kt->kt_vtype, &fvp))
1247 continue;
1249 d.d_namlen = kt->kt_namlen;
1250 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1251 ks->ks_parent, kt, ap)) != 0)
1252 break;
1253 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1254 d.d_type = kt->kt_type;
1255 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1256 break;
1257 if (cookies)
1258 *cookies++ = i + 1;
1259 n++;
1261 ncookies = n;
1262 break;
1264 #ifdef IPSEC
1265 case KFSipsecsadir:
1266 /* count SA in the system */
1267 n = 0;
1268 if (&satailq == NULL)
1269 return 0;
1270 TAILQ_FOREACH(sav, &satailq, tailq) {
1271 for (sav2 = TAILQ_FIRST(&satailq);
1272 sav2 != sav;
1273 sav2 = TAILQ_NEXT(sav2, tailq)) {
1274 if (sav->spi == sav2->spi) {
1275 /* multiple SA with same SPI */
1276 break;
1279 if (sav == sav2 || sav->spi != sav2->spi)
1280 n++;
1283 if (i >= nipsecsa_targets + n)
1284 return (0);
1286 if (ap->a_ncookies) {
1287 ncookies = min(ncookies, (n - i));
1288 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1289 M_WAITOK);
1290 *ap->a_cookies = cookies;
1293 n = 0;
1294 for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
1295 kt = &ipsecsa_targets[i];
1296 d.d_namlen = kt->kt_namlen;
1297 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1298 &kern_targets[0], kt, ap)) != 0)
1299 break;
1300 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1301 d.d_type = kt->kt_type;
1302 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1303 break;
1304 if (cookies)
1305 *cookies++ = i + 1;
1306 n++;
1308 if (error) {
1309 ncookies = n;
1310 break;
1313 TAILQ_FOREACH(sav, &satailq, tailq) {
1314 for (sav2 = TAILQ_FIRST(&satailq);
1315 sav2 != sav;
1316 sav2 = TAILQ_NEXT(sav2, tailq)) {
1317 if (sav->spi == sav2->spi) {
1318 /* multiple SA with same SPI */
1319 break;
1322 if (sav != sav2 && sav->spi == sav2->spi)
1323 continue;
1324 if (uio->uio_resid < UIO_MX)
1325 break;
1326 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
1327 sav->spi, ap)) != 0)
1328 break;
1329 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1330 "%u", ntohl(sav->spi));
1331 d.d_type = DT_REG;
1332 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1333 break;
1334 if (cookies)
1335 *cookies++ = i + 1;
1336 n++;
1337 i++;
1339 ncookies = n;
1340 break;
1342 case KFSipsecspdir:
1343 /* count SP in the system */
1344 if (&sptailq == NULL)
1345 return 0;
1347 n = 0;
1348 TAILQ_FOREACH(sp, &sptailq, tailq)
1349 n++;
1351 if (i >= nipsecsp_targets + n)
1352 return (0);
1354 if (ap->a_ncookies) {
1355 ncookies = min(ncookies, (n - i));
1356 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1357 M_WAITOK);
1358 *ap->a_cookies = cookies;
1361 n = 0;
1362 for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
1363 kt = &ipsecsp_targets[i];
1364 d.d_namlen = kt->kt_namlen;
1365 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1366 &kern_targets[0], kt, ap)) != 0)
1367 break;
1368 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1369 d.d_type = kt->kt_type;
1370 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1371 break;
1372 if (cookies)
1373 *cookies++ = i + 1;
1374 n++;
1376 if (error) {
1377 ncookies = n;
1378 break;
1381 TAILQ_FOREACH(sp, &sptailq, tailq) {
1382 if (uio->uio_resid < UIO_MX)
1383 break;
1384 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
1385 sp->id, ap)) != 0)
1386 break;
1387 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1388 "%u", sp->id);
1389 d.d_type = DT_REG;
1390 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1391 break;
1392 if (cookies)
1393 *cookies++ = i + 1;
1394 n++;
1395 i++;
1397 ncookies = n;
1398 break;
1399 #endif
1401 default:
1402 error = ENOTDIR;
1403 break;
1406 if (ap->a_ncookies) {
1407 if (error) {
1408 if (cookies)
1409 free(*ap->a_cookies, M_TEMP);
1410 *ap->a_ncookies = 0;
1411 *ap->a_cookies = NULL;
1412 } else
1413 *ap->a_ncookies = ncookies;
1416 uio->uio_offset = i;
1417 return (error);
1421 kernfs_inactive(void *v)
1423 struct vop_inactive_args /* {
1424 struct vnode *a_vp;
1425 bool *a_recycle;
1426 } */ *ap = v;
1427 struct vnode *vp = ap->a_vp;
1428 const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1429 #ifdef IPSEC
1430 struct mbuf *m;
1431 struct secpolicy *sp;
1432 #endif
1434 *ap->a_recycle = false;
1435 switch (kfs->kfs_type) {
1436 #ifdef IPSEC
1437 case KFSipsecsa:
1438 if (key_setdumpsa_spi == NULL)
1439 return 0;
1440 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
1441 if (m)
1442 m_freem(m);
1443 else
1444 *ap->a_recycle = true;
1445 break;
1446 case KFSipsecsp:
1447 if (key_getspbyid == NULL)
1448 return 0;
1449 sp = key_getspbyid(kfs->kfs_value);
1450 if (sp)
1451 key_freesp(sp);
1452 else {
1453 *ap->a_recycle = true;
1455 break;
1456 #endif
1457 default:
1458 break;
1460 VOP_UNLOCK(vp, 0);
1461 return (0);
1465 kernfs_reclaim(void *v)
1467 struct vop_reclaim_args /* {
1468 struct vnode *a_vp;
1469 } */ *ap = v;
1471 return (kernfs_freevp(ap->a_vp));
1475 * Return POSIX pathconf information applicable to special devices.
1478 kernfs_pathconf(void *v)
1480 struct vop_pathconf_args /* {
1481 struct vnode *a_vp;
1482 int a_name;
1483 register_t *a_retval;
1484 } */ *ap = v;
1486 switch (ap->a_name) {
1487 case _PC_LINK_MAX:
1488 *ap->a_retval = LINK_MAX;
1489 return (0);
1490 case _PC_MAX_CANON:
1491 *ap->a_retval = MAX_CANON;
1492 return (0);
1493 case _PC_MAX_INPUT:
1494 *ap->a_retval = MAX_INPUT;
1495 return (0);
1496 case _PC_PIPE_BUF:
1497 *ap->a_retval = PIPE_BUF;
1498 return (0);
1499 case _PC_CHOWN_RESTRICTED:
1500 *ap->a_retval = 1;
1501 return (0);
1502 case _PC_VDISABLE:
1503 *ap->a_retval = _POSIX_VDISABLE;
1504 return (0);
1505 case _PC_SYNC_IO:
1506 *ap->a_retval = 1;
1507 return (0);
1508 default:
1509 return (EINVAL);
1511 /* NOTREACHED */
1515 * Print out the contents of a /dev/fd vnode.
1517 /* ARGSUSED */
1519 kernfs_print(void *v)
1522 printf("tag VT_KERNFS, kernfs vnode\n");
1523 return (0);
1527 kernfs_link(void *v)
1529 struct vop_link_args /* {
1530 struct vnode *a_dvp;
1531 struct vnode *a_vp;
1532 struct componentname *a_cnp;
1533 } */ *ap = v;
1535 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1536 vput(ap->a_dvp);
1537 return (EROFS);
1541 kernfs_symlink(void *v)
1543 struct vop_symlink_args /* {
1544 struct vnode *a_dvp;
1545 struct vnode **a_vpp;
1546 struct componentname *a_cnp;
1547 struct vattr *a_vap;
1548 char *a_target;
1549 } */ *ap = v;
1551 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1552 vput(ap->a_dvp);
1553 return (EROFS);