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