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