int netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, register_t *retval) { /* { syscallarg(int) op; syscallarg(netbsd32_voidp) parms; } */ int error; switch (SCARG(uap, op)) { case X86_IOPL: error = x86_iopl(l, NETBSD32PTR64(SCARG(uap, parms)), retval); break; case X86_GET_MTRR: error = x86_64_get_mtrr32(l, NETBSD32PTR64(SCARG(uap, parms)), retval); break; case X86_SET_MTRR: error = x86_64_set_mtrr32(l, NETBSD32PTR64(SCARG(uap, parms)), retval); break; default: error = EINVAL; break; } return error; }
static inline void netbsd32_to_partinfo(struct netbsd32_partinfo *s32p, struct partinfo *p, u_long cmd) { p->disklab = (struct disklabel *)NETBSD32PTR64(s32p->disklab); p->part = (struct partition *)NETBSD32PTR64(s32p->part); }
/* convert to/from different structures */ static inline void netbsd32_to_fbcmap(struct netbsd32_fbcmap *s32p, struct fbcmap *p, u_long cmd) { p->index = s32p->index; p->count = s32p->count; p->red = NETBSD32PTR64(s32p->red); p->green = NETBSD32PTR64(s32p->green); p->blue = NETBSD32PTR64(s32p->blue); }
static inline void netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *s32p, struct opiocdesc *p, u_long cmd) { p->op_nodeid = s32p->op_nodeid; p->op_namelen = s32p->op_namelen; p->op_name = NETBSD32PTR64(s32p->op_name); p->op_buflen = s32p->op_buflen; p->op_buf = NETBSD32PTR64(s32p->op_buf); }
static inline void netbsd32_to_fbcursor(struct netbsd32_fbcursor *s32p, struct fbcursor *p, u_long cmd) { p->set = s32p->set; p->enable = s32p->enable; p->pos = s32p->pos; p->hot = s32p->hot; netbsd32_to_fbcmap(&s32p->cmap, &p->cmap, cmd); p->size = s32p->size; p->image = NETBSD32PTR64(s32p->image); p->mask = NETBSD32PTR64(s32p->mask); }
static int netbsd32_copyinpiod(struct ptrace_io_desc *piod, const void *addr) { struct netbsd32_ptrace_io_desc piod32; int error = copyin(addr, &piod32, sizeof(piod32)); if (error) return error; piod->piod_op = piod32.piod_op; piod->piod_offs = NETBSD32PTR64(piod32.piod_offs); piod->piod_addr = NETBSD32PTR64(piod32.piod_addr); piod->piod_len = (size_t)piod32.piod_len; return 0; }
static inline void netbsd32_to_ifdrv(struct netbsd32_ifdrv *s32p, struct ifdrv *p, u_long cmd) { memcpy(p, s32p, sizeof *s32p); p->ifd_data = (void *)NETBSD32PTR64(s32p->ifd_data); }
int linux32_sys_oldselect(struct lwp *l, const struct linux32_sys_oldselect_args *uap, register_t *retval) { /* { syscallarg(linux32_oldselectp_t) lsp; } */ struct linux32_oldselect lsp32; int error; if ((error = copyin(SCARG_P32(uap, lsp), &lsp32, sizeof(lsp32))) != 0) return error; return linux32_select1(l, retval, lsp32.nfds, NETBSD32PTR64(lsp32.readfds), NETBSD32PTR64(lsp32.writefds), NETBSD32PTR64(lsp32.exceptfds), NETBSD32PTR64(lsp32.timeout)); }
void linux32_to_native_sigaction(struct sigaction *bsa, const struct linux32_sigaction *lsa) { bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler); linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags); }
static inline void netbsd32_to_ifmediareq(struct netbsd32_ifmediareq *s32p, struct ifmediareq *p, u_long cmd) { memcpy(p, s32p, sizeof *s32p); p->ifm_ulist = (int *)NETBSD32PTR64(s32p->ifm_ulist); }
static inline void netbsd32_to_ifconf(struct netbsd32_ifconf *s32p, struct ifconf *p, u_long cmd) { p->ifc_len = s32p->ifc_len; /* ifc_buf & ifc_req are the same size so this works */ p->ifc_buf = (void *)NETBSD32PTR64(s32p->ifc_buf); }
static void linux32_to_bsd_msqid_ds(struct linux32_msqid_ds *lmp, struct msqid_ds *bmp) { memset(bmp, 0, sizeof(*bmp)); linux32_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm); bmp->_msg_first = NETBSD32PTR64(lmp->l_msg_first); bmp->_msg_last = NETBSD32PTR64(lmp->l_msg_last); bmp->_msg_cbytes = lmp->l_msg_cbytes; bmp->msg_qnum = lmp->l_msg_qnum; bmp->msg_qbytes = lmp->l_msg_qbytes; bmp->msg_lspid = lmp->l_msg_lspid; bmp->msg_lrpid = lmp->l_msg_lrpid; bmp->msg_stime = lmp->l_msg_stime; bmp->msg_rtime = lmp->l_msg_rtime; bmp->msg_ctime = lmp->l_msg_ctime; }
int compat_16_netbsd32___sigreturn14(struct lwp *l, const struct compat_16_netbsd32___sigreturn14_args *uap, register_t *retval) { /* { syscallarg(netbsd32_sigcontextp_t) sigcntxp; } */ struct netbsd32_sigcontext *scp, context; struct proc *p = l->l_proc; struct trapframe *tf; int error; /* * The trampoline code hands us the context. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ scp = NETBSD32PTR64(SCARG(uap, sigcntxp)); if (copyin(scp, &context, sizeof(*scp)) != 0) return (EFAULT); /* * Check for security violations. */ error = check_sigcontext32(l, &context); if (error != 0) return error; /* Restore register context. */ tf = l->l_md.md_regs; tf->tf_ds = context.sc_ds; tf->tf_es = context.sc_es; cpu_fsgs_reload(l, context.sc_fs, context.sc_gs); tf->tf_rflags = context.sc_eflags; tf->tf_rdi = context.sc_edi; tf->tf_rsi = context.sc_esi; tf->tf_rbp = context.sc_ebp; tf->tf_rbx = context.sc_ebx; tf->tf_rdx = context.sc_edx; tf->tf_rcx = context.sc_ecx; tf->tf_rax = context.sc_eax; tf->tf_rip = context.sc_eip; tf->tf_cs = context.sc_cs; tf->tf_rsp = context.sc_esp; tf->tf_ss = context.sc_ss; mutex_enter(p->p_lock); /* Restore signal stack. */ if (context.sc_onstack & SS_ONSTACK) l->l_sigstk.ss_flags |= SS_ONSTACK; else l->l_sigstk.ss_flags &= ~SS_ONSTACK; /* Restore signal mask. */ (void) sigprocmask1(l, SIG_SETMASK, &context.sc_mask, 0); mutex_exit(p->p_lock); return (EJUSTRETURN); }
static void linux32_to_bsd_semid_ds(struct linux32_semid_ds *lsp, struct semid_ds *bsp) { linux32_to_bsd_ipc_perm(&lsp->l_sem_perm, &bsp->sem_perm); bsp->sem_otime = lsp->l_sem_otime; bsp->sem_ctime = lsp->l_sem_ctime; bsp->sem_nsems = lsp->l_sem_nsems; bsp->_sem_base = NETBSD32PTR64(lsp->l_sem_base); }
static inline void netbsd32_to_format_op(struct netbsd32_format_op *s32p, struct format_op *p, u_long cmd) { p->df_buf = (char *)NETBSD32PTR64(s32p->df_buf); p->df_count = s32p->df_count; p->df_startblk = s32p->df_startblk; memcpy(p->df_reg, s32p->df_reg, sizeof(s32p->df_reg)); }
static void linux32_to_bsd_shmid_ds(struct linux32_shmid_ds *lsp, struct shmid_ds *bsp) { linux32_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm); bsp->shm_segsz = lsp->l_shm_segsz; bsp->shm_atime = lsp->l_shm_atime; bsp->shm_dtime = lsp->l_shm_dtime; bsp->shm_ctime = lsp->l_shm_ctime; bsp->shm_cpid = lsp->l_shm_cpid; bsp->shm_lpid = lsp->l_shm_lpid; bsp->shm_nattch = lsp->l_shm_nattch; bsp->_shm_internal = NETBSD32PTR64(lsp->l_private2); }
static int netbsd32_execve_fetch_element(char * const *array, size_t index, char **value) { int error; netbsd32_charp const *a32 = (void const *)array; netbsd32_charp e; error = copyin(a32 + index, &e, sizeof(e)); if (error) return error; *value = (char *)NETBSD32PTR64(e); return 0; }
static inline void netbsd32_to_ifreq(struct netbsd32_ifreq *s32p, struct ifreq *p, u_long cmd) { memcpy(p, s32p, sizeof *s32p); /* * XXX * struct ifreq says the same, but sometimes the ifr_data * union member needs to be converted to 64 bits... this * is very driver specific and so we ignore it for now.. */ if (cmd == SIOCGIFDATA || cmd == SIOCZIFDATA) p->ifr_data = (void *)NETBSD32PTR64(s32p->ifr_data); }
int linux32_getifconf(struct lwp *l, register_t *retval, void *data) { struct linux32_ifreq ifr, *ifrp; struct netbsd32_ifconf *ifc = data; struct ifnet *ifp; struct ifaddr *ifa; struct sockaddr *sa; struct osockaddr *osa; int space, error = 0; const int sz = (int)sizeof(ifr); ifrp = (struct linux32_ifreq *)NETBSD32PTR64(ifc->ifc_req); if (ifrp == NULL) space = 0; else space = ifc->ifc_len; IFNET_FOREACH(ifp) { (void)strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') return ENAMETOOLONG; if (IFADDR_EMPTY(ifp)) continue; IFADDR_FOREACH(ifa, ifp) { sa = ifa->ifa_addr; if (sa->sa_family != AF_INET || sa->sa_len > sizeof(*osa)) continue; memcpy(&ifr.ifr_addr, sa, sa->sa_len); osa = (struct osockaddr *)&ifr.ifr_addr; osa->sa_family = sa->sa_family; if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) return error; ifrp++; } space -= sz; } }
int netbsd32_sigaction(struct lwp *l, const struct netbsd32_sigaction_args *uap, register_t *retval) { /* { syscallarg(int) signum; syscallarg(const netbsd32_sigactionp_t) nsa; syscallarg(netbsd32_sigactionp_t) osa; } */ struct sigaction nsa, osa; struct netbsd32_sigaction13 *sa32p, sa32; int error; if (SCARG_P32(uap, nsa)) { sa32p = SCARG_P32(uap, nsa); if (copyin(sa32p, &sa32, sizeof(sa32))) return EFAULT; nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler); memset(&nsa.sa_mask, 0, sizeof(nsa.sa_mask)); nsa.sa_mask.__bits[0] = sa32.netbsd32_sa_mask; nsa.sa_flags = sa32.netbsd32_sa_flags; } error = sigaction1(l, SCARG(uap, signum), SCARG_P32(uap, nsa) ? &nsa : 0, SCARG_P32(uap, osa) ? &osa : 0, NULL, 0); if (error) return (error); if (SCARG_P32(uap, osa)) { NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); sa32.netbsd32_sa_mask = osa.sa_mask.__bits[0]; sa32.netbsd32_sa_flags = osa.sa_flags; sa32p = SCARG_P32(uap, osa); if (copyout(&sa32, sa32p, sizeof(sa32))) return EFAULT; } return (0); }
int netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(netbsd32_msghdrp_t) msg; syscallarg(int) flags; } */ struct netbsd32_msghdr msg; struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; int error; error = copyin(SCARG_P32(uap, msg), &msg, sizeof(msg)); /* netbsd32_msghdr needs the iov pre-allocated */ if (error) return (error); if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) { if ((u_int)msg.msg_iovlen > IOV_MAX) return (EMSGSIZE); iov = (struct iovec *)malloc( sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, M_WAITOK); } else iov = aiov; msg.msg_flags = SCARG(uap, flags); uiov = (struct iovec *)NETBSD32PTR64(msg.msg_iov); error = netbsd32_to_iovecin((struct netbsd32_iovec *)uiov, iov, msg.msg_iovlen); if (error) goto done; if ((error = recvit32(l, SCARG(uap, s), &msg, iov, (void *)0, retval)) == 0) { error = copyout(&msg, SCARG_P32(uap, msg), sizeof(msg)); } done: if (iov != aiov) FREE(iov, M_IOV); return (error); }
/* ARGSUSED */ int netbsd32___sigaction_sigtramp(struct lwp *l, const struct netbsd32___sigaction_sigtramp_args *uap, register_t *retval) { /* { syscallarg(int) signum; syscallarg(const netbsd32_sigactionp_t) nsa; syscallarg(netbsd32_sigactionp_t) osa; syscallarg(netbsd32_voidp) tramp; syscallarg(int) vers; } */ struct netbsd32_sigaction sa32; struct sigaction nsa, osa; int error; if (SCARG_P32(uap, nsa)) { error = copyin(SCARG_P32(uap, nsa), &sa32, sizeof(sa32)); if (error) return (error); nsa.sa_handler = NETBSD32PTR64(sa32.netbsd32_sa_handler); nsa.sa_mask = sa32.netbsd32_sa_mask; nsa.sa_flags = sa32.netbsd32_sa_flags; } error = sigaction1(l, SCARG(uap, signum), SCARG_P32(uap, nsa) ? &nsa : 0, SCARG_P32(uap, osa) ? &osa : 0, SCARG_P32(uap, tramp), SCARG(uap, vers)); if (error) return (error); if (SCARG_P32(uap, osa)) { NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler); sa32.netbsd32_sa_mask = osa.sa_mask; sa32.netbsd32_sa_flags = osa.sa_flags; error = copyout(&sa32, SCARG_P32(uap, osa), sizeof(sa32)); if (error) return (error); } return (0); }
int linux32_sys___sysctl(struct lwp *l, const struct linux32_sys___sysctl_args *uap, register_t *retval) { /* { syscallarg(linux32___sysctlp_t) lsp; } */ struct linux32_sysctl ls32; int name[CTL_MAXNAME]; size_t savelen; netbsd32_size_t oldlen32; size_t oldlen; int error; /* * Read sysctl arguments */ if ((error = copyin(SCARG_P32(uap, lsp), &ls32, sizeof(ls32))) != 0) return error; /* * Read oldlen */ if (NETBSD32PTR64(ls32.oldlenp) != NULL) { if ((error = copyin(NETBSD32PTR64(ls32.oldlenp), &oldlen32, sizeof(oldlen32))) != 0) return error; } else { oldlen32 = 0; } savelen = (size_t)oldlen32; /* * Sanity check nlen */ if ((ls32.nlen > CTL_MAXNAME) || (ls32.nlen < 1)) return ENOTDIR; /* * Read the sysctl name */ if ((error = copyin(NETBSD32PTR64(ls32.name), &name, ls32.nlen * sizeof(int))) != 0) return error; ktrmib(name, ls32.nlen); /* * First try linux32 tree, then linux tree */ oldlen = (size_t)oldlen32; sysctl_lock(NETBSD32PTR64(ls32.newval) != NULL); error = sysctl_dispatch(name, ls32.nlen, NETBSD32PTR64(ls32.oldval), &oldlen, NETBSD32PTR64(ls32.newval), ls32.newlen, name, l, &linux32_sysctl_root); oldlen32 = (netbsd32_size_t)oldlen; sysctl_unlock(); /* * Check for oldlen overflow (not likely, but who knows...) */ if (oldlen != oldlen32) { #ifdef DEBUG_LINUX printf("%s: oldlen32 = %d, oldlen = %ld\n", __func__, oldlen32, oldlen); #endif return EINVAL; } /* * set caller's oldlen, even if we got an error */ if (NETBSD32PTR64(ls32.oldlenp)) { int nerror; nerror = copyout(&oldlen32, NETBSD32PTR64(ls32.oldlenp), sizeof(oldlen32)); if (error == 0) error = nerror; } /* * oldlen was too short */ if ((error == 0) && (NETBSD32PTR64(ls32.oldval) != NULL) && (savelen < oldlen32)) error = ENOMEM; return error; }
int recvit32(struct lwp *l, int s, struct netbsd32_msghdr *mp, struct iovec *iov, void *namelenp, register_t *retsize) { struct uio auio; int i, len, error, iovlen; struct mbuf *from = 0, *control = 0; struct socket *so; struct proc *p; struct iovec *ktriov = NULL; p = l->l_proc; /* fd_getsock() will use the descriptor for us */ if ((error = fd_getsock(s, &so)) != 0) return (error); auio.uio_iov = iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_rw = UIO_READ; auio.uio_vmspace = l->l_proc->p_vmspace; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; for (i = 0; i < mp->msg_iovlen; i++, iov++) { #if 0 /* cannot happen iov_len is unsigned */ if (iov->iov_len < 0) { error = EINVAL; goto out1; } #endif /* * Reads return ssize_t because -1 is returned on error. * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ auio.uio_resid += iov->iov_len; if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { error = EINVAL; goto out1; } } if (ktrpoint(KTR_GENIO)) { iovlen = auio.uio_iovcnt * sizeof(struct iovec); ktriov = (struct iovec *)malloc(iovlen, M_TEMP, M_WAITOK); memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen); } len = auio.uio_resid; error = (*so->so_receive)(so, &from, &auio, NULL, NETBSD32PTR64(mp->msg_control) ? &control : NULL, &mp->msg_flags); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } if (ktriov != NULL) { ktrgeniov(s, UIO_READ, ktriov, len - auio.uio_resid, error); FREE(ktriov, M_TEMP); } if (error) goto out; *retsize = len - auio.uio_resid; if (NETBSD32PTR64(mp->msg_name)) { len = mp->msg_namelen; if (len <= 0 || from == 0) len = 0; else { if (len > from->m_len) len = from->m_len; /* else if len < from->m_len ??? */ error = copyout(mtod(from, void *), (void *)NETBSD32PTR64(mp->msg_name), (unsigned)len); if (error) goto out; } mp->msg_namelen = len; if (namelenp && (error = copyout((void *)&len, namelenp, sizeof(int)))) goto out; }
int do_netbsd32___semctl14(struct lwp *l, const struct netbsd32___semctl14_args *uap, register_t *retval, void *vkarg) { /* { syscallarg(int) semid; syscallarg(int) semnum; syscallarg(int) cmd; syscallarg(netbsd32_semunp_t) arg; } */ struct semid_ds sembuf; struct netbsd32_semid_ds sembuf32; int cmd, error; void *pass_arg; union __semun karg; union netbsd32_semun karg32; cmd = SCARG(uap, cmd); switch (cmd) { case IPC_SET: case IPC_STAT: pass_arg = &sembuf; break; case GETALL: case SETVAL: case SETALL: pass_arg = &karg; break; default: pass_arg = NULL; break; } if (pass_arg) { if (vkarg != NULL) karg32 = *(union netbsd32_semun *)vkarg; else { error = copyin(SCARG_P32(uap, arg), &karg32, sizeof(karg32)); if (error) return error; } if (pass_arg == &karg) { switch (cmd) { case GETALL: case SETALL: karg.array = NETBSD32PTR64(karg32.array); break; case SETVAL: karg.val = karg32.val; break; } } if (cmd == IPC_SET) { error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32, sizeof(sembuf32)); if (error) return (error); netbsd32_to_semid_ds(&sembuf32, &sembuf); } } error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd, pass_arg, retval); if (error == 0 && cmd == IPC_STAT) { netbsd32_from_semid_ds(&sembuf, &sembuf32); error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf), sizeof(sembuf32)); } return (error); }
static int linux32_semctl(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) { int lcmd, cmd, error; struct semid_ds bs; struct linux32_semid_ds ls; struct linux32_semid64_ds ls64; union linux32_semun lsem; union __semun bsem; void *buf = NULL; if ((error = copyin(SCARG_P32(uap, ptr), &lsem, sizeof lsem))) return error; lcmd = SCARG(uap, a3); switch (lcmd & ~LINUX32_IPC_64) { case LINUX32_IPC_RMID: cmd = IPC_RMID; break; case LINUX32_IPC_STAT: cmd = IPC_STAT; buf = &bs; break; case LINUX32_IPC_SET: if (lcmd & LINUX32_IPC_64) { error = copyin(NETBSD32PTR64(lsem.l_buf), &ls64, sizeof ls64); linux32_to_bsd_semid64_ds(&ls64, &bs); } else { error = copyin(NETBSD32PTR64(lsem.l_buf), &ls, sizeof ls); linux32_to_bsd_semid_ds(&ls, &bs); } if (error) return error; cmd = IPC_SET; buf = &bs; break; case LINUX32_GETVAL: cmd = GETVAL; break; case LINUX32_SETVAL: cmd = SETVAL; bsem.val = lsem.l_val; buf = &bsem; break; case LINUX32_GETPID: cmd = GETPID; break; case LINUX32_GETNCNT: cmd = GETNCNT; break; case LINUX32_GETZCNT: cmd = GETZCNT; break; case LINUX32_GETALL: cmd = GETALL; bsem.array = NETBSD32PTR64(lsem.l_array); buf = &bsem; break; case LINUX32_SETALL: cmd = SETALL; bsem.array = NETBSD32PTR64(lsem.l_array); buf = &bsem; break; default: return EINVAL; } error = semctl1(l, SCARG(uap, a1), SCARG(uap, a2), cmd, buf, retval); if (error) return error; switch (lcmd) { case LINUX32_IPC_STAT: bsd_to_linux32_semid_ds(&bs, &ls); error = copyout(&ls, NETBSD32PTR64(lsem.l_buf), sizeof ls); break; case LINUX32_IPC_STAT|LINUX32_IPC_64: bsd_to_linux32_semid64_ds(&bs, &ls64); error = copyout(&ls64, NETBSD32PTR64(lsem.l_buf), sizeof ls64); break; default: break; } return error; }
int svr4_32_sock_ioctl(file_t *fp, struct lwp *l, register_t *retval, int fd, u_long cmd, void *data) { int error; int (*ctl)(file_t *, u_long, void *) = fp->f_ops->fo_ioctl; *retval = 0; switch (cmd) { case SVR4_SIOCGIFNUM: { struct ifnet *ifp; int ifnum = 0; int s; /* * This does not return the number of physical * interfaces (if_index), but the number of interfaces * + addresses like ifconf() does, because this number * is used by code that will call SVR4_SIOCGIFCONF to * find the space needed for SVR4_SIOCGIFCONF. So we * count the number of ifreq entries that the next * SVR4_SIOCGIFCONF will return. Maybe a more correct * fix is to make SVR4_SIOCGIFCONF return only one * entry per physical interface? */ s = pserialize_read_enter(); IFNET_READER_FOREACH(ifp) ifnum += svr4_count_ifnum(ifp); pserialize_read_exit(s); DPRINTF(("SIOCGIFNUM %d\n", ifnum)); return copyout(&ifnum, data, sizeof(ifnum)); } case SVR4_32_SIOCGIFFLAGS: { struct oifreq br; struct svr4_32_ifreq sr; if ((error = copyin(data, &sr, sizeof(sr))) != 0) return error; (void) strncpy(br.ifr_name, sr.svr4_ifr_name, sizeof(br.ifr_name)); if ((error = (*ctl)(fp, SIOCGIFFLAGS, &br)) != 0) { DPRINTF(("SIOCGIFFLAGS %s: error %d\n", sr.svr4_ifr_name, error)); return error; } sr.svr4_ifr_flags = bsd_to_svr4_flags(br.ifr_flags); DPRINTF(("SIOCGIFFLAGS %s = %x\n", sr.svr4_ifr_name, sr.svr4_ifr_flags)); return copyout(&sr, data, sizeof(sr)); } case SVR4_32_SIOCGIFCONF: { struct svr4_32_ifconf sc; struct oifconf ifc; if ((error = copyin(data, &sc, sizeof(sc))) != 0) return error; DPRINTF(("ifreq %ld svr4_32_ifreq %ld ifc_len %d\n", (unsigned long)sizeof(struct oifreq), (unsigned long)sizeof(struct svr4_32_ifreq), sc.svr4_32_ifc_len)); ifc.ifc_len = sc.svr4_32_ifc_len; ifc.ifc_buf = NETBSD32PTR64(sc.ifc_ifcu.ifcu_buf); if ((error = (*ctl)(fp, OOSIOCGIFCONF, &ifc)) != 0) return error; DPRINTF(("SIOCGIFCONF\n")); return 0; } default: DPRINTF(("Unknown svr4_32 sockio %lx\n", cmd)); return 0; /* ENOSYS really */ } }
/* * This is a brutal clone of compat_43_sys_recvmsg(). */ int compat_43_netbsd32_orecvmsg(struct lwp *l, const struct compat_43_netbsd32_orecvmsg_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(netbsd32_omsghdrp_t) msg; syscallarg(int) flags; } */ struct netbsd32_omsghdr omsg; struct msghdr msg; struct mbuf *from, *control; struct iovec *iov, aiov[UIO_SMALLIOV]; int error; error = copyin(SCARG_P32(uap, msg), &omsg, sizeof (struct omsghdr)); if (error) return (error); if (NETBSD32PTR64(omsg.msg_accrights) == NULL) omsg.msg_accrightslen = 0; /* it was this way in 4.4BSD */ if (omsg.msg_accrightslen > MLEN) return EINVAL; iov = netbsd32_get_iov(NETBSD32PTR64(omsg.msg_iov), omsg.msg_iovlen, aiov, __arraycount(aiov)); if (iov == NULL) return EFAULT; msg.msg_name = NETBSD32PTR64(omsg.msg_name); msg.msg_namelen = omsg.msg_namelen; msg.msg_iovlen = omsg.msg_iovlen; msg.msg_iov = iov; msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NETBSD32PTR64(omsg.msg_accrights) != NULL ? &control : NULL, retval); if (error != 0) return error; /* * If there is any control information and it's SCM_RIGHTS, * pass it back to the program. * XXX: maybe there can be more than one chunk of control data? */ if (NETBSD32PTR64(omsg.msg_accrights) != NULL && control != NULL) { struct cmsghdr *cmsg = mtod(control, void *); if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS && cmsg->cmsg_len < omsg.msg_accrightslen && copyout(CMSG_DATA(cmsg), NETBSD32PTR64(omsg.msg_accrights), cmsg->cmsg_len) == 0) { omsg.msg_accrightslen = cmsg->cmsg_len; free_control_mbuf(l, control, control->m_next); } else { omsg.msg_accrightslen = 0; free_control_mbuf(l, control, control); } } else