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