1 /* $NetBSD: kernfs_vnops.c,v 1.140 2010/01/22 22:46:00 njoly 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.140 2010/01/22 22:46:00 njoly 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(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen) 384 { 385 const struct kern_target *kt; 386 #ifdef IPSEC 387 struct mbuf *m; 388 #endif 389 int err; 390 391 kt = kfs->kfs_kt; 392 393 switch (kfs->kfs_type) { 394 case KFStime: { 395 struct timeval tv; 396 397 microtime(&tv); 398 snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec, 399 (long)tv.tv_usec); 400 break; 401 } 402 403 case KFSint: { 404 int *ip = kt->kt_data; 405 406 snprintf(*bufp, len, "%d\n", *ip); 407 break; 408 } 409 410 case KFSstring: { 411 char *cp = kt->kt_data; 412 413 *bufp = cp; 414 break; 415 } 416 417 case KFSmsgbuf: { 418 long n; 419 420 /* 421 * deal with cases where the message buffer has 422 * become corrupted. 423 */ 424 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 425 msgbufenabled = 0; 426 return (ENXIO); 427 } 428 429 /* 430 * Note that reads of /kern/msgbuf won't necessarily yield 431 * consistent results, if the message buffer is modified 432 * while the read is in progress. The worst that can happen 433 * is that incorrect data will be read. There's no way 434 * that this can crash the system unless the values in the 435 * message buffer header are corrupted, but that'll cause 436 * the system to die anyway. 437 */ 438 if (off >= msgbufp->msg_bufs) { 439 *wrlen = 0; 440 return (0); 441 } 442 n = msgbufp->msg_bufx + off; 443 if (n >= msgbufp->msg_bufs) 444 n -= msgbufp->msg_bufs; 445 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off); 446 *bufp = msgbufp->msg_bufc + n; 447 *wrlen = len; 448 return (0); 449 } 450 451 case KFShostname: { 452 char *cp = hostname; 453 size_t xlen = hostnamelen; 454 455 if (xlen >= (len - 2)) 456 return (EINVAL); 457 458 memcpy(*bufp, cp, xlen); 459 (*bufp)[xlen] = '\n'; 460 (*bufp)[xlen+1] = '\0'; 461 break; 462 } 463 464 case KFSavenrun: 465 averunnable.fscale = FSCALE; 466 snprintf(*bufp, len, "%d %d %d %ld\n", 467 averunnable.ldavg[0], averunnable.ldavg[1], 468 averunnable.ldavg[2], averunnable.fscale); 469 break; 470 471 #ifdef IPSEC 472 case KFSipsecsa: 473 if (key_setdumpsa_spi == NULL) 474 return 0; 475 /* 476 * Note that SA configuration could be changed during the 477 * read operation, resulting in garbled output. 478 */ 479 m = key_setdumpsa_spi(htonl(kfs->kfs_value)); 480 if (!m) 481 return (ENOBUFS); 482 if (off >= m->m_pkthdr.len) { 483 *wrlen = 0; 484 m_freem(m); 485 return (0); 486 } 487 if (len > m->m_pkthdr.len - off) 488 len = m->m_pkthdr.len - off; 489 m_copydata(m, off, len, *bufp); 490 *wrlen = len; 491 m_freem(m); 492 return (0); 493 494 case KFSipsecsp: 495 /* 496 * Note that SP configuration could be changed during the 497 * read operation, resulting in garbled output. 498 */ 499 if (key_getspbyid == NULL) 500 return 0; 501 if (!kfs->kfs_v) { 502 struct secpolicy *sp; 503 504 sp = key_getspbyid(kfs->kfs_value); 505 if (sp) 506 kfs->kfs_v = sp; 507 else 508 return (ENOENT); 509 } 510 m = key_setdumpsp((struct secpolicy *)kfs->kfs_v, 511 SADB_X_SPDGET, 0, 0); 512 if (!m) 513 return (ENOBUFS); 514 if (off >= m->m_pkthdr.len) { 515 *wrlen = 0; 516 m_freem(m); 517 return (0); 518 } 519 if (len > m->m_pkthdr.len - off) 520 len = m->m_pkthdr.len - off; 521 m_copydata(m, off, len, *bufp); 522 *wrlen = len; 523 m_freem(m); 524 return (0); 525 #endif 526 527 default: 528 err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len, 529 EOPNOTSUPP); 530 if (err) 531 return err; 532 } 533 534 len = strlen(*bufp); 535 if (len <= off) 536 *wrlen = 0; 537 else { 538 *bufp += off; 539 *wrlen = len - off; 540 } 541 return (0); 542 } 543 544 static int 545 kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len) 546 { 547 548 switch (kfs->kfs_type) { 549 case KFShostname: 550 if (bf[len-1] == '\n') 551 --len; 552 memcpy(hostname, bf, len); 553 hostname[len] = '\0'; 554 hostnamelen = (size_t) len; 555 return (0); 556 557 default: 558 return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO); 559 } 560 } 561 562 563 /* 564 * vp is the current namei directory 565 * ndp is the name to locate in that directory... 566 */ 567 int 568 kernfs_lookup(void *v) 569 { 570 struct vop_lookup_args /* { 571 struct vnode * a_dvp; 572 struct vnode ** a_vpp; 573 struct componentname * a_cnp; 574 } */ *ap = v; 575 struct componentname *cnp = ap->a_cnp; 576 struct vnode **vpp = ap->a_vpp; 577 struct vnode *dvp = ap->a_dvp; 578 const char *pname = cnp->cn_nameptr; 579 const struct kernfs_node *kfs; 580 const struct kern_target *kt; 581 const struct dyn_kern_target *dkt; 582 const struct kernfs_subdir *ks; 583 int error, i; 584 #ifdef IPSEC 585 char *ep; 586 u_int32_t id; 587 #endif 588 589 *vpp = NULLVP; 590 591 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 592 return (EROFS); 593 594 if (cnp->cn_namelen == 1 && *pname == '.') { 595 *vpp = dvp; 596 vref(dvp); 597 return (0); 598 } 599 600 kfs = VTOKERN(dvp); 601 switch (kfs->kfs_type) { 602 case KFSkern: 603 /* 604 * Shouldn't get here with .. in the root node. 605 */ 606 if (cnp->cn_flags & ISDOTDOT) 607 return (EIO); 608 609 for (i = 0; i < static_nkern_targets; i++) { 610 kt = &kern_targets[i]; 611 if (cnp->cn_namelen == kt->kt_namlen && 612 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) 613 goto found; 614 } 615 SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) { 616 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && 617 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { 618 kt = &dkt->dkt_kt; 619 goto found; 620 } 621 } 622 break; 623 624 found: 625 error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0); 626 return (error); 627 628 case KFSsubdir: 629 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 630 if (cnp->cn_flags & ISDOTDOT) { 631 kt = ks->ks_parent; 632 goto found; 633 } 634 635 SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) { 636 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && 637 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { 638 kt = &dkt->dkt_kt; 639 goto found; 640 } 641 } 642 break; 643 644 #ifdef IPSEC 645 case KFSipsecsadir: 646 if (cnp->cn_flags & ISDOTDOT) { 647 kt = &kern_targets[0]; 648 goto found; 649 } 650 651 for (i = 2; i < nipsecsa_targets; i++) { 652 kt = &ipsecsa_targets[i]; 653 if (cnp->cn_namelen == kt->kt_namlen && 654 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) 655 goto found; 656 } 657 658 ep = NULL; 659 id = strtoul(pname, &ep, 10); 660 if (!ep || *ep || ep == pname) 661 break; 662 663 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id); 664 return (error); 665 666 case KFSipsecspdir: 667 if (cnp->cn_flags & ISDOTDOT) { 668 kt = &kern_targets[0]; 669 goto found; 670 } 671 672 for (i = 2; i < nipsecsp_targets; i++) { 673 kt = &ipsecsp_targets[i]; 674 if (cnp->cn_namelen == kt->kt_namlen && 675 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) 676 goto found; 677 } 678 679 ep = NULL; 680 id = strtoul(pname, &ep, 10); 681 if (!ep || *ep || ep == pname) 682 break; 683 684 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id); 685 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(void *v) 697 { 698 struct vop_open_args /* { 699 struct vnode *a_vp; 700 int a_mode; 701 kauth_cred_t a_cred; 702 } */ *ap = v; 703 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 704 #ifdef IPSEC 705 struct mbuf *m; 706 struct secpolicy *sp; 707 #endif 708 709 switch (kfs->kfs_type) { 710 #ifdef IPSEC 711 case KFSipsecsa: 712 if (key_setdumpsa_spi == NULL) 713 return 0; 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 if (key_getspbyid == NULL) 723 return 0; 724 sp = key_getspbyid(kfs->kfs_value); 725 if (sp) { 726 kfs->kfs_v = sp; 727 return (0); 728 } else 729 return (ENOENT); 730 #endif 731 732 default: 733 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN, 734 v, 0); 735 } 736 } 737 738 int 739 kernfs_close(void *v) 740 { 741 struct vop_close_args /* { 742 struct vnode *a_vp; 743 int a_fflag; 744 kauth_cred_t a_cred; 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 if (key_freesp == NULL) 752 return 0; 753 key_freesp((struct secpolicy *)kfs->kfs_v); 754 break; 755 #endif 756 757 default: 758 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE, 759 v, 0); 760 } 761 762 return (0); 763 } 764 765 static int 766 kernfs_check_possible(struct vnode *vp, mode_t mode) 767 { 768 769 return 0; 770 } 771 772 static int 773 kernfs_check_permitted(struct vattr *va, mode_t mode, kauth_cred_t cred) 774 { 775 776 return genfs_can_access(va->va_type, va->va_mode, va->va_uid, va->va_gid, 777 mode, cred); 778 } 779 780 int 781 kernfs_access(void *v) 782 { 783 struct vop_access_args /* { 784 struct vnode *a_vp; 785 int a_mode; 786 kauth_cred_t a_cred; 787 } */ *ap = v; 788 struct vattr va; 789 int error; 790 791 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0) 792 return (error); 793 794 error = kernfs_check_possible(ap->a_vp, ap->a_mode); 795 if (error) 796 return error; 797 798 error = kernfs_check_permitted(&va, ap->a_mode, ap->a_cred); 799 800 return error; 801 } 802 803 static int 804 kernfs_default_fileop_getattr(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 } */ *ap = v; 811 struct vattr *vap = ap->a_vap; 812 813 vap->va_nlink = 1; 814 vap->va_bytes = vap->va_size = 0; 815 816 return 0; 817 } 818 819 int 820 kernfs_getattr(void *v) 821 { 822 struct vop_getattr_args /* { 823 struct vnode *a_vp; 824 struct vattr *a_vap; 825 kauth_cred_t a_cred; 826 } */ *ap = v; 827 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 828 struct kernfs_subdir *ks; 829 struct vattr *vap = ap->a_vap; 830 int error = 0; 831 char strbuf[KSTRING], *bf; 832 size_t nread, total; 833 834 vattr_null(vap); 835 vap->va_type = ap->a_vp->v_type; 836 vap->va_uid = 0; 837 vap->va_gid = 0; 838 vap->va_mode = kfs->kfs_mode; 839 vap->va_fileid = kfs->kfs_fileno; 840 vap->va_flags = 0; 841 vap->va_size = 0; 842 vap->va_blocksize = DEV_BSIZE; 843 /* Make all times be current TOD, except for the "boottime" node. */ 844 if (kfs->kfs_kt->kt_namlen == 8 && 845 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) { 846 vap->va_ctime = boottime; 847 } else { 848 getnanotime(&vap->va_ctime); 849 } 850 vap->va_atime = vap->va_mtime = vap->va_ctime; 851 vap->va_gen = 0; 852 vap->va_flags = 0; 853 vap->va_rdev = 0; 854 vap->va_bytes = 0; 855 856 switch (kfs->kfs_type) { 857 case KFSkern: 858 vap->va_nlink = nkern_dirs; 859 vap->va_bytes = vap->va_size = DEV_BSIZE; 860 break; 861 862 case KFSroot: 863 vap->va_nlink = 1; 864 vap->va_bytes = vap->va_size = DEV_BSIZE; 865 break; 866 867 case KFSsubdir: 868 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 869 vap->va_nlink = ks->ks_dirs; 870 vap->va_bytes = vap->va_size = DEV_BSIZE; 871 break; 872 873 case KFSnull: 874 case KFStime: 875 case KFSint: 876 case KFSstring: 877 case KFShostname: 878 case KFSavenrun: 879 case KFSdevice: 880 case KFSmsgbuf: 881 #ifdef IPSEC 882 case KFSipsecsa: 883 case KFSipsecsp: 884 #endif 885 vap->va_nlink = 1; 886 total = 0; 887 do { 888 bf = strbuf; 889 error = kernfs_xread(kfs, total, &bf, 890 sizeof(strbuf), &nread); 891 total += nread; 892 } while (error == 0 && nread != 0); 893 vap->va_bytes = vap->va_size = total; 894 break; 895 896 #ifdef IPSEC 897 case KFSipsecsadir: 898 case KFSipsecspdir: 899 vap->va_nlink = 2; 900 vap->va_bytes = vap->va_size = DEV_BSIZE; 901 break; 902 #endif 903 904 default: 905 error = kernfs_try_fileop(kfs->kfs_type, 906 KERNFS_FILEOP_GETATTR, v, EINVAL); 907 break; 908 } 909 910 return (error); 911 } 912 913 /*ARGSUSED*/ 914 int 915 kernfs_setattr(void *v) 916 { 917 918 /* 919 * Silently ignore attribute changes. 920 * This allows for open with truncate to have no 921 * effect until some data is written. I want to 922 * do it this way because all writes are atomic. 923 */ 924 return (0); 925 } 926 927 int 928 kernfs_default_xread(void *v) 929 { 930 struct vop_read_args /* { 931 struct vnode *a_vp; 932 struct uio *a_uio; 933 int a_ioflag; 934 kauth_cred_t a_cred; 935 } */ *ap = v; 936 struct uio *uio = ap->a_uio; 937 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 938 char strbuf[KSTRING], *bf; 939 int off; 940 size_t len; 941 int error; 942 943 if (ap->a_vp->v_type == VDIR) 944 return (EOPNOTSUPP); 945 946 off = (int)uio->uio_offset; 947 /* Don't allow negative offsets */ 948 if (off < 0) 949 return EINVAL; 950 951 bf = strbuf; 952 if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0) 953 error = uiomove(bf, len, uio); 954 return (error); 955 } 956 957 int 958 kernfs_read(void *v) 959 { 960 struct vop_read_args /* { 961 struct vnode *a_vp; 962 struct uio *a_uio; 963 int a_ioflag; 964 struct ucred *a_cred; 965 } */ *ap = v; 966 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 967 968 if (kfs->kfs_type < KFSlasttype) { 969 /* use default function */ 970 return kernfs_default_xread(v); 971 } 972 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v, 973 EOPNOTSUPP); 974 } 975 976 static int 977 kernfs_default_xwrite(void *v) 978 { 979 struct vop_write_args /* { 980 struct vnode *a_vp; 981 struct uio *a_uio; 982 int a_ioflag; 983 kauth_cred_t a_cred; 984 } */ *ap = v; 985 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 986 struct uio *uio = ap->a_uio; 987 int error; 988 size_t xlen; 989 char strbuf[KSTRING]; 990 991 if (uio->uio_offset != 0) 992 return (EINVAL); 993 994 xlen = min(uio->uio_resid, KSTRING-1); 995 if ((error = uiomove(strbuf, xlen, uio)) != 0) 996 return (error); 997 998 if (uio->uio_resid != 0) 999 return (EIO); 1000 1001 strbuf[xlen] = '\0'; 1002 xlen = strlen(strbuf); 1003 return (kernfs_xwrite(kfs, strbuf, xlen)); 1004 } 1005 1006 int 1007 kernfs_write(void *v) 1008 { 1009 struct vop_write_args /* { 1010 struct vnode *a_vp; 1011 struct uio *a_uio; 1012 int a_ioflag; 1013 kauth_cred_t a_cred; 1014 } */ *ap = v; 1015 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 1016 1017 if (kfs->kfs_type < KFSlasttype) { 1018 /* use default function */ 1019 return kernfs_default_xwrite(v); 1020 } 1021 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 1022 EOPNOTSUPP); 1023 } 1024 1025 int 1026 kernfs_ioctl(void *v) 1027 { 1028 struct vop_ioctl_args /* { 1029 const struct vnodeop_desc *a_desc; 1030 struct vnode *a_vp; 1031 u_long a_command; 1032 void *a_data; 1033 int a_fflag; 1034 kauth_cred_t a_cred; 1035 } */ *ap = v; 1036 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 1037 1038 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v, 1039 EPASSTHROUGH); 1040 } 1041 1042 static int 1043 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt, 1044 u_int32_t value, struct vop_readdir_args *ap) 1045 { 1046 struct kernfs_node *kfs; 1047 struct vnode *vp; 1048 int error; 1049 1050 if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt, 1051 value)) != 0) 1052 return error; 1053 if (kt->kt_tag == KFSdevice) { 1054 struct vattr va; 1055 1056 error = VOP_GETATTR(vp, &va, ap->a_cred); 1057 if (error != 0) { 1058 return error; 1059 } 1060 d->d_fileno = va.va_fileid; 1061 } else { 1062 kfs = VTOKERN(vp); 1063 d->d_fileno = kfs->kfs_fileno; 1064 } 1065 vput(vp); 1066 return 0; 1067 } 1068 1069 static int 1070 kernfs_setdirentfileno(struct dirent *d, off_t entry, 1071 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt, 1072 const struct kern_target *kt, struct vop_readdir_args *ap) 1073 { 1074 const struct kern_target *ikt; 1075 int error; 1076 1077 switch (entry) { 1078 case 0: 1079 d->d_fileno = thisdir_kfs->kfs_fileno; 1080 return 0; 1081 case 1: 1082 ikt = parent_kt; 1083 break; 1084 default: 1085 ikt = kt; 1086 break; 1087 } 1088 if (ikt != thisdir_kfs->kfs_kt) { 1089 if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0) 1090 return error; 1091 } else 1092 d->d_fileno = thisdir_kfs->kfs_fileno; 1093 return 0; 1094 } 1095 1096 int 1097 kernfs_readdir(void *v) 1098 { 1099 struct vop_readdir_args /* { 1100 struct vnode *a_vp; 1101 struct uio *a_uio; 1102 kauth_cred_t a_cred; 1103 int *a_eofflag; 1104 off_t **a_cookies; 1105 int a_*ncookies; 1106 } */ *ap = v; 1107 struct uio *uio = ap->a_uio; 1108 struct dirent d; 1109 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 1110 const struct kern_target *kt; 1111 const struct dyn_kern_target *dkt = NULL; 1112 const struct kernfs_subdir *ks; 1113 off_t i, j; 1114 int error; 1115 off_t *cookies = NULL; 1116 int ncookies = 0, n; 1117 #ifdef IPSEC 1118 struct secasvar *sav, *sav2; 1119 struct secpolicy *sp; 1120 #endif 1121 1122 if (uio->uio_resid < UIO_MX) 1123 return (EINVAL); 1124 if (uio->uio_offset < 0) 1125 return (EINVAL); 1126 1127 error = 0; 1128 i = uio->uio_offset; 1129 memset(&d, 0, sizeof(d)); 1130 d.d_reclen = UIO_MX; 1131 ncookies = uio->uio_resid / UIO_MX; 1132 1133 switch (kfs->kfs_type) { 1134 case KFSkern: 1135 if (i >= nkern_targets) 1136 return (0); 1137 1138 if (ap->a_ncookies) { 1139 ncookies = min(ncookies, (nkern_targets - i)); 1140 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1141 M_WAITOK); 1142 *ap->a_cookies = cookies; 1143 } 1144 1145 n = 0; 1146 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) { 1147 if (i < static_nkern_targets) 1148 kt = &kern_targets[i]; 1149 else { 1150 if (dkt == NULL) { 1151 dkt = SIMPLEQ_FIRST(&dyn_kern_targets); 1152 for (j = static_nkern_targets; j < i && 1153 dkt != NULL; j++) 1154 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1155 if (j != i) 1156 break; 1157 } else { 1158 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1159 } 1160 if (dkt == NULL) 1161 break; 1162 kt = &dkt->dkt_kt; 1163 } 1164 if (kt->kt_tag == KFSdevice) { 1165 dev_t *dp = kt->kt_data; 1166 struct vnode *fvp; 1167 1168 if (*dp == NODEV || 1169 !vfinddev(*dp, kt->kt_vtype, &fvp)) 1170 continue; 1171 } 1172 d.d_namlen = kt->kt_namlen; 1173 if ((error = kernfs_setdirentfileno(&d, i, kfs, 1174 &kern_targets[0], kt, ap)) != 0) 1175 break; 1176 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1177 d.d_type = kt->kt_type; 1178 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1179 break; 1180 if (cookies) 1181 *cookies++ = i + 1; 1182 n++; 1183 } 1184 ncookies = n; 1185 break; 1186 1187 case KFSroot: 1188 if (i >= 2) 1189 return 0; 1190 1191 if (ap->a_ncookies) { 1192 ncookies = min(ncookies, (2 - i)); 1193 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1194 M_WAITOK); 1195 *ap->a_cookies = cookies; 1196 } 1197 1198 n = 0; 1199 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { 1200 kt = &kern_targets[i]; 1201 d.d_namlen = kt->kt_namlen; 1202 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0); 1203 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1204 d.d_type = kt->kt_type; 1205 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1206 break; 1207 if (cookies) 1208 *cookies++ = i + 1; 1209 n++; 1210 } 1211 ncookies = n; 1212 break; 1213 1214 case KFSsubdir: 1215 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 1216 if (i >= ks->ks_nentries) 1217 return (0); 1218 1219 if (ap->a_ncookies) { 1220 ncookies = min(ncookies, (ks->ks_nentries - i)); 1221 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1222 M_WAITOK); 1223 *ap->a_cookies = cookies; 1224 } 1225 1226 dkt = SIMPLEQ_FIRST(&ks->ks_entries); 1227 for (j = 0; j < i && dkt != NULL; j++) 1228 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1229 n = 0; 1230 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) { 1231 if (i < 2) 1232 kt = &subdir_targets[i]; 1233 else { 1234 /* check if ks_nentries lied to us */ 1235 if (dkt == NULL) 1236 break; 1237 kt = &dkt->dkt_kt; 1238 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1239 } 1240 if (kt->kt_tag == KFSdevice) { 1241 dev_t *dp = kt->kt_data; 1242 struct vnode *fvp; 1243 1244 if (*dp == NODEV || 1245 !vfinddev(*dp, kt->kt_vtype, &fvp)) 1246 continue; 1247 } 1248 d.d_namlen = kt->kt_namlen; 1249 if ((error = kernfs_setdirentfileno(&d, i, kfs, 1250 ks->ks_parent, kt, ap)) != 0) 1251 break; 1252 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1253 d.d_type = kt->kt_type; 1254 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1255 break; 1256 if (cookies) 1257 *cookies++ = i + 1; 1258 n++; 1259 } 1260 ncookies = n; 1261 break; 1262 1263 #ifdef IPSEC 1264 case KFSipsecsadir: 1265 /* count SA in the system */ 1266 n = 0; 1267 if (&satailq == NULL) 1268 return 0; 1269 TAILQ_FOREACH(sav, &satailq, tailq) { 1270 for (sav2 = TAILQ_FIRST(&satailq); 1271 sav2 != sav; 1272 sav2 = TAILQ_NEXT(sav2, tailq)) { 1273 if (sav->spi == sav2->spi) { 1274 /* multiple SA with same SPI */ 1275 break; 1276 } 1277 } 1278 if (sav == sav2 || sav->spi != sav2->spi) 1279 n++; 1280 } 1281 1282 if (i >= nipsecsa_targets + n) 1283 return (0); 1284 1285 if (ap->a_ncookies) { 1286 ncookies = min(ncookies, (n - i)); 1287 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1288 M_WAITOK); 1289 *ap->a_cookies = cookies; 1290 } 1291 1292 n = 0; 1293 for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) { 1294 kt = &ipsecsa_targets[i]; 1295 d.d_namlen = kt->kt_namlen; 1296 if ((error = kernfs_setdirentfileno(&d, i, kfs, 1297 &kern_targets[0], kt, ap)) != 0) 1298 break; 1299 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1300 d.d_type = kt->kt_type; 1301 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1302 break; 1303 if (cookies) 1304 *cookies++ = i + 1; 1305 n++; 1306 } 1307 if (error) { 1308 ncookies = n; 1309 break; 1310 } 1311 1312 TAILQ_FOREACH(sav, &satailq, tailq) { 1313 for (sav2 = TAILQ_FIRST(&satailq); 1314 sav2 != sav; 1315 sav2 = TAILQ_NEXT(sav2, tailq)) { 1316 if (sav->spi == sav2->spi) { 1317 /* multiple SA with same SPI */ 1318 break; 1319 } 1320 } 1321 if (sav != sav2 && sav->spi == sav2->spi) 1322 continue; 1323 if (uio->uio_resid < UIO_MX) 1324 break; 1325 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt, 1326 sav->spi, ap)) != 0) 1327 break; 1328 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), 1329 "%u", ntohl(sav->spi)); 1330 d.d_type = DT_REG; 1331 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1332 break; 1333 if (cookies) 1334 *cookies++ = i + 1; 1335 n++; 1336 i++; 1337 } 1338 ncookies = n; 1339 break; 1340 1341 case KFSipsecspdir: 1342 /* count SP in the system */ 1343 if (&sptailq == NULL) 1344 return 0; 1345 1346 n = 0; 1347 TAILQ_FOREACH(sp, &sptailq, tailq) 1348 n++; 1349 1350 if (i >= nipsecsp_targets + n) 1351 return (0); 1352 1353 if (ap->a_ncookies) { 1354 ncookies = min(ncookies, (n - i)); 1355 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1356 M_WAITOK); 1357 *ap->a_cookies = cookies; 1358 } 1359 1360 n = 0; 1361 for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) { 1362 kt = &ipsecsp_targets[i]; 1363 d.d_namlen = kt->kt_namlen; 1364 if ((error = kernfs_setdirentfileno(&d, i, kfs, 1365 &kern_targets[0], kt, ap)) != 0) 1366 break; 1367 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1368 d.d_type = kt->kt_type; 1369 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1370 break; 1371 if (cookies) 1372 *cookies++ = i + 1; 1373 n++; 1374 } 1375 if (error) { 1376 ncookies = n; 1377 break; 1378 } 1379 1380 TAILQ_FOREACH(sp, &sptailq, tailq) { 1381 if (uio->uio_resid < UIO_MX) 1382 break; 1383 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt, 1384 sp->id, ap)) != 0) 1385 break; 1386 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), 1387 "%u", sp->id); 1388 d.d_type = DT_REG; 1389 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1390 break; 1391 if (cookies) 1392 *cookies++ = i + 1; 1393 n++; 1394 i++; 1395 } 1396 ncookies = n; 1397 break; 1398 #endif 1399 1400 default: 1401 error = ENOTDIR; 1402 break; 1403 } 1404 1405 if (ap->a_ncookies) { 1406 if (error) { 1407 if (cookies) 1408 free(*ap->a_cookies, M_TEMP); 1409 *ap->a_ncookies = 0; 1410 *ap->a_cookies = NULL; 1411 } else 1412 *ap->a_ncookies = ncookies; 1413 } 1414 1415 uio->uio_offset = i; 1416 return (error); 1417 } 1418 1419 int 1420 kernfs_inactive(void *v) 1421 { 1422 struct vop_inactive_args /* { 1423 struct vnode *a_vp; 1424 bool *a_recycle; 1425 } */ *ap = v; 1426 struct vnode *vp = ap->a_vp; 1427 const struct kernfs_node *kfs = VTOKERN(ap->a_vp); 1428 #ifdef IPSEC 1429 struct mbuf *m; 1430 struct secpolicy *sp; 1431 #endif 1432 1433 *ap->a_recycle = false; 1434 switch (kfs->kfs_type) { 1435 #ifdef IPSEC 1436 case KFSipsecsa: 1437 if (key_setdumpsa_spi == NULL) 1438 return 0; 1439 m = key_setdumpsa_spi(htonl(kfs->kfs_value)); 1440 if (m) 1441 m_freem(m); 1442 else 1443 *ap->a_recycle = true; 1444 break; 1445 case KFSipsecsp: 1446 if (key_getspbyid == NULL) 1447 return 0; 1448 sp = key_getspbyid(kfs->kfs_value); 1449 if (sp) 1450 key_freesp(sp); 1451 else { 1452 *ap->a_recycle = true; 1453 } 1454 break; 1455 #endif 1456 default: 1457 break; 1458 } 1459 VOP_UNLOCK(vp, 0); 1460 return (0); 1461 } 1462 1463 int 1464 kernfs_reclaim(void *v) 1465 { 1466 struct vop_reclaim_args /* { 1467 struct vnode *a_vp; 1468 } */ *ap = v; 1469 1470 return (kernfs_freevp(ap->a_vp)); 1471 } 1472 1473 /* 1474 * Return POSIX pathconf information applicable to special devices. 1475 */ 1476 int 1477 kernfs_pathconf(void *v) 1478 { 1479 struct vop_pathconf_args /* { 1480 struct vnode *a_vp; 1481 int a_name; 1482 register_t *a_retval; 1483 } */ *ap = v; 1484 1485 switch (ap->a_name) { 1486 case _PC_LINK_MAX: 1487 *ap->a_retval = LINK_MAX; 1488 return (0); 1489 case _PC_MAX_CANON: 1490 *ap->a_retval = MAX_CANON; 1491 return (0); 1492 case _PC_MAX_INPUT: 1493 *ap->a_retval = MAX_INPUT; 1494 return (0); 1495 case _PC_PIPE_BUF: 1496 *ap->a_retval = PIPE_BUF; 1497 return (0); 1498 case _PC_CHOWN_RESTRICTED: 1499 *ap->a_retval = 1; 1500 return (0); 1501 case _PC_VDISABLE: 1502 *ap->a_retval = _POSIX_VDISABLE; 1503 return (0); 1504 case _PC_SYNC_IO: 1505 *ap->a_retval = 1; 1506 return (0); 1507 default: 1508 return (EINVAL); 1509 } 1510 /* NOTREACHED */ 1511 } 1512 1513 /* 1514 * Print out the contents of a /dev/fd vnode. 1515 */ 1516 /* ARGSUSED */ 1517 int 1518 kernfs_print(void *v) 1519 { 1520 1521 printf("tag VT_KERNFS, kernfs vnode\n"); 1522 return (0); 1523 } 1524 1525 int 1526 kernfs_link(void *v) 1527 { 1528 struct vop_link_args /* { 1529 struct vnode *a_dvp; 1530 struct vnode *a_vp; 1531 struct componentname *a_cnp; 1532 } */ *ap = v; 1533 1534 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1535 vput(ap->a_dvp); 1536 return (EROFS); 1537 } 1538 1539 int 1540 kernfs_symlink(void *v) 1541 { 1542 struct vop_symlink_args /* { 1543 struct vnode *a_dvp; 1544 struct vnode **a_vpp; 1545 struct componentname *a_cnp; 1546 struct vattr *a_vap; 1547 char *a_target; 1548 } */ *ap = v; 1549 1550 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1551 vput(ap->a_dvp); 1552 return (EROFS); 1553 } 1554