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