1 /* $NetBSD: kernfs_vnops.c,v 1.138 2009/07/03 21:17:41 elad Exp $ */
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
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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
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 $");
45 #include "opt_ipsec.h"
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/vmmeter.h>
54 #include <sys/vnode.h>
55 #include <sys/malloc.h>
58 #include <sys/mount.h>
59 #include <sys/namei.h>
61 #include <sys/dirent.h>
62 #include <sys/msgbuf.h>
64 #include <miscfs/genfs/genfs.h>
65 #include <miscfs/kernfs/kernfs.h>
69 #include <net/route.h>
70 #include <netinet/in.h>
71 #include <netinet6/ipsec.h>
72 #include <netkey/key.h>
75 #include <uvm/uvm_extern.h>
77 #define KSTRING 256 /* Largest I/O available via this filesystem */
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
},
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
},
99 { DT_DIR
, N("ipsecsa"), 0, KFSipsecsadir
, VDIR
, UDIR_MODE
},
100 { DT_DIR
, N("ipsecsp"), 0, KFSipsecspdir
, VDIR
, UDIR_MODE
},
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
},
107 { DT_DIR
, N("root"), 0, KFSnull
, VDIR
, DIR_MODE
},
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
},
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
},
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
};
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]);
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 */
153 int kernfs_try_fileop(kfstype
, kfsfileop
, void *, int);
154 int kernfs_try_xread(kfstype
, const struct kernfs_node
*, char **,
156 int kernfs_try_xwrite(kfstype
, const struct kernfs_node
*, char *,
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 **,
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 */
262 const struct vnodeopv_desc kernfs_vnodeop_opv_desc
=
263 { &kernfs_vnodeop_p
, kernfs_vnodeop_entries
};
266 kernfs_fileop_compare(struct kernfs_fileop
*a
, struct kernfs_fileop
*b
)
268 if (a
->kf_type
< b
->kf_type
)
270 if (a
->kf_type
> b
->kf_type
)
272 if (a
->kf_fileop
< b
->kf_fileop
)
274 if (a
->kf_fileop
> b
->kf_fileop
)
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
);
285 kernfs_alloctype(int nkf
, const struct kernfs_fileop
*kf
)
287 static u_char nextfreetype
= KFSlasttype
;
288 struct kernfs_fileop
*dkf
, *fkf
, skf
;
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
;
318 skf
.kf_fileop
= fileop
;
319 if ((kf
= SPLAY_FIND(kfsfileoptree
, &kfsfileoptree
, &skf
)))
321 return kf
->kf_vop(v
);
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
;
332 skf
.kf_fileop
= KERNFS_XREAD
;
333 if ((kf
= SPLAY_FIND(kfsfileoptree
, &kfsfileoptree
, &skf
)))
335 return kf
->kf_xread(kfs
, bfp
, len
);
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
;
346 skf
.kf_fileop
= KERNFS_XWRITE
;
347 if ((kf
= SPLAY_FIND(kfsfileoptree
, &kfsfileoptree
, &skf
)))
349 return kf
->kf_xwrite(kfs
, bf
, len
);
354 kernfs_addentry(kernfs_parentdir_t
*pkt
, kernfs_entry_t
*dkt
)
356 struct kernfs_subdir
*ks
, *parent
;
359 SIMPLEQ_INSERT_TAIL(&dyn_kern_targets
, dkt
, dkt_queue
);
361 if (dkt
->dkt_kt
.kt_vtype
== VDIR
)
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
)
370 if (dkt
->dkt_kt
.kt_vtype
== VDIR
&& dkt
->dkt_kt
.kt_data
== NULL
) {
371 ks
= malloc(sizeof(struct kernfs_subdir
),
373 SIMPLEQ_INIT(&ks
->ks_entries
);
374 ks
->ks_nentries
= 2; /* . and .. */
376 ks
->ks_parent
= pkt
? pkt
: &kern_targets
[0];
377 dkt
->dkt_kt
.kt_data
= ks
;
383 kernfs_xread(struct kernfs_node
*kfs
, int off
, char **bufp
, size_t len
, size_t *wrlen
)
385 const struct kern_target
*kt
;
393 switch (kfs
->kfs_type
) {
398 snprintf(*bufp
, len
, "%lld %ld\n", (long long)tv
.tv_sec
,
404 int *ip
= kt
->kt_data
;
406 snprintf(*bufp
, len
, "%d\n", *ip
);
411 char *cp
= kt
->kt_data
;
421 * deal with cases where the message buffer has
424 if (!msgbufenabled
|| msgbufp
->msg_magic
!= MSG_MAGIC
) {
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
) {
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
;
453 size_t xlen
= hostnamelen
;
455 if (xlen
>= (len
- 2))
458 memcpy(*bufp
, cp
, xlen
);
459 (*bufp
)[xlen
] = '\n';
460 (*bufp
)[xlen
+1] = '\0';
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
);
474 if (key_setdumpsa_spi
== NULL
)
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
));
483 if (off
>= m
->m_pkthdr
.len
) {
488 if (len
> m
->m_pkthdr
.len
- off
)
489 len
= m
->m_pkthdr
.len
- off
;
490 m_copydata(m
, off
, len
, *bufp
);
497 * Note that SP configuration could be changed during the
498 * read operation, resulting in garbled output.
500 if (key_getspbyid
== NULL
)
503 struct secpolicy
*sp
;
505 sp
= key_getspbyid(kfs
->kfs_value
);
511 m
= key_setdumpsp((struct secpolicy
*)kfs
->kfs_v
,
512 SADB_X_SPDGET
, 0, 0);
515 if (off
>= m
->m_pkthdr
.len
) {
520 if (len
> m
->m_pkthdr
.len
- off
)
521 len
= m
->m_pkthdr
.len
- off
;
522 m_copydata(m
, off
, len
, *bufp
);
529 err
= kernfs_try_xread(kfs
->kfs_type
, kfs
, bufp
, len
,
546 kernfs_xwrite(const struct kernfs_node
*kfs
, char *bf
, size_t len
)
549 switch (kfs
->kfs_type
) {
551 if (bf
[len
-1] == '\n')
553 memcpy(hostname
, bf
, len
);
554 hostname
[len
] = '\0';
555 hostnamelen
= (size_t) len
;
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;
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
;
592 if (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
)
595 if (cnp
->cn_namelen
== 1 && *pname
== '.') {
602 switch (kfs
->kfs_type
) {
605 * Shouldn't get here with .. in the root node.
607 if (cnp
->cn_flags
& ISDOTDOT
)
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)
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) {
626 error
= kernfs_allocvp(dvp
->v_mount
, vpp
, kt
->kt_tag
, kt
, 0);
630 ks
= (struct kernfs_subdir
*)kfs
->kfs_kt
->kt_data
;
631 if (cnp
->cn_flags
& ISDOTDOT
) {
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) {
647 if (cnp
->cn_flags
& ISDOTDOT
) {
648 kt
= &kern_targets
[0];
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)
660 id
= strtoul(pname
, &ep
, 10);
661 if (!ep
|| *ep
|| ep
== pname
)
664 error
= kernfs_allocvp(dvp
->v_mount
, vpp
, KFSipsecsa
, &ipsecsa_kt
, id
);
668 if (cnp
->cn_flags
& ISDOTDOT
) {
669 kt
= &kern_targets
[0];
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)
681 id
= strtoul(pname
, &ep
, 10);
682 if (!ep
|| *ep
|| ep
== pname
)
685 error
= kernfs_allocvp(dvp
->v_mount
, vpp
, KFSipsecsp
, &ipsecsp_kt
, id
);
693 return (cnp
->cn_nameiop
== LOOKUP
? ENOENT
: EROFS
);
699 struct vop_open_args
/* {
704 struct kernfs_node
*kfs
= VTOKERN(ap
->a_vp
);
707 struct secpolicy
*sp
;
710 switch (kfs
->kfs_type
) {
713 if (key_setdumpsa_spi
== NULL
)
715 m
= key_setdumpsa_spi(htonl(kfs
->kfs_value
));
723 if (key_getspbyid
== NULL
)
725 sp
= key_getspbyid(kfs
->kfs_value
);
734 return kernfs_try_fileop(kfs
->kfs_type
, KERNFS_FILEOP_OPEN
,
740 kernfs_close(void *v
)
742 struct vop_close_args
/* {
747 struct kernfs_node
*kfs
= VTOKERN(ap
->a_vp
);
749 switch (kfs
->kfs_type
) {
752 if (key_freesp
== NULL
)
754 key_freesp((struct secpolicy
*)kfs
->kfs_v
);
759 return kernfs_try_fileop(kfs
->kfs_type
, KERNFS_FILEOP_CLOSE
,
767 kernfs_check_possible(struct vnode
*vp
, mode_t mode
)
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
,
782 kernfs_access(void *v
)
784 struct vop_access_args
/* {
792 if ((error
= VOP_GETATTR(ap
->a_vp
, &va
, ap
->a_cred
)) != 0)
795 error
= kernfs_check_possible(ap
->a_vp
, ap
->a_mode
);
799 error
= kernfs_check_permitted(&va
, ap
->a_mode
, ap
->a_cred
);
805 kernfs_default_fileop_getattr(void *v
)
807 struct vop_getattr_args
/* {
812 struct vattr
*vap
= ap
->a_vap
;
815 vap
->va_bytes
= vap
->va_size
= 0;
821 kernfs_getattr(void *v
)
823 struct vop_getattr_args
/* {
828 struct kernfs_node
*kfs
= VTOKERN(ap
->a_vp
);
829 struct kernfs_subdir
*ks
;
830 struct vattr
*vap
= ap
->a_vap
;
832 char strbuf
[KSTRING
], *bf
;
836 vap
->va_type
= ap
->a_vp
->v_type
;
839 vap
->va_mode
= kfs
->kfs_mode
;
840 vap
->va_fileid
= kfs
->kfs_fileno
;
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
;
849 getnanotime(&vap
->va_ctime
);
851 vap
->va_atime
= vap
->va_mtime
= vap
->va_ctime
;
857 switch (kfs
->kfs_type
) {
859 vap
->va_nlink
= nkern_dirs
;
860 vap
->va_bytes
= vap
->va_size
= DEV_BSIZE
;
865 vap
->va_bytes
= vap
->va_size
= DEV_BSIZE
;
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
;
890 error
= kernfs_xread(kfs
, total
, &bf
,
891 sizeof(strbuf
), &nread
);
893 } while (error
== 0 && nread
!= 0);
894 vap
->va_bytes
= vap
->va_size
= total
;
901 vap
->va_bytes
= vap
->va_size
= DEV_BSIZE
;
906 error
= kernfs_try_fileop(kfs
->kfs_type
,
907 KERNFS_FILEOP_GETATTR
, v
, EINVAL
);
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.
929 kernfs_default_xread(void *v
)
931 struct vop_read_args
/* {
937 struct uio
*uio
= ap
->a_uio
;
938 struct kernfs_node
*kfs
= VTOKERN(ap
->a_vp
);
939 char strbuf
[KSTRING
], *bf
;
944 if (ap
->a_vp
->v_type
== VDIR
)
947 off
= (int)uio
->uio_offset
;
948 /* Don't allow negative offsets */
953 if ((error
= kernfs_xread(kfs
, off
, &bf
, sizeof(strbuf
), &len
)) == 0)
954 error
= uiomove(bf
, len
, uio
);
961 struct vop_read_args
/* {
965 struct ucred *a_cred;
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
,
978 kernfs_default_xwrite(void *v
)
980 struct vop_write_args
/* {
986 struct kernfs_node
*kfs
= VTOKERN(ap
->a_vp
);
987 struct uio
*uio
= ap
->a_uio
;
990 char strbuf
[KSTRING
];
992 if (uio
->uio_offset
!= 0)
995 xlen
= min(uio
->uio_resid
, KSTRING
-1);
996 if ((error
= uiomove(strbuf
, xlen
, uio
)) != 0)
999 if (uio
->uio_resid
!= 0)
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
/* {
1014 kauth_cred_t a_cred;
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
,
1027 kernfs_ioctl(void *v
)
1029 struct vop_ioctl_args
/* {
1030 const struct vnodeop_desc *a_desc;
1035 kauth_cred_t a_cred;
1037 struct kernfs_node
*kfs
= VTOKERN(ap
->a_vp
);
1039 return kernfs_try_fileop(kfs
->kfs_type
, KERNFS_FILEOP_IOCTL
, v
,
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
;
1051 if ((error
= kernfs_allocvp(ap
->a_vp
->v_mount
, &vp
, kt
->kt_tag
, kt
,
1054 if (kt
->kt_tag
== KFSdevice
) {
1057 error
= VOP_GETATTR(vp
, &va
, ap
->a_cred
);
1061 d
->d_fileno
= va
.va_fileid
;
1064 d
->d_fileno
= kfs
->kfs_fileno
;
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
;
1080 d
->d_fileno
= thisdir_kfs
->kfs_fileno
;
1089 if (ikt
!= thisdir_kfs
->kfs_kt
) {
1090 if ((error
= kernfs_setdirentfileno_kt(d
, ikt
, 0, ap
)) != 0)
1093 d
->d_fileno
= thisdir_kfs
->kfs_fileno
;
1098 kernfs_readdir(void *v
)
1100 struct vop_readdir_args
/* {
1103 kauth_cred_t a_cred;
1108 struct uio
*uio
= ap
->a_uio
;
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
;
1116 off_t
*cookies
= NULL
;
1117 int ncookies
= 0, n
;
1119 struct secasvar
*sav
, *sav2
;
1120 struct secpolicy
*sp
;
1123 if (uio
->uio_resid
< UIO_MX
)
1125 if (uio
->uio_offset
< 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
) {
1136 if (i
>= nkern_targets
)
1139 if (ap
->a_ncookies
) {
1140 ncookies
= min(ncookies
, (nkern_targets
- i
));
1141 cookies
= malloc(ncookies
* sizeof(off_t
), M_TEMP
,
1143 *ap
->a_cookies
= cookies
;
1147 for (; i
< nkern_targets
&& uio
->uio_resid
>= UIO_MX
; i
++) {
1148 if (i
< static_nkern_targets
)
1149 kt
= &kern_targets
[i
];
1152 dkt
= SIMPLEQ_FIRST(&dyn_kern_targets
);
1153 for (j
= static_nkern_targets
; j
< i
&&
1155 dkt
= SIMPLEQ_NEXT(dkt
, dkt_queue
);
1159 dkt
= SIMPLEQ_NEXT(dkt
, dkt_queue
);
1165 if (kt
->kt_tag
== KFSdevice
) {
1166 dev_t
*dp
= kt
->kt_data
;
1170 !vfinddev(*dp
, kt
->kt_vtype
, &fvp
))
1173 d
.d_namlen
= kt
->kt_namlen
;
1174 if ((error
= kernfs_setdirentfileno(&d
, i
, kfs
,
1175 &kern_targets
[0], kt
, ap
)) != 0)
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)
1192 if (ap
->a_ncookies
) {
1193 ncookies
= min(ncookies
, (2 - i
));
1194 cookies
= malloc(ncookies
* sizeof(off_t
), M_TEMP
,
1196 *ap
->a_cookies
= cookies
;
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)
1216 ks
= (struct kernfs_subdir
*)kfs
->kfs_kt
->kt_data
;
1217 if (i
>= ks
->ks_nentries
)
1220 if (ap
->a_ncookies
) {
1221 ncookies
= min(ncookies
, (ks
->ks_nentries
- i
));
1222 cookies
= malloc(ncookies
* sizeof(off_t
), M_TEMP
,
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
);
1231 for (; i
< ks
->ks_nentries
&& uio
->uio_resid
>= UIO_MX
; i
++) {
1233 kt
= &subdir_targets
[i
];
1235 /* check if ks_nentries lied to us */
1239 dkt
= SIMPLEQ_NEXT(dkt
, dkt_queue
);
1241 if (kt
->kt_tag
== KFSdevice
) {
1242 dev_t
*dp
= kt
->kt_data
;
1246 !vfinddev(*dp
, kt
->kt_vtype
, &fvp
))
1249 d
.d_namlen
= kt
->kt_namlen
;
1250 if ((error
= kernfs_setdirentfileno(&d
, i
, kfs
,
1251 ks
->ks_parent
, kt
, ap
)) != 0)
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)
1266 /* count SA in the system */
1268 if (&satailq
== NULL
)
1270 TAILQ_FOREACH(sav
, &satailq
, tailq
) {
1271 for (sav2
= TAILQ_FIRST(&satailq
);
1273 sav2
= TAILQ_NEXT(sav2
, tailq
)) {
1274 if (sav
->spi
== sav2
->spi
) {
1275 /* multiple SA with same SPI */
1279 if (sav
== sav2
|| sav
->spi
!= sav2
->spi
)
1283 if (i
>= nipsecsa_targets
+ n
)
1286 if (ap
->a_ncookies
) {
1287 ncookies
= min(ncookies
, (n
- i
));
1288 cookies
= malloc(ncookies
* sizeof(off_t
), M_TEMP
,
1290 *ap
->a_cookies
= cookies
;
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)
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)
1313 TAILQ_FOREACH(sav
, &satailq
, tailq
) {
1314 for (sav2
= TAILQ_FIRST(&satailq
);
1316 sav2
= TAILQ_NEXT(sav2
, tailq
)) {
1317 if (sav
->spi
== sav2
->spi
) {
1318 /* multiple SA with same SPI */
1322 if (sav
!= sav2
&& sav
->spi
== sav2
->spi
)
1324 if (uio
->uio_resid
< UIO_MX
)
1326 if ((error
= kernfs_setdirentfileno_kt(&d
, &ipsecsa_kt
,
1327 sav
->spi
, ap
)) != 0)
1329 d
.d_namlen
= snprintf(d
.d_name
, sizeof(d
.d_name
),
1330 "%u", ntohl(sav
->spi
));
1332 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
1343 /* count SP in the system */
1344 if (&sptailq
== NULL
)
1348 TAILQ_FOREACH(sp
, &sptailq
, tailq
)
1351 if (i
>= nipsecsp_targets
+ n
)
1354 if (ap
->a_ncookies
) {
1355 ncookies
= min(ncookies
, (n
- i
));
1356 cookies
= malloc(ncookies
* sizeof(off_t
), M_TEMP
,
1358 *ap
->a_cookies
= cookies
;
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)
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)
1381 TAILQ_FOREACH(sp
, &sptailq
, tailq
) {
1382 if (uio
->uio_resid
< UIO_MX
)
1384 if ((error
= kernfs_setdirentfileno_kt(&d
, &ipsecsp_kt
,
1387 d
.d_namlen
= snprintf(d
.d_name
, sizeof(d
.d_name
),
1390 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
1406 if (ap
->a_ncookies
) {
1409 free(*ap
->a_cookies
, M_TEMP
);
1410 *ap
->a_ncookies
= 0;
1411 *ap
->a_cookies
= NULL
;
1413 *ap
->a_ncookies
= ncookies
;
1416 uio
->uio_offset
= i
;
1421 kernfs_inactive(void *v
)
1423 struct vop_inactive_args
/* {
1427 struct vnode
*vp
= ap
->a_vp
;
1428 const struct kernfs_node
*kfs
= VTOKERN(ap
->a_vp
);
1431 struct secpolicy
*sp
;
1434 *ap
->a_recycle
= false;
1435 switch (kfs
->kfs_type
) {
1438 if (key_setdumpsa_spi
== NULL
)
1440 m
= key_setdumpsa_spi(htonl(kfs
->kfs_value
));
1444 *ap
->a_recycle
= true;
1447 if (key_getspbyid
== NULL
)
1449 sp
= key_getspbyid(kfs
->kfs_value
);
1453 *ap
->a_recycle
= true;
1465 kernfs_reclaim(void *v
)
1467 struct vop_reclaim_args
/* {
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
/* {
1483 register_t *a_retval;
1486 switch (ap
->a_name
) {
1488 *ap
->a_retval
= LINK_MAX
;
1491 *ap
->a_retval
= MAX_CANON
;
1494 *ap
->a_retval
= MAX_INPUT
;
1497 *ap
->a_retval
= PIPE_BUF
;
1499 case _PC_CHOWN_RESTRICTED
:
1503 *ap
->a_retval
= _POSIX_VDISABLE
;
1515 * Print out the contents of a /dev/fd vnode.
1519 kernfs_print(void *v
)
1522 printf("tag VT_KERNFS, kernfs vnode\n");
1527 kernfs_link(void *v
)
1529 struct vop_link_args
/* {
1530 struct vnode *a_dvp;
1532 struct componentname *a_cnp;
1535 VOP_ABORTOP(ap
->a_dvp
, ap
->a_cnp
);
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;
1551 VOP_ABORTOP(ap
->a_dvp
, ap
->a_cnp
);