kernfs_vnops.c revision 1.98.2.1 1 /* $NetBSD: kernfs_vnops.c,v 1.98.2.1 2004/05/14 06:31:44 jdc 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.98.2.1 2004/05/14 06:31:44 jdc 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 /* XXX cast away const */
94 { DT_REG, N("copyright"), (void *)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 /* XXX cast away const */
113 { DT_REG, N("version"), (void *)version,
114 KFSstring, VREG, READ_MODE },
115 };
116 #ifdef IPSEC
117 const struct kern_target ipsecsa_targets[] = {
118 /* NOTE: The name must be less than UIO_MX-16 chars in length */
119 /* name data tag type ro/rw */
120 { DT_DIR, N("."), 0, KFSipsecsadir, VDIR, DIR_MODE },
121 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
122 };
123 const struct kern_target ipsecsp_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, KFSipsecspdir, VDIR, DIR_MODE },
127 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
128 };
129 const struct kern_target ipsecsa_kt =
130 { DT_DIR, N(""), 0, KFSipsecsa, VREG, UREAD_MODE };
131 const struct kern_target ipsecsp_kt =
132 { DT_DIR, N(""), 0, KFSipsecsp, VREG, UREAD_MODE };
133 #endif
134 #undef N
135 int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
136 #ifdef IPSEC
137 int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
138 int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
139 #endif
140
141
142 int kernfs_lookup __P((void *));
143 #define kernfs_create genfs_eopnotsupp
144 #define kernfs_mknod genfs_eopnotsupp
145 int kernfs_open __P((void *));
146 int kernfs_close __P((void *));
147 int kernfs_access __P((void *));
148 int kernfs_getattr __P((void *));
149 int kernfs_setattr __P((void *));
150 int kernfs_read __P((void *));
151 int kernfs_write __P((void *));
152 #define kernfs_fcntl genfs_fcntl
153 #define kernfs_ioctl genfs_enoioctl
154 #define kernfs_poll genfs_poll
155 #define kernfs_revoke genfs_revoke
156 #define kernfs_fsync genfs_nullop
157 #define kernfs_seek genfs_nullop
158 #define kernfs_remove genfs_eopnotsupp
159 int kernfs_link __P((void *));
160 #define kernfs_rename genfs_eopnotsupp
161 #define kernfs_mkdir genfs_eopnotsupp
162 #define kernfs_rmdir genfs_eopnotsupp
163 int kernfs_symlink __P((void *));
164 int kernfs_readdir __P((void *));
165 #define kernfs_readlink genfs_eopnotsupp
166 #define kernfs_abortop genfs_abortop
167 int kernfs_inactive __P((void *));
168 int kernfs_reclaim __P((void *));
169 #define kernfs_lock genfs_lock
170 #define kernfs_unlock genfs_unlock
171 #define kernfs_bmap genfs_badop
172 #define kernfs_strategy genfs_badop
173 int kernfs_print __P((void *));
174 #define kernfs_islocked genfs_islocked
175 int kernfs_pathconf __P((void *));
176 #define kernfs_advlock genfs_einval
177 #define kernfs_blkatoff genfs_eopnotsupp
178 #define kernfs_valloc genfs_eopnotsupp
179 #define kernfs_vfree genfs_nullop
180 #define kernfs_truncate genfs_eopnotsupp
181 #define kernfs_update genfs_nullop
182 #define kernfs_bwrite genfs_eopnotsupp
183 #define kernfs_putpages genfs_putpages
184
185 static int kernfs_xread __P((struct kernfs_node *, int, char **, size_t, size_t *));
186 static int kernfs_xwrite __P((const struct kernfs_node *, char *, size_t));
187
188 int (**kernfs_vnodeop_p) __P((void *));
189 const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
190 { &vop_default_desc, vn_default_error },
191 { &vop_lookup_desc, kernfs_lookup }, /* lookup */
192 { &vop_create_desc, kernfs_create }, /* create */
193 { &vop_mknod_desc, kernfs_mknod }, /* mknod */
194 { &vop_open_desc, kernfs_open }, /* open */
195 { &vop_close_desc, kernfs_close }, /* close */
196 { &vop_access_desc, kernfs_access }, /* access */
197 { &vop_getattr_desc, kernfs_getattr }, /* getattr */
198 { &vop_setattr_desc, kernfs_setattr }, /* setattr */
199 { &vop_read_desc, kernfs_read }, /* read */
200 { &vop_write_desc, kernfs_write }, /* write */
201 { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */
202 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
203 { &vop_poll_desc, kernfs_poll }, /* poll */
204 { &vop_revoke_desc, kernfs_revoke }, /* revoke */
205 { &vop_fsync_desc, kernfs_fsync }, /* fsync */
206 { &vop_seek_desc, kernfs_seek }, /* seek */
207 { &vop_remove_desc, kernfs_remove }, /* remove */
208 { &vop_link_desc, kernfs_link }, /* link */
209 { &vop_rename_desc, kernfs_rename }, /* rename */
210 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
211 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
212 { &vop_symlink_desc, kernfs_symlink }, /* symlink */
213 { &vop_readdir_desc, kernfs_readdir }, /* readdir */
214 { &vop_readlink_desc, kernfs_readlink }, /* readlink */
215 { &vop_abortop_desc, kernfs_abortop }, /* abortop */
216 { &vop_inactive_desc, kernfs_inactive }, /* inactive */
217 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
218 { &vop_lock_desc, kernfs_lock }, /* lock */
219 { &vop_unlock_desc, kernfs_unlock }, /* unlock */
220 { &vop_bmap_desc, kernfs_bmap }, /* bmap */
221 { &vop_strategy_desc, kernfs_strategy }, /* strategy */
222 { &vop_print_desc, kernfs_print }, /* print */
223 { &vop_islocked_desc, kernfs_islocked }, /* islocked */
224 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */
225 { &vop_advlock_desc, kernfs_advlock }, /* advlock */
226 { &vop_blkatoff_desc, kernfs_blkatoff }, /* blkatoff */
227 { &vop_valloc_desc, kernfs_valloc }, /* valloc */
228 { &vop_vfree_desc, kernfs_vfree }, /* vfree */
229 { &vop_truncate_desc, kernfs_truncate }, /* truncate */
230 { &vop_update_desc, kernfs_update }, /* update */
231 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
232 { &vop_putpages_desc, kernfs_putpages }, /* putpages */
233 { NULL, NULL }
234 };
235 const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
236 { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
237
238 static int
239 kernfs_xread(kfs, off, bufp, len, wrlen)
240 struct kernfs_node *kfs;
241 int off;
242 char **bufp;
243 size_t len;
244 size_t *wrlen;
245 {
246 const struct kern_target *kt;
247 #ifdef IPSEC
248 struct mbuf *m;
249 #endif
250
251 kt = kfs->kfs_kt;
252
253 switch (kfs->kfs_type) {
254 case KFStime: {
255 struct timeval tv;
256
257 microtime(&tv);
258 snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
259 break;
260 }
261
262 case KFSint: {
263 int *ip = kt->kt_data;
264
265 snprintf(*bufp, len, "%d\n", *ip);
266 break;
267 }
268
269 case KFSstring: {
270 char *cp = kt->kt_data;
271
272 *bufp = cp;
273 break;
274 }
275
276 case KFSmsgbuf: {
277 long n;
278
279 /*
280 * deal with cases where the message buffer has
281 * become corrupted.
282 */
283 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
284 msgbufenabled = 0;
285 return (ENXIO);
286 }
287
288 /*
289 * Note that reads of /kern/msgbuf won't necessarily yield
290 * consistent results, if the message buffer is modified
291 * while the read is in progress. The worst that can happen
292 * is that incorrect data will be read. There's no way
293 * that this can crash the system unless the values in the
294 * message buffer header are corrupted, but that'll cause
295 * the system to die anyway.
296 */
297 if (off >= msgbufp->msg_bufs) {
298 *wrlen = 0;
299 return (0);
300 }
301 n = msgbufp->msg_bufx + off;
302 if (n >= msgbufp->msg_bufs)
303 n -= msgbufp->msg_bufs;
304 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
305 *bufp = msgbufp->msg_bufc + n;
306 *wrlen = len;
307 return (0);
308 }
309
310 case KFShostname: {
311 char *cp = hostname;
312 int xlen = hostnamelen;
313
314 if (xlen >= (len - 2))
315 return (EINVAL);
316
317 memcpy(*bufp, cp, xlen);
318 (*bufp)[xlen] = '\n';
319 (*bufp)[xlen+1] = '\0';
320 len = strlen(*bufp);
321 break;
322 }
323
324 case KFSavenrun:
325 averunnable.fscale = FSCALE;
326 snprintf(*bufp, len, "%d %d %d %ld\n",
327 averunnable.ldavg[0], averunnable.ldavg[1],
328 averunnable.ldavg[2], averunnable.fscale);
329 break;
330
331 #ifdef IPSEC
332 case KFSipsecsa:
333 /*
334 * Note that SA configuration could be changed during the
335 * read operation, resulting in garbled output.
336 */
337 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
338 if (!m)
339 return (ENOBUFS);
340 if (off >= m->m_pkthdr.len) {
341 *wrlen = 0;
342 m_freem(m);
343 return (0);
344 }
345 if (len > m->m_pkthdr.len - off)
346 len = m->m_pkthdr.len - off;
347 m_copydata(m, off, len, *bufp);
348 *wrlen = len;
349 m_freem(m);
350 return (0);
351
352 case KFSipsecsp:
353 /*
354 * Note that SP configuration could be changed during the
355 * read operation, resulting in garbled output.
356 */
357 if (!kfs->kfs_v) {
358 struct secpolicy *sp;
359
360 sp = key_getspbyid(kfs->kfs_value);
361 if (sp)
362 kfs->kfs_v = sp;
363 else
364 return (ENOENT);
365 }
366 m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
367 SADB_X_SPDGET, 0, 0);
368 if (!m)
369 return (ENOBUFS);
370 if (off >= m->m_pkthdr.len) {
371 *wrlen = 0;
372 m_freem(m);
373 return (0);
374 }
375 if (len > m->m_pkthdr.len - off)
376 len = m->m_pkthdr.len - off;
377 m_copydata(m, off, len, *bufp);
378 *wrlen = len;
379 m_freem(m);
380 return (0);
381 #endif
382
383 default:
384 *wrlen = 0;
385 return (0);
386 }
387
388 len = strlen(*bufp);
389 if (len <= off)
390 *wrlen = 0;
391 else {
392 *bufp += off;
393 *wrlen = len - off;
394 }
395 return (0);
396 }
397
398 static int
399 kernfs_xwrite(kfs, buf, len)
400 const struct kernfs_node *kfs;
401 char *buf;
402 size_t len;
403 {
404
405 switch (kfs->kfs_type) {
406 case KFShostname:
407 if (buf[len-1] == '\n')
408 --len;
409 memcpy(hostname, buf, len);
410 hostname[len] = '\0';
411 hostnamelen = (size_t) len;
412 return (0);
413
414 default:
415 return (EIO);
416 }
417 }
418
419
420 /*
421 * vp is the current namei directory
422 * ndp is the name to locate in that directory...
423 */
424 int
425 kernfs_lookup(v)
426 void *v;
427 {
428 struct vop_lookup_args /* {
429 struct vnode * a_dvp;
430 struct vnode ** a_vpp;
431 struct componentname * a_cnp;
432 } */ *ap = v;
433 struct componentname *cnp = ap->a_cnp;
434 struct vnode **vpp = ap->a_vpp;
435 struct vnode *dvp = ap->a_dvp;
436 const char *pname = cnp->cn_nameptr;
437 const struct kernfs_node *kfs;
438 const struct kern_target *kt;
439 int error, i, wantpunlock;
440 #ifdef IPSEC
441 char *ep;
442 u_int32_t id;
443 #endif
444
445 *vpp = NULLVP;
446 cnp->cn_flags &= ~PDIRUNLOCK;
447
448 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
449 return (EROFS);
450
451 if (cnp->cn_namelen == 1 && *pname == '.') {
452 *vpp = dvp;
453 VREF(dvp);
454 return (0);
455 }
456
457 wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
458 kfs = VTOKERN(dvp);
459 switch (kfs->kfs_type) {
460 case KFSkern:
461 /*
462 * Shouldn't get here with .. in the root node.
463 */
464 if (cnp->cn_flags & ISDOTDOT)
465 return (EIO);
466
467 for (i = 0; i < nkern_targets; i++) {
468 kt = &kern_targets[i];
469 if (cnp->cn_namelen == kt->kt_namlen &&
470 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
471 goto found;
472 }
473 break;
474
475 found:
476 error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
477 if ((error == 0) && wantpunlock) {
478 VOP_UNLOCK(dvp, 0);
479 cnp->cn_flags |= PDIRUNLOCK;
480 }
481 return (error);
482
483 #ifdef IPSEC
484 case KFSipsecsadir:
485 if (cnp->cn_flags & ISDOTDOT) {
486 kt = &kern_targets[0];
487 goto found;
488 }
489
490 for (i = 2; i < nipsecsa_targets; i++) {
491 kt = &ipsecsa_targets[i];
492 if (cnp->cn_namelen == kt->kt_namlen &&
493 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
494 goto found;
495 }
496
497 ep = NULL;
498 id = strtoul(pname, &ep, 10);
499 if (!ep || *ep || ep == pname)
500 break;
501
502 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
503 if ((error == 0) && wantpunlock) {
504 VOP_UNLOCK(dvp, 0);
505 cnp->cn_flags |= PDIRUNLOCK;
506 }
507 return (error);
508
509 case KFSipsecspdir:
510 if (cnp->cn_flags & ISDOTDOT) {
511 kt = &kern_targets[0];
512 goto found;
513 }
514
515 for (i = 2; i < nipsecsp_targets; i++) {
516 kt = &ipsecsp_targets[i];
517 if (cnp->cn_namelen == kt->kt_namlen &&
518 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
519 goto found;
520 }
521
522 ep = NULL;
523 id = strtoul(pname, &ep, 10);
524 if (!ep || *ep || ep == pname)
525 break;
526
527 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
528 if ((error == 0) && wantpunlock) {
529 VOP_UNLOCK(dvp, 0);
530 cnp->cn_flags |= PDIRUNLOCK;
531 }
532 return (error);
533 #endif
534
535 default:
536 return (ENOTDIR);
537 }
538
539 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
540 }
541
542 int
543 kernfs_open(v)
544 void *v;
545 {
546 struct vop_open_args /* {
547 struct vnode *a_vp;
548 int a_mode;
549 struct ucred *a_cred;
550 struct proc *a_p;
551 } */ *ap = v;
552 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
553 #ifdef IPSEC
554 struct mbuf *m;
555 struct secpolicy *sp;
556 #endif
557
558 switch (kfs->kfs_type) {
559 #ifdef IPSEC
560 case KFSipsecsa:
561 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
562 if (m) {
563 m_freem(m);
564 return (0);
565 } else
566 return (ENOENT);
567
568 case KFSipsecsp:
569 sp = key_getspbyid(kfs->kfs_value);
570 if (sp) {
571 kfs->kfs_v = sp;
572 return (0);
573 } else
574 return (ENOENT);
575 #endif
576
577 default:
578 return (0);
579 }
580 }
581
582 int
583 kernfs_close(v)
584 void *v;
585 {
586 struct vop_close_args /* {
587 struct vnode *a_vp;
588 int a_fflag;
589 struct ucred *a_cred;
590 struct proc *a_p;
591 } */ *ap = v;
592 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
593
594 switch (kfs->kfs_type) {
595 #ifdef IPSEC
596 case KFSipsecsp:
597 key_freesp((struct secpolicy *)kfs->kfs_v);
598 break;
599 #endif
600
601 default:
602 break;
603 }
604
605 return (0);
606 }
607
608 int
609 kernfs_access(v)
610 void *v;
611 {
612 struct vop_access_args /* {
613 struct vnode *a_vp;
614 int a_mode;
615 struct ucred *a_cred;
616 struct proc *a_p;
617 } */ *ap = v;
618 struct vattr va;
619 int error;
620
621 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)
622 return (error);
623
624 return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
625 ap->a_mode, ap->a_cred));
626 }
627
628 int
629 kernfs_getattr(v)
630 void *v;
631 {
632 struct vop_getattr_args /* {
633 struct vnode *a_vp;
634 struct vattr *a_vap;
635 struct ucred *a_cred;
636 struct proc *a_p;
637 } */ *ap = v;
638 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
639 struct vattr *vap = ap->a_vap;
640 int error = 0;
641 char strbuf[KSTRING], *buf;
642 size_t nread, total;
643
644 VATTR_NULL(vap);
645 vap->va_type = ap->a_vp->v_type;
646 vap->va_uid = 0;
647 vap->va_gid = 0;
648 vap->va_mode = kfs->kfs_mode;
649 vap->va_fileid = kfs->kfs_fileno;
650 vap->va_flags = 0;
651 vap->va_size = 0;
652 vap->va_blocksize = DEV_BSIZE;
653 /*
654 * Make all times be current TOD, except for the "boottime" node.
655 * Avoid microtime(9), it's slow.
656 * We don't guard the read from time(9) with splclock(9) since we
657 * don't actually need to be THAT sure the access is atomic.
658 */
659 if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 &&
660 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
661 TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
662 } else {
663 TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);
664 }
665 vap->va_atime = vap->va_mtime = vap->va_ctime;
666 vap->va_gen = 0;
667 vap->va_flags = 0;
668 vap->va_rdev = 0;
669 vap->va_bytes = 0;
670
671 switch (kfs->kfs_type) {
672 case KFSkern:
673 #ifdef IPSEC
674 vap->va_nlink = 4; /* 2 extra subdirs */
675 #else
676 vap->va_nlink = 2;
677 #endif
678 vap->va_bytes = vap->va_size = DEV_BSIZE;
679 break;
680
681 case KFSroot:
682 vap->va_nlink = 1;
683 vap->va_bytes = vap->va_size = DEV_BSIZE;
684 break;
685
686 case KFSnull:
687 case KFStime:
688 case KFSint:
689 case KFSstring:
690 case KFShostname:
691 case KFSavenrun:
692 case KFSdevice:
693 case KFSmsgbuf:
694 #ifdef IPSEC
695 case KFSipsecsa:
696 case KFSipsecsp:
697 #endif
698 vap->va_nlink = 1;
699 total = 0;
700 do {
701 buf = strbuf;
702 error = kernfs_xread(kfs, total, &buf,
703 sizeof(strbuf), &nread);
704 total += nread;
705 } while (error == 0 && nread != 0);
706 vap->va_bytes = vap->va_size = total;
707 break;
708
709 #ifdef IPSEC
710 case KFSipsecsadir:
711 case KFSipsecspdir:
712 vap->va_nlink = 2;
713 vap->va_bytes = vap->va_size = DEV_BSIZE;
714 break;
715 #endif
716
717 default:
718 error = EINVAL;
719 break;
720 }
721
722 return (error);
723 }
724
725 /*ARGSUSED*/
726 int
727 kernfs_setattr(v)
728 void *v;
729 {
730
731 /*
732 * Silently ignore attribute changes.
733 * This allows for open with truncate to have no
734 * effect until some data is written. I want to
735 * do it this way because all writes are atomic.
736 */
737 return (0);
738 }
739
740 int
741 kernfs_read(v)
742 void *v;
743 {
744 struct vop_read_args /* {
745 struct vnode *a_vp;
746 struct uio *a_uio;
747 int a_ioflag;
748 struct ucred *a_cred;
749 } */ *ap = v;
750 struct uio *uio = ap->a_uio;
751 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
752 char strbuf[KSTRING], *buf;
753 off_t off;
754 size_t len;
755 int error;
756
757 if (ap->a_vp->v_type == VDIR)
758 return (EOPNOTSUPP);
759
760 off = uio->uio_offset;
761 buf = strbuf;
762 if ((error = kernfs_xread(kfs, off, &buf, sizeof(strbuf), &len)) == 0)
763 error = uiomove(buf, len, uio);
764 return (error);
765 }
766
767 int
768 kernfs_write(v)
769 void *v;
770 {
771 struct vop_write_args /* {
772 struct vnode *a_vp;
773 struct uio *a_uio;
774 int a_ioflag;
775 struct ucred *a_cred;
776 } */ *ap = v;
777 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
778 struct uio *uio = ap->a_uio;
779 int error, xlen;
780 char strbuf[KSTRING];
781
782 if (uio->uio_offset != 0)
783 return (EINVAL);
784
785 xlen = min(uio->uio_resid, KSTRING-1);
786 if ((error = uiomove(strbuf, xlen, uio)) != 0)
787 return (error);
788
789 if (uio->uio_resid != 0)
790 return (EIO);
791
792 strbuf[xlen] = '\0';
793 xlen = strlen(strbuf);
794 return (kernfs_xwrite(kfs, strbuf, xlen));
795 }
796
797 static int
798 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
799 u_int32_t value, struct vop_readdir_args *ap)
800 {
801 struct kernfs_node *kfs;
802 struct vnode *vp;
803 int error;
804
805 if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
806 value)) != 0)
807 return error;
808 if (kt->kt_tag == KFSdevice) {
809 struct vattr va;
810 if ((error = VOP_GETATTR(vp, &va, ap->a_cred,
811 ap->a_uio->uio_segflg == UIO_USERSPACE ?
812 ap->a_uio->uio_procp : &proc0)) != 0)
813 return (error);
814 d->d_fileno = va.va_fileid;
815 } else {
816 kfs = VTOKERN(vp);
817 d->d_fileno = kfs->kfs_fileno;
818 }
819 vput(vp);
820 return 0;
821 }
822
823 static int
824 kernfs_setdirentfileno(struct dirent *d, off_t entry,
825 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
826 const struct kern_target *kt, struct vop_readdir_args *ap)
827 {
828 const struct kern_target *ikt;
829 int error;
830
831 switch (entry) {
832 case 0:
833 d->d_fileno = thisdir_kfs->kfs_fileno;
834 return 0;
835 case 1:
836 ikt = parent_kt;
837 break;
838 default:
839 ikt = kt;
840 break;
841 }
842 if (ikt != thisdir_kfs->kfs_kt) {
843 if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
844 return error;
845 } else
846 d->d_fileno = thisdir_kfs->kfs_fileno;
847 return 0;
848 }
849
850 int
851 kernfs_readdir(v)
852 void *v;
853 {
854 struct vop_readdir_args /* {
855 struct vnode *a_vp;
856 struct uio *a_uio;
857 struct ucred *a_cred;
858 int *a_eofflag;
859 off_t **a_cookies;
860 int a_*ncookies;
861 } */ *ap = v;
862 struct uio *uio = ap->a_uio;
863 struct dirent d;
864 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
865 const struct kern_target *kt;
866 off_t i;
867 int error;
868 off_t *cookies = NULL;
869 int ncookies = 0, n;
870 #ifdef IPSEC
871 struct secasvar *sav, *sav2;
872 struct secpolicy *sp;
873 #endif
874
875 if (uio->uio_resid < UIO_MX)
876 return (EINVAL);
877 if (uio->uio_offset < 0)
878 return (EINVAL);
879
880 error = 0;
881 i = uio->uio_offset;
882 memset(&d, 0, sizeof(d));
883 d.d_reclen = UIO_MX;
884 ncookies = uio->uio_resid / UIO_MX;
885
886 switch (kfs->kfs_type) {
887 case KFSkern:
888 if (i >= nkern_targets)
889 return (0);
890
891 if (ap->a_ncookies) {
892 ncookies = min(ncookies, (nkern_targets - i));
893 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
894 M_WAITOK);
895 *ap->a_cookies = cookies;
896 }
897
898 n = 0;
899 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
900 kt = &kern_targets[i];
901 if (kt->kt_tag == KFSdevice) {
902 dev_t *dp = kt->kt_data;
903 struct vnode *fvp;
904
905 if (*dp == NODEV ||
906 !vfinddev(*dp, kt->kt_vtype, &fvp))
907 continue;
908 }
909 d.d_namlen = kt->kt_namlen;
910 if ((error = kernfs_setdirentfileno(&d, i, kfs,
911 &kern_targets[0], kt, ap)) != 0)
912 break;
913 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
914 d.d_type = kt->kt_type;
915 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
916 break;
917 if (cookies)
918 *cookies++ = i + 1;
919 n++;
920 }
921 ncookies = n;
922 break;
923
924 case KFSroot:
925 if (i >= 2)
926 return 0;
927
928 if (ap->a_ncookies) {
929 ncookies = min(ncookies, (2 - i));
930 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
931 M_WAITOK);
932 *ap->a_cookies = cookies;
933 }
934
935 n = 0;
936 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
937 kt = &kern_targets[i];
938 d.d_namlen = kt->kt_namlen;
939 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
940 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
941 d.d_type = kt->kt_type;
942 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
943 break;
944 if (cookies)
945 *cookies++ = i + 1;
946 n++;
947 }
948 ncookies = n;
949 break;
950
951 #ifdef IPSEC
952 case KFSipsecsadir:
953 /* count SA in the system */
954 n = 0;
955 TAILQ_FOREACH(sav, &satailq, tailq) {
956 for (sav2 = TAILQ_FIRST(&satailq);
957 sav2 != sav;
958 sav2 = TAILQ_NEXT(sav2, tailq)) {
959 if (sav->spi == sav2->spi) {
960 /* multiple SA with same SPI */
961 break;
962 }
963 }
964 if (sav == sav2 || sav->spi != sav2->spi)
965 n++;
966 }
967
968 if (i >= nipsecsa_targets + n)
969 return (0);
970
971 if (ap->a_ncookies) {
972 ncookies = min(ncookies, (n - i));
973 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
974 M_WAITOK);
975 *ap->a_cookies = cookies;
976 }
977
978 n = 0;
979 for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
980 kt = &ipsecsa_targets[i];
981 d.d_namlen = kt->kt_namlen;
982 if ((error = kernfs_setdirentfileno(&d, i, kfs,
983 &kern_targets[0], kt, ap)) != 0)
984 break;
985 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
986 d.d_type = kt->kt_type;
987 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
988 break;
989 if (cookies)
990 *cookies++ = i + 1;
991 n++;
992 }
993 if (error) {
994 ncookies = n;
995 break;
996 }
997
998 TAILQ_FOREACH(sav, &satailq, tailq) {
999 for (sav2 = TAILQ_FIRST(&satailq);
1000 sav2 != sav;
1001 sav2 = TAILQ_NEXT(sav2, tailq)) {
1002 if (sav->spi == sav2->spi) {
1003 /* multiple SA with same SPI */
1004 break;
1005 }
1006 }
1007 if (sav != sav2 && sav->spi == sav2->spi)
1008 continue;
1009 if (uio->uio_resid < UIO_MX)
1010 break;
1011 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
1012 sav->spi, ap)) != 0)
1013 break;
1014 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1015 "%u", ntohl(sav->spi));
1016 d.d_type = DT_REG;
1017 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1018 break;
1019 if (cookies)
1020 *cookies++ = i + 1;
1021 n++;
1022 i++;
1023 }
1024 ncookies = n;
1025 break;
1026
1027 case KFSipsecspdir:
1028 /* count SP in the system */
1029 n = 0;
1030 TAILQ_FOREACH(sp, &sptailq, tailq)
1031 n++;
1032
1033 if (i >= 2 + n)
1034 return (0);
1035
1036 if (ap->a_ncookies) {
1037 ncookies = min(ncookies, (n - i));
1038 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1039 M_WAITOK);
1040 *ap->a_cookies = cookies;
1041 }
1042
1043 n = 0;
1044 for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
1045 kt = &ipsecsp_targets[i];
1046 d.d_namlen = kt->kt_namlen;
1047 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1048 &kern_targets[0], kt, ap)) != 0)
1049 break;
1050 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1051 d.d_type = kt->kt_type;
1052 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1053 break;
1054 if (cookies)
1055 *cookies++ = i + 1;
1056 n++;
1057 }
1058 if (error) {
1059 ncookies = n;
1060 break;
1061 }
1062
1063 TAILQ_FOREACH(sp, &sptailq, tailq) {
1064 if (uio->uio_resid < UIO_MX)
1065 break;
1066 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
1067 sp->id, ap)) != 0)
1068 break;
1069 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1070 "%u", sp->id);
1071 d.d_type = DT_REG;
1072 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1073 break;
1074 if (cookies)
1075 *cookies++ = i + 1;
1076 n++;
1077 i++;
1078 }
1079 ncookies = n;
1080 break;
1081 #endif
1082
1083 default:
1084 error = ENOTDIR;
1085 break;
1086 }
1087
1088 if (ap->a_ncookies) {
1089 if (error) {
1090 if (cookies)
1091 free(*ap->a_cookies, M_TEMP);
1092 *ap->a_ncookies = 0;
1093 *ap->a_cookies = NULL;
1094 } else
1095 *ap->a_ncookies = ncookies;
1096 }
1097
1098 uio->uio_offset = i;
1099 return (error);
1100 }
1101
1102 int
1103 kernfs_inactive(v)
1104 void *v;
1105 {
1106 struct vop_inactive_args /* {
1107 struct vnode *a_vp;
1108 struct proc *a_p;
1109 } */ *ap = v;
1110 struct vnode *vp = ap->a_vp;
1111 const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1112 #ifdef IPSEC
1113 struct mbuf *m;
1114 struct secpolicy *sp;
1115 #endif
1116
1117 VOP_UNLOCK(vp, 0);
1118 switch (kfs->kfs_type) {
1119 #ifdef IPSEC
1120 case KFSipsecsa:
1121 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
1122 if (m)
1123 m_freem(m);
1124 else
1125 vgone(vp);
1126 break;
1127 case KFSipsecsp:
1128 sp = key_getspbyid(kfs->kfs_value);
1129 if (sp)
1130 key_freesp(sp);
1131 else {
1132 /* should never happen as we hold a refcnt */
1133 vgone(vp);
1134 }
1135 break;
1136 #endif
1137 default:
1138 break;
1139 }
1140 return (0);
1141 }
1142
1143 int
1144 kernfs_reclaim(v)
1145 void *v;
1146 {
1147 struct vop_reclaim_args /* {
1148 struct vnode *a_vp;
1149 } */ *ap = v;
1150
1151 return (kernfs_freevp(ap->a_vp));
1152 }
1153
1154 /*
1155 * Return POSIX pathconf information applicable to special devices.
1156 */
1157 int
1158 kernfs_pathconf(v)
1159 void *v;
1160 {
1161 struct vop_pathconf_args /* {
1162 struct vnode *a_vp;
1163 int a_name;
1164 register_t *a_retval;
1165 } */ *ap = v;
1166
1167 switch (ap->a_name) {
1168 case _PC_LINK_MAX:
1169 *ap->a_retval = LINK_MAX;
1170 return (0);
1171 case _PC_MAX_CANON:
1172 *ap->a_retval = MAX_CANON;
1173 return (0);
1174 case _PC_MAX_INPUT:
1175 *ap->a_retval = MAX_INPUT;
1176 return (0);
1177 case _PC_PIPE_BUF:
1178 *ap->a_retval = PIPE_BUF;
1179 return (0);
1180 case _PC_CHOWN_RESTRICTED:
1181 *ap->a_retval = 1;
1182 return (0);
1183 case _PC_VDISABLE:
1184 *ap->a_retval = _POSIX_VDISABLE;
1185 return (0);
1186 case _PC_SYNC_IO:
1187 *ap->a_retval = 1;
1188 return (0);
1189 default:
1190 return (EINVAL);
1191 }
1192 /* NOTREACHED */
1193 }
1194
1195 /*
1196 * Print out the contents of a /dev/fd vnode.
1197 */
1198 /* ARGSUSED */
1199 int
1200 kernfs_print(v)
1201 void *v;
1202 {
1203
1204 printf("tag VT_KERNFS, kernfs vnode\n");
1205 return (0);
1206 }
1207
1208 int
1209 kernfs_link(v)
1210 void *v;
1211 {
1212 struct vop_link_args /* {
1213 struct vnode *a_dvp;
1214 struct vnode *a_vp;
1215 struct componentname *a_cnp;
1216 } */ *ap = v;
1217
1218 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1219 vput(ap->a_dvp);
1220 return (EROFS);
1221 }
1222
1223 int
1224 kernfs_symlink(v)
1225 void *v;
1226 {
1227 struct vop_symlink_args /* {
1228 struct vnode *a_dvp;
1229 struct vnode **a_vpp;
1230 struct componentname *a_cnp;
1231 struct vattr *a_vap;
1232 char *a_target;
1233 } */ *ap = v;
1234
1235 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1236 vput(ap->a_dvp);
1237 return (EROFS);
1238 }
1239