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