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