kernfs_vnops.c revision 1.124 1 /* $NetBSD: kernfs_vnops.c,v 1.124 2006/06/23 20:30:11 bouyer Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software donated to Berkeley by
8 * Jan-Simon Pendry.
9 *
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.
21 *
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.
33 *
34 * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95
35 */
36
37 /*
38 * Kernel parameter filesystem (/kern)
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.124 2006/06/23 20:30:11 bouyer Exp $");
43
44 #ifdef _KERNEL_OPT
45 #include "opt_ipsec.h"
46 #endif
47
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>
63
64 #include <miscfs/genfs/genfs.h>
65 #include <miscfs/kernfs/kernfs.h>
66
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
74
75 #include <uvm/uvm_extern.h>
76
77 #define KSTRING 256 /* Largest I/O available via this filesystem */
78 #define UIO_MX 32
79
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)
85
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 },
115 };
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 },
121 };
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 },
128 };
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 },
134 };
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
152
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);
158
159 static int kernfs_default_xread(void *v);
160 static int kernfs_default_xwrite(void *v);
161 static int kernfs_default_fileop_getattr(void *);
162
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_genop = {kernfs_default_fileop_getattr} },
170 { .kf_fileop = KERNFS_FILEOP_IOCTL },
171 { .kf_fileop = KERNFS_FILEOP_CLOSE },
172 { .kf_fileop = KERNFS_FILEOP_READ, .kf_genop = {kernfs_default_xread} },
173 { .kf_fileop = KERNFS_FILEOP_WRITE, .kf_genop = {kernfs_default_xwrite} },
174 };
175
176 int kernfs_lookup(void *);
177 #define kernfs_create genfs_eopnotsupp
178 #define kernfs_mknod genfs_eopnotsupp
179 int kernfs_open(void *);
180 int kernfs_close(void *);
181 int kernfs_access(void *);
182 int kernfs_getattr(void *);
183 int kernfs_setattr(void *);
184 int kernfs_read(void *);
185 int kernfs_write(void *);
186 #define kernfs_fcntl genfs_fcntl
187 int kernfs_ioctl(void *);
188 #define kernfs_poll genfs_poll
189 #define kernfs_revoke genfs_revoke
190 #define kernfs_fsync genfs_nullop
191 #define kernfs_seek genfs_nullop
192 #define kernfs_remove genfs_eopnotsupp
193 int kernfs_link(void *);
194 #define kernfs_rename genfs_eopnotsupp
195 #define kernfs_mkdir genfs_eopnotsupp
196 #define kernfs_rmdir genfs_eopnotsupp
197 int kernfs_symlink(void *);
198 int kernfs_readdir(void *);
199 #define kernfs_readlink genfs_eopnotsupp
200 #define kernfs_abortop genfs_abortop
201 int kernfs_inactive(void *);
202 int kernfs_reclaim(void *);
203 #define kernfs_lock genfs_lock
204 #define kernfs_unlock genfs_unlock
205 #define kernfs_bmap genfs_badop
206 #define kernfs_strategy genfs_badop
207 int kernfs_print(void *);
208 #define kernfs_islocked genfs_islocked
209 int kernfs_pathconf(void *);
210 #define kernfs_advlock genfs_einval
211 #define kernfs_bwrite genfs_eopnotsupp
212 #define kernfs_putpages genfs_putpages
213
214 static int kernfs_xread(struct kernfs_node *, int, char **,
215 size_t, size_t *);
216 static int kernfs_xwrite(const struct kernfs_node *, char *, size_t);
217
218 int (**kernfs_vnodeop_p)(void *);
219 const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
220 { &vop_default_desc, vn_default_error },
221 { &vop_lookup_desc, kernfs_lookup }, /* lookup */
222 { &vop_create_desc, kernfs_create }, /* create */
223 { &vop_mknod_desc, kernfs_mknod }, /* mknod */
224 { &vop_open_desc, kernfs_open }, /* open */
225 { &vop_close_desc, kernfs_close }, /* close */
226 { &vop_access_desc, kernfs_access }, /* access */
227 { &vop_getattr_desc, kernfs_getattr }, /* getattr */
228 { &vop_setattr_desc, kernfs_setattr }, /* setattr */
229 { &vop_read_desc, kernfs_read }, /* read */
230 { &vop_write_desc, kernfs_write }, /* write */
231 { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */
232 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
233 { &vop_poll_desc, kernfs_poll }, /* poll */
234 { &vop_revoke_desc, kernfs_revoke }, /* revoke */
235 { &vop_fsync_desc, kernfs_fsync }, /* fsync */
236 { &vop_seek_desc, kernfs_seek }, /* seek */
237 { &vop_remove_desc, kernfs_remove }, /* remove */
238 { &vop_link_desc, kernfs_link }, /* link */
239 { &vop_rename_desc, kernfs_rename }, /* rename */
240 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
241 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
242 { &vop_symlink_desc, kernfs_symlink }, /* symlink */
243 { &vop_readdir_desc, kernfs_readdir }, /* readdir */
244 { &vop_readlink_desc, kernfs_readlink }, /* readlink */
245 { &vop_abortop_desc, kernfs_abortop }, /* abortop */
246 { &vop_inactive_desc, kernfs_inactive }, /* inactive */
247 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
248 { &vop_lock_desc, kernfs_lock }, /* lock */
249 { &vop_unlock_desc, kernfs_unlock }, /* unlock */
250 { &vop_bmap_desc, kernfs_bmap }, /* bmap */
251 { &vop_strategy_desc, kernfs_strategy }, /* strategy */
252 { &vop_print_desc, kernfs_print }, /* print */
253 { &vop_islocked_desc, kernfs_islocked }, /* islocked */
254 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */
255 { &vop_advlock_desc, kernfs_advlock }, /* advlock */
256 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
257 { &vop_putpages_desc, kernfs_putpages }, /* putpages */
258 { NULL, NULL }
259 };
260 const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
261 { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
262
263 static inline int
264 kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
265 {
266 if (a->kf_type < b->kf_type)
267 return -1;
268 if (a->kf_type > b->kf_type)
269 return 1;
270 if (a->kf_fileop < b->kf_fileop)
271 return -1;
272 if (a->kf_fileop > b->kf_fileop)
273 return 1;
274 return (0);
275 }
276
277 SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
278 SPLAY_INITIALIZER(kfsfileoptree);
279 SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
280 SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
281
282 kfstype
283 kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
284 {
285 static u_char nextfreetype = KFSlasttype;
286 struct kernfs_fileop *dkf, *fkf, skf;
287 int i;
288
289 /* XXX need to keep track of dkf's memory if we support
290 deallocating types */
291 dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
292 memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
293
294 for (i = 0; i < sizeof(kernfs_default_fileops) /
295 sizeof(kernfs_default_fileops[0]); i++) {
296 dkf[i].kf_type = nextfreetype;
297 SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
298 }
299
300 for (i = 0; i < nkf; i++) {
301 skf.kf_type = nextfreetype;
302 skf.kf_fileop = kf[i].kf_fileop;
303 if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
304 fkf->kf_genop = kf[i].kf_genop;
305 }
306
307 return nextfreetype++;
308 }
309
310 int
311 kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
312 {
313 struct kernfs_fileop *kf, skf;
314
315 skf.kf_type = type;
316 skf.kf_fileop = fileop;
317 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
318 if (kf->kf_vop)
319 return kf->kf_vop(v);
320 return error;
321 }
322
323 int
324 kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp,
325 size_t len, int error)
326 {
327 struct kernfs_fileop *kf, skf;
328
329 skf.kf_type = type;
330 skf.kf_fileop = KERNFS_XREAD;
331 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
332 if (kf->kf_xread)
333 return kf->kf_xread(kfs, bfp, len);
334 return error;
335 }
336
337 int
338 kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,
339 size_t len, int error)
340 {
341 struct kernfs_fileop *kf, skf;
342
343 skf.kf_type = type;
344 skf.kf_fileop = KERNFS_XWRITE;
345 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
346 if (kf->kf_xwrite)
347 return kf->kf_xwrite(kfs, bf, len);
348 return error;
349 }
350
351 int
352 kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
353 {
354 struct kernfs_subdir *ks, *parent;
355
356 if (pkt == NULL) {
357 SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
358 nkern_targets++;
359 if (dkt->dkt_kt.kt_vtype == VDIR)
360 nkern_dirs++;
361 } else {
362 parent = (struct kernfs_subdir *)pkt->kt_data;
363 SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
364 parent->ks_nentries++;
365 if (dkt->dkt_kt.kt_vtype == VDIR)
366 parent->ks_dirs++;
367 }
368 if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
369 ks = malloc(sizeof(struct kernfs_subdir),
370 M_TEMP, M_WAITOK);
371 SIMPLEQ_INIT(&ks->ks_entries);
372 ks->ks_nentries = 2; /* . and .. */
373 ks->ks_dirs = 2;
374 ks->ks_parent = pkt ? pkt : &kern_targets[0];
375 dkt->dkt_kt.kt_data = ks;
376 }
377 return 0;
378 }
379
380 static int
381 kernfs_xread(kfs, off, bufp, len, wrlen)
382 struct kernfs_node *kfs;
383 int off;
384 char **bufp;
385 size_t len;
386 size_t *wrlen;
387 {
388 const struct kern_target *kt;
389 #ifdef IPSEC
390 struct mbuf *m;
391 #endif
392 int err;
393
394 kt = kfs->kfs_kt;
395
396 switch (kfs->kfs_type) {
397 case KFStime: {
398 struct timeval tv;
399
400 microtime(&tv);
401 snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
402 break;
403 }
404
405 case KFSint: {
406 int *ip = kt->kt_data;
407
408 snprintf(*bufp, len, "%d\n", *ip);
409 break;
410 }
411
412 case KFSstring: {
413 char *cp = kt->kt_data;
414
415 *bufp = cp;
416 break;
417 }
418
419 case KFSmsgbuf: {
420 long n;
421
422 /*
423 * deal with cases where the message buffer has
424 * become corrupted.
425 */
426 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
427 msgbufenabled = 0;
428 return (ENXIO);
429 }
430
431 /*
432 * Note that reads of /kern/msgbuf won't necessarily yield
433 * consistent results, if the message buffer is modified
434 * while the read is in progress. The worst that can happen
435 * is that incorrect data will be read. There's no way
436 * that this can crash the system unless the values in the
437 * message buffer header are corrupted, but that'll cause
438 * the system to die anyway.
439 */
440 if (off >= msgbufp->msg_bufs) {
441 *wrlen = 0;
442 return (0);
443 }
444 n = msgbufp->msg_bufx + off;
445 if (n >= msgbufp->msg_bufs)
446 n -= msgbufp->msg_bufs;
447 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
448 *bufp = msgbufp->msg_bufc + n;
449 *wrlen = len;
450 return (0);
451 }
452
453 case KFShostname: {
454 char *cp = hostname;
455 int xlen = hostnamelen;
456
457 if (xlen >= (len - 2))
458 return (EINVAL);
459
460 memcpy(*bufp, cp, xlen);
461 (*bufp)[xlen] = '\n';
462 (*bufp)[xlen+1] = '\0';
463 len = strlen(*bufp);
464 break;
465 }
466
467 case KFSavenrun:
468 averunnable.fscale = FSCALE;
469 snprintf(*bufp, len, "%d %d %d %ld\n",
470 averunnable.ldavg[0], averunnable.ldavg[1],
471 averunnable.ldavg[2], averunnable.fscale);
472 break;
473
474 #ifdef IPSEC
475 case KFSipsecsa:
476 /*
477 * Note that SA configuration could be changed during the
478 * read operation, resulting in garbled output.
479 */
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);
487 }
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);
494
495 case KFSipsecsp:
496 /*
497 * Note that SP configuration could be changed during the
498 * read operation, resulting in garbled output.
499 */
500 if (!kfs->kfs_v) {
501 struct secpolicy *sp;
502
503 sp = key_getspbyid(kfs->kfs_value);
504 if (sp)
505 kfs->kfs_v = sp;
506 else
507 return (ENOENT);
508 }
509 m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
510 SADB_X_SPDGET, 0, 0);
511 if (!m)
512 return (ENOBUFS);
513 if (off >= m->m_pkthdr.len) {
514 *wrlen = 0;
515 m_freem(m);
516 return (0);
517 }
518 if (len > m->m_pkthdr.len - off)
519 len = m->m_pkthdr.len - off;
520 m_copydata(m, off, len, *bufp);
521 *wrlen = len;
522 m_freem(m);
523 return (0);
524 #endif
525
526 default:
527 err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len,
528 EOPNOTSUPP);
529 if (err)
530 return err;
531 }
532
533 len = strlen(*bufp);
534 if (len <= off)
535 *wrlen = 0;
536 else {
537 *bufp += off;
538 *wrlen = len - off;
539 }
540 return (0);
541 }
542
543 static int
544 kernfs_xwrite(kfs, bf, len)
545 const struct kernfs_node *kfs;
546 char *bf;
547 size_t len;
548 {
549
550 switch (kfs->kfs_type) {
551 case KFShostname:
552 if (bf[len-1] == '\n')
553 --len;
554 memcpy(hostname, bf, len);
555 hostname[len] = '\0';
556 hostnamelen = (size_t) len;
557 return (0);
558
559 default:
560 return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO);
561 }
562 }
563
564
565 /*
566 * vp is the current namei directory
567 * ndp is the name to locate in that directory...
568 */
569 int
570 kernfs_lookup(v)
571 void *v;
572 {
573 struct vop_lookup_args /* {
574 struct vnode * a_dvp;
575 struct vnode ** a_vpp;
576 struct componentname * a_cnp;
577 } */ *ap = v;
578 struct componentname *cnp = ap->a_cnp;
579 struct vnode **vpp = ap->a_vpp;
580 struct vnode *dvp = ap->a_dvp;
581 const char *pname = cnp->cn_nameptr;
582 const struct kernfs_node *kfs;
583 const struct kern_target *kt;
584 const struct dyn_kern_target *dkt;
585 const struct kernfs_subdir *ks;
586 int error, i, wantpunlock;
587 #ifdef IPSEC
588 char *ep;
589 u_int32_t id;
590 #endif
591
592 *vpp = NULLVP;
593 cnp->cn_flags &= ~PDIRUNLOCK;
594
595 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
596 return (EROFS);
597
598 if (cnp->cn_namelen == 1 && *pname == '.') {
599 *vpp = dvp;
600 VREF(dvp);
601 return (0);
602 }
603
604 wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
605 kfs = VTOKERN(dvp);
606 switch (kfs->kfs_type) {
607 case KFSkern:
608 /*
609 * Shouldn't get here with .. in the root node.
610 */
611 if (cnp->cn_flags & ISDOTDOT)
612 return (EIO);
613
614 for (i = 0; i < static_nkern_targets; i++) {
615 kt = &kern_targets[i];
616 if (cnp->cn_namelen == kt->kt_namlen &&
617 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
618 goto found;
619 }
620 SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
621 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
622 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
623 kt = &dkt->dkt_kt;
624 goto found;
625 }
626 }
627 break;
628
629 found:
630 error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
631 if ((error == 0) && wantpunlock) {
632 VOP_UNLOCK(dvp, 0);
633 cnp->cn_flags |= PDIRUNLOCK;
634 }
635 return (error);
636
637 case KFSsubdir:
638 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
639 if (cnp->cn_flags & ISDOTDOT) {
640 kt = ks->ks_parent;
641 goto found;
642 }
643
644 SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
645 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
646 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
647 kt = &dkt->dkt_kt;
648 goto found;
649 }
650 }
651 break;
652
653 #ifdef IPSEC
654 case KFSipsecsadir:
655 if (cnp->cn_flags & ISDOTDOT) {
656 kt = &kern_targets[0];
657 goto found;
658 }
659
660 for (i = 2; i < nipsecsa_targets; i++) {
661 kt = &ipsecsa_targets[i];
662 if (cnp->cn_namelen == kt->kt_namlen &&
663 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
664 goto found;
665 }
666
667 ep = NULL;
668 id = strtoul(pname, &ep, 10);
669 if (!ep || *ep || ep == pname)
670 break;
671
672 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
673 if ((error == 0) && wantpunlock) {
674 VOP_UNLOCK(dvp, 0);
675 cnp->cn_flags |= PDIRUNLOCK;
676 }
677 return (error);
678
679 case KFSipsecspdir:
680 if (cnp->cn_flags & ISDOTDOT) {
681 kt = &kern_targets[0];
682 goto found;
683 }
684
685 for (i = 2; i < nipsecsp_targets; i++) {
686 kt = &ipsecsp_targets[i];
687 if (cnp->cn_namelen == kt->kt_namlen &&
688 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
689 goto found;
690 }
691
692 ep = NULL;
693 id = strtoul(pname, &ep, 10);
694 if (!ep || *ep || ep == pname)
695 break;
696
697 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
698 if ((error == 0) && wantpunlock) {
699 VOP_UNLOCK(dvp, 0);
700 cnp->cn_flags |= PDIRUNLOCK;
701 }
702 return (error);
703 #endif
704
705 default:
706 return (ENOTDIR);
707 }
708
709 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
710 }
711
712 int
713 kernfs_open(v)
714 void *v;
715 {
716 struct vop_open_args /* {
717 struct vnode *a_vp;
718 int a_mode;
719 kauth_cred_t a_cred;
720 struct lwp *a_l;
721 } */ *ap = v;
722 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
723 #ifdef IPSEC
724 struct mbuf *m;
725 struct secpolicy *sp;
726 #endif
727
728 switch (kfs->kfs_type) {
729 #ifdef IPSEC
730 case KFSipsecsa:
731 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
732 if (m) {
733 m_freem(m);
734 return (0);
735 } else
736 return (ENOENT);
737
738 case KFSipsecsp:
739 sp = key_getspbyid(kfs->kfs_value);
740 if (sp) {
741 kfs->kfs_v = sp;
742 return (0);
743 } else
744 return (ENOENT);
745 #endif
746
747 default:
748 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
749 v, 0);
750 }
751 }
752
753 int
754 kernfs_close(v)
755 void *v;
756 {
757 struct vop_close_args /* {
758 struct vnode *a_vp;
759 int a_fflag;
760 kauth_cred_t a_cred;
761 struct lwp *a_l;
762 } */ *ap = v;
763 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
764
765 switch (kfs->kfs_type) {
766 #ifdef IPSEC
767 case KFSipsecsp:
768 key_freesp((struct secpolicy *)kfs->kfs_v);
769 break;
770 #endif
771
772 default:
773 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
774 v, 0);
775 }
776
777 return (0);
778 }
779
780 int
781 kernfs_access(v)
782 void *v;
783 {
784 struct vop_access_args /* {
785 struct vnode *a_vp;
786 int a_mode;
787 kauth_cred_t a_cred;
788 struct lwp *a_l;
789 } */ *ap = v;
790 struct vattr va;
791 int error;
792
793 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_l)) != 0)
794 return (error);
795
796 return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
797 ap->a_mode, ap->a_cred));
798 }
799
800 static int
801 kernfs_default_fileop_getattr(v)
802 void *v;
803 {
804 struct vop_getattr_args /* {
805 struct vnode *a_vp;
806 struct vattr *a_vap;
807 kauth_cred_t a_cred;
808 struct lwp *a_l;
809 } */ *ap = v;
810 struct vattr *vap = ap->a_vap;
811
812 vap->va_nlink = 1;
813 vap->va_bytes = vap->va_size = 0;
814
815 return 0;
816 }
817
818 int
819 kernfs_getattr(v)
820 void *v;
821 {
822 struct vop_getattr_args /* {
823 struct vnode *a_vp;
824 struct vattr *a_vap;
825 kauth_cred_t a_cred;
826 struct lwp *a_l;
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;
834
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 && kfs->kfs_kt->kt_namlen == 8 &&
846 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
847 TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
848 } else {
849 getnanotime(&vap->va_ctime);
850 }
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;
856
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;
862
863 case KFSroot:
864 vap->va_nlink = 1;
865 vap->va_bytes = vap->va_size = DEV_BSIZE;
866 break;
867
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;
873
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;
896
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
904
905 default:
906 error = kernfs_try_fileop(kfs->kfs_type,
907 KERNFS_FILEOP_GETATTR, v, EINVAL);
908 break;
909 }
910
911 return (error);
912 }
913
914 /*ARGSUSED*/
915 int
916 kernfs_setattr(v)
917 void *v;
918 {
919
920 /*
921 * Silently ignore attribute changes.
922 * This allows for open with truncate to have no
923 * effect until some data is written. I want to
924 * do it this way because all writes are atomic.
925 */
926 return (0);
927 }
928
929 int
930 kernfs_default_xread(v)
931 void *v;
932 {
933 struct vop_read_args /* {
934 struct vnode *a_vp;
935 struct uio *a_uio;
936 int a_ioflag;
937 kauth_cred_t a_cred;
938 } */ *ap = v;
939 struct uio *uio = ap->a_uio;
940 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
941 char strbuf[KSTRING], *bf;
942 int off;
943 size_t len;
944 int error;
945
946 if (ap->a_vp->v_type == VDIR)
947 return (EOPNOTSUPP);
948
949 off = (int)uio->uio_offset;
950 /* Don't allow negative offsets */
951 if (off < 0)
952 return EINVAL;
953
954 bf = strbuf;
955 if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
956 error = uiomove(bf, len, uio);
957 return (error);
958 }
959
960 int
961 kernfs_read(v)
962 void *v;
963 {
964 struct vop_read_args /* {
965 struct vnode *a_vp;
966 struct uio *a_uio;
967 int a_ioflag;
968 struct ucred *a_cred;
969 } */ *ap = v;
970 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
971
972 if (kfs->kfs_type < KFSlasttype) {
973 /* use default function */
974 return kernfs_default_xread(v);
975 }
976 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v,
977 EOPNOTSUPP);
978 }
979
980 static int
981 kernfs_default_xwrite(v)
982 void *v;
983 {
984 struct vop_write_args /* {
985 struct vnode *a_vp;
986 struct uio *a_uio;
987 int a_ioflag;
988 kauth_cred_t a_cred;
989 } */ *ap = v;
990 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
991 struct uio *uio = ap->a_uio;
992 int error, xlen;
993 char strbuf[KSTRING];
994
995 if (uio->uio_offset != 0)
996 return (EINVAL);
997
998 xlen = min(uio->uio_resid, KSTRING-1);
999 if ((error = uiomove(strbuf, xlen, uio)) != 0)
1000 return (error);
1001
1002 if (uio->uio_resid != 0)
1003 return (EIO);
1004
1005 strbuf[xlen] = '\0';
1006 xlen = strlen(strbuf);
1007 return (kernfs_xwrite(kfs, strbuf, xlen));
1008 }
1009
1010 int
1011 kernfs_write(v)
1012 void *v;
1013 {
1014 struct vop_write_args /* {
1015 struct vnode *a_vp;
1016 struct uio *a_uio;
1017 int a_ioflag;
1018 kauth_cred_t a_cred;
1019 } */ *ap = v;
1020 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1021
1022 if (kfs->kfs_type < KFSlasttype) {
1023 /* use default function */
1024 return kernfs_default_xwrite(v);
1025 }
1026 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v,
1027 EOPNOTSUPP);
1028 }
1029
1030 int
1031 kernfs_ioctl(v)
1032 void *v;
1033 {
1034 struct vop_ioctl_args /* {
1035 const struct vnodeop_desc *a_desc;
1036 struct vnode *a_vp;
1037 u_long a_command;
1038 void *a_data;
1039 int a_fflag;
1040 kauth_cred_t a_cred;
1041 struct lwp *a_l;
1042 } */ *ap = v;
1043 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1044
1045 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
1046 EPASSTHROUGH);
1047 }
1048
1049 static int
1050 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
1051 u_int32_t value, struct vop_readdir_args *ap)
1052 {
1053 struct kernfs_node *kfs;
1054 struct vnode *vp;
1055 int error;
1056
1057 if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
1058 value)) != 0)
1059 return error;
1060 if (kt->kt_tag == KFSdevice) {
1061 struct vattr va;
1062
1063 error = VOP_GETATTR(vp, &va, ap->a_cred, curlwp);
1064 if (error != 0) {
1065 return error;
1066 }
1067 d->d_fileno = va.va_fileid;
1068 } else {
1069 kfs = VTOKERN(vp);
1070 d->d_fileno = kfs->kfs_fileno;
1071 }
1072 vput(vp);
1073 return 0;
1074 }
1075
1076 static int
1077 kernfs_setdirentfileno(struct dirent *d, off_t entry,
1078 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
1079 const struct kern_target *kt, struct vop_readdir_args *ap)
1080 {
1081 const struct kern_target *ikt;
1082 int error;
1083
1084 switch (entry) {
1085 case 0:
1086 d->d_fileno = thisdir_kfs->kfs_fileno;
1087 return 0;
1088 case 1:
1089 ikt = parent_kt;
1090 break;
1091 default:
1092 ikt = kt;
1093 break;
1094 }
1095 if (ikt != thisdir_kfs->kfs_kt) {
1096 if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
1097 return error;
1098 } else
1099 d->d_fileno = thisdir_kfs->kfs_fileno;
1100 return 0;
1101 }
1102
1103 int
1104 kernfs_readdir(v)
1105 void *v;
1106 {
1107 struct vop_readdir_args /* {
1108 struct vnode *a_vp;
1109 struct uio *a_uio;
1110 kauth_cred_t a_cred;
1111 int *a_eofflag;
1112 off_t **a_cookies;
1113 int a_*ncookies;
1114 } */ *ap = v;
1115 struct uio *uio = ap->a_uio;
1116 struct dirent d;
1117 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1118 const struct kern_target *kt;
1119 const struct dyn_kern_target *dkt = NULL;
1120 const struct kernfs_subdir *ks;
1121 off_t i, j;
1122 int error;
1123 off_t *cookies = NULL;
1124 int ncookies = 0, n;
1125 #ifdef IPSEC
1126 struct secasvar *sav, *sav2;
1127 struct secpolicy *sp;
1128 #endif
1129
1130 if (uio->uio_resid < UIO_MX)
1131 return (EINVAL);
1132 if (uio->uio_offset < 0)
1133 return (EINVAL);
1134
1135 error = 0;
1136 i = uio->uio_offset;
1137 memset(&d, 0, sizeof(d));
1138 d.d_reclen = UIO_MX;
1139 ncookies = uio->uio_resid / UIO_MX;
1140
1141 switch (kfs->kfs_type) {
1142 case KFSkern:
1143 if (i >= nkern_targets)
1144 return (0);
1145
1146 if (ap->a_ncookies) {
1147 ncookies = min(ncookies, (nkern_targets - i));
1148 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1149 M_WAITOK);
1150 *ap->a_cookies = cookies;
1151 }
1152
1153 n = 0;
1154 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1155 if (i < static_nkern_targets)
1156 kt = &kern_targets[i];
1157 else {
1158 if (dkt == NULL) {
1159 dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
1160 for (j = static_nkern_targets; j < i &&
1161 dkt != NULL; j++)
1162 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1163 if (j != i)
1164 break;
1165 } else {
1166 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1167 }
1168 if (dkt == NULL)
1169 break;
1170 kt = &dkt->dkt_kt;
1171 }
1172 if (kt->kt_tag == KFSdevice) {
1173 dev_t *dp = kt->kt_data;
1174 struct vnode *fvp;
1175
1176 if (*dp == NODEV ||
1177 !vfinddev(*dp, kt->kt_vtype, &fvp))
1178 continue;
1179 }
1180 d.d_namlen = kt->kt_namlen;
1181 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1182 &kern_targets[0], kt, ap)) != 0)
1183 break;
1184 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1185 d.d_type = kt->kt_type;
1186 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1187 break;
1188 if (cookies)
1189 *cookies++ = i + 1;
1190 n++;
1191 }
1192 ncookies = n;
1193 break;
1194
1195 case KFSroot:
1196 if (i >= 2)
1197 return 0;
1198
1199 if (ap->a_ncookies) {
1200 ncookies = min(ncookies, (2 - i));
1201 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1202 M_WAITOK);
1203 *ap->a_cookies = cookies;
1204 }
1205
1206 n = 0;
1207 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1208 kt = &kern_targets[i];
1209 d.d_namlen = kt->kt_namlen;
1210 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
1211 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1212 d.d_type = kt->kt_type;
1213 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1214 break;
1215 if (cookies)
1216 *cookies++ = i + 1;
1217 n++;
1218 }
1219 ncookies = n;
1220 break;
1221
1222 case KFSsubdir:
1223 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
1224 if (i >= ks->ks_nentries)
1225 return (0);
1226
1227 if (ap->a_ncookies) {
1228 ncookies = min(ncookies, (ks->ks_nentries - i));
1229 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1230 M_WAITOK);
1231 *ap->a_cookies = cookies;
1232 }
1233
1234 dkt = SIMPLEQ_FIRST(&ks->ks_entries);
1235 for (j = 0; j < i && dkt != NULL; j++)
1236 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1237 n = 0;
1238 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
1239 if (i < 2)
1240 kt = &subdir_targets[i];
1241 else {
1242 /* check if ks_nentries lied to us */
1243 if (dkt == NULL)
1244 break;
1245 kt = &dkt->dkt_kt;
1246 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1247 }
1248 if (kt->kt_tag == KFSdevice) {
1249 dev_t *dp = kt->kt_data;
1250 struct vnode *fvp;
1251
1252 if (*dp == NODEV ||
1253 !vfinddev(*dp, kt->kt_vtype, &fvp))
1254 continue;
1255 }
1256 d.d_namlen = kt->kt_namlen;
1257 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1258 ks->ks_parent, kt, ap)) != 0)
1259 break;
1260 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1261 d.d_type = kt->kt_type;
1262 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1263 break;
1264 if (cookies)
1265 *cookies++ = i + 1;
1266 n++;
1267 }
1268 ncookies = n;
1269 break;
1270
1271 #ifdef IPSEC
1272 case KFSipsecsadir:
1273 /* count SA in the system */
1274 n = 0;
1275 TAILQ_FOREACH(sav, &satailq, tailq) {
1276 for (sav2 = TAILQ_FIRST(&satailq);
1277 sav2 != sav;
1278 sav2 = TAILQ_NEXT(sav2, tailq)) {
1279 if (sav->spi == sav2->spi) {
1280 /* multiple SA with same SPI */
1281 break;
1282 }
1283 }
1284 if (sav == sav2 || sav->spi != sav2->spi)
1285 n++;
1286 }
1287
1288 if (i >= nipsecsa_targets + n)
1289 return (0);
1290
1291 if (ap->a_ncookies) {
1292 ncookies = min(ncookies, (n - i));
1293 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1294 M_WAITOK);
1295 *ap->a_cookies = cookies;
1296 }
1297
1298 n = 0;
1299 for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
1300 kt = &ipsecsa_targets[i];
1301 d.d_namlen = kt->kt_namlen;
1302 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1303 &kern_targets[0], kt, ap)) != 0)
1304 break;
1305 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1306 d.d_type = kt->kt_type;
1307 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1308 break;
1309 if (cookies)
1310 *cookies++ = i + 1;
1311 n++;
1312 }
1313 if (error) {
1314 ncookies = n;
1315 break;
1316 }
1317
1318 TAILQ_FOREACH(sav, &satailq, tailq) {
1319 for (sav2 = TAILQ_FIRST(&satailq);
1320 sav2 != sav;
1321 sav2 = TAILQ_NEXT(sav2, tailq)) {
1322 if (sav->spi == sav2->spi) {
1323 /* multiple SA with same SPI */
1324 break;
1325 }
1326 }
1327 if (sav != sav2 && sav->spi == sav2->spi)
1328 continue;
1329 if (uio->uio_resid < UIO_MX)
1330 break;
1331 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
1332 sav->spi, ap)) != 0)
1333 break;
1334 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1335 "%u", ntohl(sav->spi));
1336 d.d_type = DT_REG;
1337 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1338 break;
1339 if (cookies)
1340 *cookies++ = i + 1;
1341 n++;
1342 i++;
1343 }
1344 ncookies = n;
1345 break;
1346
1347 case KFSipsecspdir:
1348 /* count SP in the system */
1349 n = 0;
1350 TAILQ_FOREACH(sp, &sptailq, tailq)
1351 n++;
1352
1353 if (i >= nipsecsp_targets + n)
1354 return (0);
1355
1356 if (ap->a_ncookies) {
1357 ncookies = min(ncookies, (n - i));
1358 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1359 M_WAITOK);
1360 *ap->a_cookies = cookies;
1361 }
1362
1363 n = 0;
1364 for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
1365 kt = &ipsecsp_targets[i];
1366 d.d_namlen = kt->kt_namlen;
1367 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1368 &kern_targets[0], kt, ap)) != 0)
1369 break;
1370 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1371 d.d_type = kt->kt_type;
1372 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1373 break;
1374 if (cookies)
1375 *cookies++ = i + 1;
1376 n++;
1377 }
1378 if (error) {
1379 ncookies = n;
1380 break;
1381 }
1382
1383 TAILQ_FOREACH(sp, &sptailq, tailq) {
1384 if (uio->uio_resid < UIO_MX)
1385 break;
1386 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
1387 sp->id, ap)) != 0)
1388 break;
1389 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1390 "%u", sp->id);
1391 d.d_type = DT_REG;
1392 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1393 break;
1394 if (cookies)
1395 *cookies++ = i + 1;
1396 n++;
1397 i++;
1398 }
1399 ncookies = n;
1400 break;
1401 #endif
1402
1403 default:
1404 error = ENOTDIR;
1405 break;
1406 }
1407
1408 if (ap->a_ncookies) {
1409 if (error) {
1410 if (cookies)
1411 free(*ap->a_cookies, M_TEMP);
1412 *ap->a_ncookies = 0;
1413 *ap->a_cookies = NULL;
1414 } else
1415 *ap->a_ncookies = ncookies;
1416 }
1417
1418 uio->uio_offset = i;
1419 return (error);
1420 }
1421
1422 int
1423 kernfs_inactive(v)
1424 void *v;
1425 {
1426 struct vop_inactive_args /* {
1427 struct vnode *a_vp;
1428 struct lwp *a_l;
1429 } */ *ap = v;
1430 struct vnode *vp = ap->a_vp;
1431 const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1432 #ifdef IPSEC
1433 struct mbuf *m;
1434 struct secpolicy *sp;
1435 #endif
1436
1437 VOP_UNLOCK(vp, 0);
1438 switch (kfs->kfs_type) {
1439 #ifdef IPSEC
1440 case KFSipsecsa:
1441 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
1442 if (m)
1443 m_freem(m);
1444 else
1445 vgone(vp);
1446 break;
1447 case KFSipsecsp:
1448 sp = key_getspbyid(kfs->kfs_value);
1449 if (sp)
1450 key_freesp(sp);
1451 else {
1452 /* should never happen as we hold a refcnt */
1453 vgone(vp);
1454 }
1455 break;
1456 #endif
1457 default:
1458 break;
1459 }
1460 return (0);
1461 }
1462
1463 int
1464 kernfs_reclaim(v)
1465 void *v;
1466 {
1467 struct vop_reclaim_args /* {
1468 struct vnode *a_vp;
1469 } */ *ap = v;
1470
1471 return (kernfs_freevp(ap->a_vp));
1472 }
1473
1474 /*
1475 * Return POSIX pathconf information applicable to special devices.
1476 */
1477 int
1478 kernfs_pathconf(v)
1479 void *v;
1480 {
1481 struct vop_pathconf_args /* {
1482 struct vnode *a_vp;
1483 int a_name;
1484 register_t *a_retval;
1485 } */ *ap = v;
1486
1487 switch (ap->a_name) {
1488 case _PC_LINK_MAX:
1489 *ap->a_retval = LINK_MAX;
1490 return (0);
1491 case _PC_MAX_CANON:
1492 *ap->a_retval = MAX_CANON;
1493 return (0);
1494 case _PC_MAX_INPUT:
1495 *ap->a_retval = MAX_INPUT;
1496 return (0);
1497 case _PC_PIPE_BUF:
1498 *ap->a_retval = PIPE_BUF;
1499 return (0);
1500 case _PC_CHOWN_RESTRICTED:
1501 *ap->a_retval = 1;
1502 return (0);
1503 case _PC_VDISABLE:
1504 *ap->a_retval = _POSIX_VDISABLE;
1505 return (0);
1506 case _PC_SYNC_IO:
1507 *ap->a_retval = 1;
1508 return (0);
1509 default:
1510 return (EINVAL);
1511 }
1512 /* NOTREACHED */
1513 }
1514
1515 /*
1516 * Print out the contents of a /dev/fd vnode.
1517 */
1518 /* ARGSUSED */
1519 int
1520 kernfs_print(v)
1521 void *v;
1522 {
1523
1524 printf("tag VT_KERNFS, kernfs vnode\n");
1525 return (0);
1526 }
1527
1528 int
1529 kernfs_link(v)
1530 void *v;
1531 {
1532 struct vop_link_args /* {
1533 struct vnode *a_dvp;
1534 struct vnode *a_vp;
1535 struct componentname *a_cnp;
1536 } */ *ap = v;
1537
1538 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1539 vput(ap->a_dvp);
1540 return (EROFS);
1541 }
1542
1543 int
1544 kernfs_symlink(v)
1545 void *v;
1546 {
1547 struct vop_symlink_args /* {
1548 struct vnode *a_dvp;
1549 struct vnode **a_vpp;
1550 struct componentname *a_cnp;
1551 struct vattr *a_vap;
1552 char *a_target;
1553 } */ *ap = v;
1554
1555 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1556 vput(ap->a_dvp);
1557 return (EROFS);
1558 }
1559