/* * sys_lfs_segwait: * * System call wrapper around lfs_segwait(). * * 0 on success * 1 on timeout * -1/errno is return on error. */ int sys___lfs_segwait50(struct lwp *l, const struct sys___lfs_segwait50_args *uap, register_t *retval) { /* { syscallarg(fsid_t *) fsidp; syscallarg(struct timeval *) tv; } */ struct timeval atv; fsid_t fsid; int error; /* XXX need we be su to segwait? */ error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS, KAUTH_REQ_SYSTEM_LFS_SEGWAIT, NULL, NULL, NULL); if (error) return (error); if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) return (error); if (SCARG(uap, tv)) { error = copyin(SCARG(uap, tv), &atv, sizeof(struct timeval)); if (error) return (error); if (itimerfix(&atv)) return (EINVAL); } else /* NULL or invalid */ atv.tv_sec = atv.tv_usec = 0; return lfs_segwait(&fsid, &atv); }
/* * Low level support for sleep/wakeup paradigm * If a timeout is specified: * returns 0 if wakeup * returns EAGAIN if timed out * returns EINVAL if error * * If a timeout is not specified: * * returns time waiting in ticks. */ int sys_thr_sleep(struct thr_sleep_args *uap) { struct proc *p = curproc; struct lwp *lp = curthread->td_lwp; int sleepstart; struct timespec ts; struct timeval atv; int error, timo; timo = 0; if (uap->timeout != 0) { /* * Get timespec struct */ if ((error = copyin(uap->timeout, &ts, sizeof(ts))) != 0) { p->p_wakeup = 0; return error; } if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) { p->p_wakeup = 0; return (EINVAL); } TIMESPEC_TO_TIMEVAL(&atv, &ts); if (itimerfix(&atv)) { p->p_wakeup = 0; return (EINVAL); } timo = tvtohz_high(&atv); } uap->sysmsg_result = 0; if (p->p_wakeup == 0) { sleepstart = ticks; lp->lwp_flag |= LWP_SINTR; error = tsleep(p, 0, "thrslp", timo); lp->lwp_flag &= ~LWP_SINTR; if (error == EWOULDBLOCK) { p->p_wakeup = 0; uap->sysmsg_result = EAGAIN; return 0; } if (uap->timeout == 0) uap->sysmsg_result = ticks - sleepstart; } p->p_wakeup = 0; return (0); }
/* ARGSUSED */ int bpfioctl(dev_t dev, u_long cmd, caddr_t addr, __unused int flags, struct proc *p) { struct bpf_d *d; int error = 0; lck_mtx_lock(bpf_mlock); d = bpf_dtab[minor(dev)]; if (d == 0 || d == (void *)1) { lck_mtx_unlock(bpf_mlock); return (ENXIO); } switch (cmd) { default: error = EINVAL; break; /* * Check for read packet available. */ case FIONREAD: { int n; n = d->bd_slen; if (d->bd_hbuf) n += d->bd_hlen; *(int *)addr = n; break; } case SIOCGIFADDR: { struct ifnet *ifp; if (d->bd_bif == 0) error = EINVAL; else { ifp = d->bd_bif->bif_ifp; error = ifnet_ioctl(ifp, 0, cmd, addr); } break; } /* * Get buffer len [for read()]. */ case BIOCGBLEN: *(u_int *)addr = d->bd_bufsize; break; /* * Set buffer length. */ case BIOCSBLEN: #if BSD < 199103 error = EINVAL; #else if (d->bd_bif != 0) error = EINVAL; else { u_int size = *(u_int *)addr; if (size > bpf_maxbufsize) *(u_int *)addr = size = bpf_maxbufsize; else if (size < BPF_MINBUFSIZE) *(u_int *)addr = size = BPF_MINBUFSIZE; d->bd_bufsize = size; } #endif break; /* * Set link layer read filter. */ case BIOCSETF32: { struct bpf_program32 *prg32 = (struct bpf_program32 *)addr; error = bpf_setf(d, prg32->bf_len, CAST_USER_ADDR_T(prg32->bf_insns)); break; } case BIOCSETF64: { struct bpf_program64 *prg64 = (struct bpf_program64 *)addr; error = bpf_setf(d, prg64->bf_len, prg64->bf_insns); break; } /* * Flush read packet buffer. */ case BIOCFLUSH: reset_d(d); break; /* * Put interface into promiscuous mode. */ case BIOCPROMISC: if (d->bd_bif == 0) { /* * No interface attached yet. */ error = EINVAL; break; } if (d->bd_promisc == 0) { lck_mtx_unlock(bpf_mlock); error = ifnet_set_promiscuous(d->bd_bif->bif_ifp, 1); lck_mtx_lock(bpf_mlock); if (error == 0) d->bd_promisc = 1; } break; /* * Get device parameters. */ case BIOCGDLT: if (d->bd_bif == 0) error = EINVAL; else *(u_int *)addr = d->bd_bif->bif_dlt; break; /* * Get a list of supported data link types. */ case BIOCGDLTLIST: if (d->bd_bif == NULL) { error = EINVAL; } else { error = bpf_getdltlist(d, (struct bpf_dltlist *)addr, p); } break; /* * Set data link type. */ case BIOCSDLT: if (d->bd_bif == NULL) error = EINVAL; else error = bpf_setdlt(d, *(u_int *)addr); break; /* * Get interface name. */ case BIOCGETIF: if (d->bd_bif == 0) error = EINVAL; else { struct ifnet *const ifp = d->bd_bif->bif_ifp; struct ifreq *const ifr = (struct ifreq *)addr; snprintf(ifr->ifr_name, sizeof(ifr->ifr_name), "%s%d", ifp->if_name, ifp->if_unit); } break; /* * Set interface. */ case BIOCSETIF: { ifnet_t ifp; ifp = ifunit(((struct ifreq *)addr)->ifr_name); if (ifp == NULL) error = ENXIO; else error = bpf_setif(d, ifp, 0); break; } /* * Set read timeout. */ case BIOCSRTIMEOUT: { struct BPF_TIMEVAL *_tv = (struct BPF_TIMEVAL *)addr; struct timeval tv; tv.tv_sec = _tv->tv_sec; tv.tv_usec = _tv->tv_usec; /* * Subtract 1 tick from tvtohz() since this isn't * a one-shot timer. */ if ((error = itimerfix(&tv)) == 0) d->bd_rtout = tvtohz(&tv) - 1; break; } /* * Get read timeout. */ case BIOCGRTIMEOUT: { struct BPF_TIMEVAL *tv = (struct BPF_TIMEVAL *)addr; tv->tv_sec = d->bd_rtout / hz; tv->tv_usec = (d->bd_rtout % hz) * tick; break; } /* * Get packet stats. */ case BIOCGSTATS: { struct bpf_stat *bs = (struct bpf_stat *)addr; bs->bs_recv = d->bd_rcount; bs->bs_drop = d->bd_dcount; break; } /* * Set immediate mode. */ case BIOCIMMEDIATE: d->bd_immediate = *(u_int *)addr; break; case BIOCVERSION: { struct bpf_version *bv = (struct bpf_version *)addr; bv->bv_major = BPF_MAJOR_VERSION; bv->bv_minor = BPF_MINOR_VERSION; break; } /* * Get "header already complete" flag */ case BIOCGHDRCMPLT: *(u_int *)addr = d->bd_hdrcmplt; break; /* * Set "header already complete" flag */ case BIOCSHDRCMPLT: d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0; break; /* * Get "see sent packets" flag */ case BIOCGSEESENT: *(u_int *)addr = d->bd_seesent; break; /* * Set "see sent packets" flag */ case BIOCSSEESENT: d->bd_seesent = *(u_int *)addr; break; case FIONBIO: /* Non-blocking I/O */ break; case FIOASYNC: /* Send signal on receive packets */ d->bd_async = *(int *)addr; break; #ifndef __APPLE__ case FIOSETOWN: error = fsetown(*(int *)addr, &d->bd_sigio); break; case FIOGETOWN: *(int *)addr = fgetown(d->bd_sigio); break; /* This is deprecated, FIOSETOWN should be used instead. */ case TIOCSPGRP: error = fsetown(-(*(int *)addr), &d->bd_sigio); break; /* This is deprecated, FIOGETOWN should be used instead. */ case TIOCGPGRP: *(int *)addr = -fgetown(d->bd_sigio); break; #endif case BIOCSRSIG: /* Set receive signal */ { u_int sig; sig = *(u_int *)addr; if (sig >= NSIG) error = EINVAL; else d->bd_sig = sig; break; } case BIOCGRSIG: *(u_int *)addr = d->bd_sig; break; } lck_mtx_unlock(bpf_mlock); return (error); }