svr4_stream.c revision 92761
143412Snewton/* 243412Snewton * Copyright (c) 1998 Mark Newton. All rights reserved. 343412Snewton * Copyright (c) 1994, 1996 Christos Zoulas. All rights reserved. 443412Snewton * 543412Snewton * Redistribution and use in source and binary forms, with or without 643412Snewton * modification, are permitted provided that the following conditions 743412Snewton * are met: 843412Snewton * 1. Redistributions of source code must retain the above copyright 943412Snewton * notice, this list of conditions and the following disclaimer. 1043412Snewton * 2. Redistributions in binary form must reproduce the above copyright 1143412Snewton * notice, this list of conditions and the following disclaimer in the 1243412Snewton * documentation and/or other materials provided with the distribution. 1343412Snewton * 3. All advertising materials mentioning features or use of this software 1443412Snewton * must display the following acknowledgement: 1543412Snewton * This product includes software developed by Christos Zoulas. 1643412Snewton * 4. The name of the author may not be used to endorse or promote products 1743412Snewton * derived from this software without specific prior written permission. 1843412Snewton * 1943412Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2043412Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2143412Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2243412Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2343412Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2443412Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2543412Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2643412Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2743412Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2843412Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2949267Snewton * 3050477Speter * $FreeBSD: head/sys/compat/svr4/svr4_stream.c 92761 2002-03-20 05:48:58Z alfred $ 3143412Snewton */ 3243412Snewton 3343412Snewton/* 3443412Snewton * Pretend that we have streams... 3543412Snewton * Yes, this is gross. 3643412Snewton * 3743412Snewton * ToDo: The state machine for getmsg needs re-thinking 3843412Snewton */ 3943412Snewton 4043412Snewton#define COMPAT_43 1 4143412Snewton 4243412Snewton#include <sys/param.h> 4343412Snewton#include <sys/systm.h> 4476166Smarkm#include <sys/fcntl.h> 4543412Snewton#include <sys/filedesc.h> 4643412Snewton#include <sys/filio.h> 4776166Smarkm#include <sys/lock.h> 4876166Smarkm#include <sys/malloc.h> 4976166Smarkm#include <sys/file.h> /* Must come after sys/malloc.h */ 5043412Snewton#include <sys/mbuf.h> 5176166Smarkm#include <sys/mutex.h> 5276166Smarkm#include <sys/proc.h> 5343412Snewton#include <sys/protosw.h> 5443412Snewton#include <sys/signal.h> 5543412Snewton#include <sys/signalvar.h> 5676166Smarkm#include <sys/socket.h> 5776166Smarkm#include <sys/socketvar.h> 5843412Snewton#include <sys/stat.h> 5943412Snewton#include <sys/sysproto.h> 6076166Smarkm#include <sys/uio.h> 6176166Smarkm#include <sys/ktrace.h> /* Must come after sys/uio.h */ 6276166Smarkm#include <sys/un.h> 6343412Snewton 6476166Smarkm#include <netinet/in.h> 6576166Smarkm 6665302Sobrien#include <compat/svr4/svr4.h> 6765302Sobrien#include <compat/svr4/svr4_types.h> 6865302Sobrien#include <compat/svr4/svr4_util.h> 6965302Sobrien#include <compat/svr4/svr4_signal.h> 7065302Sobrien#include <compat/svr4/svr4_proto.h> 7165302Sobrien#include <compat/svr4/svr4_stropts.h> 7265302Sobrien#include <compat/svr4/svr4_timod.h> 7365302Sobrien#include <compat/svr4/svr4_sockmod.h> 7465302Sobrien#include <compat/svr4/svr4_ioctl.h> 7565302Sobrien#include <compat/svr4/svr4_socket.h> 7643412Snewton 7743412Snewton/* Utils */ 7892761Salfredstatic int clean_pipe(struct thread *, const char *); 7992761Salfredstatic void getparm(struct file *, struct svr4_si_sockparms *); 8092761Salfredstatic int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *, 8192761Salfred struct file *); 8292761Salfredstatic int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *, 8392761Salfred struct file *); 8443412Snewton 8543412Snewton/* Address Conversions */ 8692761Salfredstatic void sockaddr_to_netaddr_in(struct svr4_strmcmd *, 8792761Salfred const struct sockaddr_in *); 8892761Salfredstatic void sockaddr_to_netaddr_un(struct svr4_strmcmd *, 8992761Salfred const struct sockaddr_un *); 9092761Salfredstatic void netaddr_to_sockaddr_in(struct sockaddr_in *, 9192761Salfred const struct svr4_strmcmd *); 9292761Salfredstatic void netaddr_to_sockaddr_un(struct sockaddr_un *, 9392761Salfred const struct svr4_strmcmd *); 9443412Snewton 9543412Snewton/* stream ioctls */ 9692761Salfredstatic int i_nread(struct file *, struct thread *, register_t *, int, 9792761Salfred u_long, caddr_t); 9892761Salfredstatic int i_fdinsert(struct file *, struct thread *, register_t *, int, 9992761Salfred u_long, caddr_t); 10092761Salfredstatic int i_str(struct file *, struct thread *, register_t *, int, 10192761Salfred u_long, caddr_t); 10292761Salfredstatic int i_setsig(struct file *, struct thread *, register_t *, int, 10392761Salfred u_long, caddr_t); 10492761Salfredstatic int i_getsig(struct file *, struct thread *, register_t *, int, 10592761Salfred u_long, caddr_t); 10692761Salfredstatic int _i_bind_rsvd(struct file *, struct thread *, register_t *, int, 10792761Salfred u_long, caddr_t); 10892761Salfredstatic int _i_rele_rsvd(struct file *, struct thread *, register_t *, int, 10992761Salfred u_long, caddr_t); 11043412Snewton 11143412Snewton/* i_str sockmod calls */ 11292761Salfredstatic int sockmod(struct file *, int, struct svr4_strioctl *, 11392761Salfred struct thread *); 11492761Salfredstatic int si_listen(struct file *, int, struct svr4_strioctl *, 11592761Salfred struct thread *); 11692761Salfredstatic int si_ogetudata(struct file *, int, struct svr4_strioctl *, 11792761Salfred struct thread *); 11892761Salfredstatic int si_sockparams(struct file *, int, struct svr4_strioctl *, 11992761Salfred struct thread *); 12092761Salfredstatic int si_shutdown (struct file *, int, struct svr4_strioctl *, 12192761Salfred struct thread *); 12292761Salfredstatic int si_getudata(struct file *, int, struct svr4_strioctl *, 12392761Salfred struct thread *); 12443412Snewton 12543412Snewton/* i_str timod calls */ 12692761Salfredstatic int timod(struct file *, int, struct svr4_strioctl *, struct thread *); 12792761Salfredstatic int ti_getinfo(struct file *, int, struct svr4_strioctl *, 12892761Salfred struct thread *); 12992761Salfredstatic int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *); 13043412Snewton 13143412Snewton/* infrastructure */ 13292761Salfredstatic int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags); 13343412Snewton 13492761Salfredstatic int svr4_recvit(struct thread *td, int s, struct msghdr *mp, 13592761Salfred caddr_t namelenp); 13643412Snewton 13743412Snewton/* <sigh> Ok, so we shouldn't use sendit() in uipc_syscalls.c because 13843412Snewton * it isn't part of a "public" interface; We're supposed to use 13943412Snewton * pru_sosend instead. Same goes for recvit()/pru_soreceive() for 14043412Snewton * that matter. Solution: Suck sendit()/recvit() into here where we 14143412Snewton * can do what we like. 14243412Snewton * 14343412Snewton * I hate code duplication. 14443412Snewton * 14543412Snewton * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though. 14643412Snewton */ 14743412Snewtonstatic int 14883366Sjuliansvr4_sendit(td, s, mp, flags) 14983366Sjulian register struct thread *td; 15043412Snewton int s; 15143412Snewton register struct msghdr *mp; 15243412Snewton int flags; 15343412Snewton{ 15443412Snewton struct uio auio; 15543412Snewton register struct iovec *iov; 15643412Snewton register int i; 15743412Snewton struct mbuf *control; 15843412Snewton struct sockaddr *to; 15943412Snewton int len, error; 16043412Snewton struct socket *so; 16143412Snewton#ifdef KTRACE 16243412Snewton struct iovec *ktriov = NULL; 16362378Sgreen struct uio ktruio; 16443412Snewton#endif 16543412Snewton 16686487Sdillon if ((error = fgetsock(td, s, &so, NULL)) != 0) 16743412Snewton return (error); 16843412Snewton auio.uio_iov = mp->msg_iov; 16943412Snewton auio.uio_iovcnt = mp->msg_iovlen; 17043412Snewton auio.uio_segflg = UIO_USERSPACE; 17143412Snewton auio.uio_rw = UIO_WRITE; 17283366Sjulian auio.uio_td = td; 17343412Snewton auio.uio_offset = 0; /* XXX */ 17443412Snewton auio.uio_resid = 0; 17543412Snewton iov = mp->msg_iov; 17643412Snewton for (i = 0; i < mp->msg_iovlen; i++, iov++) { 17769084Sdillon if ((auio.uio_resid += iov->iov_len) < 0) { 17886487Sdillon error = EINVAL; 17986487Sdillon goto done1; 18069084Sdillon } 18143412Snewton } 18243412Snewton if (mp->msg_name) { 18343412Snewton error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); 18486487Sdillon if (error) 18586487Sdillon goto done1; 18669084Sdillon } else { 18743412Snewton to = 0; 18869084Sdillon } 18943412Snewton if (mp->msg_control) { 19043412Snewton if (mp->msg_controllen < sizeof(struct cmsghdr)) { 19143412Snewton error = EINVAL; 19243412Snewton goto bad; 19343412Snewton } 19443412Snewton error = sockargs(&control, mp->msg_control, 19543412Snewton mp->msg_controllen, MT_CONTROL); 19643412Snewton if (error) 19743412Snewton goto bad; 19869084Sdillon } else { 19943412Snewton control = 0; 20069084Sdillon } 20143412Snewton#ifdef KTRACE 20283366Sjulian if (KTRPOINT(td->td_proc, KTR_GENIO)) { 20343412Snewton int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 20443412Snewton 20543412Snewton MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 20643412Snewton bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 20762378Sgreen ktruio = auio; 20843412Snewton } 20943412Snewton#endif 21043412Snewton len = auio.uio_resid; 21143412Snewton error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control, 21283366Sjulian flags, td); 21343412Snewton if (error) { 21443412Snewton if (auio.uio_resid != len && (error == ERESTART || 21543412Snewton error == EINTR || error == EWOULDBLOCK)) 21643412Snewton error = 0; 21773929Sjhb if (error == EPIPE) { 21883366Sjulian PROC_LOCK(td->td_proc); 21983366Sjulian psignal(td->td_proc, SIGPIPE); 22083366Sjulian PROC_UNLOCK(td->td_proc); 22173929Sjhb } 22243412Snewton } 22343412Snewton if (error == 0) 22483366Sjulian td->td_retval[0] = len - auio.uio_resid; 22543412Snewton#ifdef KTRACE 22643412Snewton if (ktriov != NULL) { 22762378Sgreen if (error == 0) { 22862378Sgreen ktruio.uio_iov = ktriov; 22983366Sjulian ktruio.uio_resid = td->td_retval[0]; 23083366Sjulian ktrgenio(td->td_proc->p_tracep, s, UIO_WRITE, &ktruio, error); 23162378Sgreen } 23243412Snewton FREE(ktriov, M_TEMP); 23343412Snewton } 23443412Snewton#endif 23543412Snewtonbad: 23643412Snewton if (to) 23743412Snewton FREE(to, M_SONAME); 23886487Sdillondone1: 23986487Sdillon fputsock(so); 24043412Snewton return (error); 24143412Snewton} 24243412Snewton 24343412Snewtonstatic int 24483366Sjuliansvr4_recvit(td, s, mp, namelenp) 24583366Sjulian register struct thread *td; 24643412Snewton int s; 24743412Snewton register struct msghdr *mp; 24843412Snewton caddr_t namelenp; 24943412Snewton{ 25043412Snewton struct uio auio; 25143412Snewton register struct iovec *iov; 25243412Snewton register int i; 25343412Snewton int len, error; 25443412Snewton struct mbuf *m, *control = 0; 25543412Snewton caddr_t ctlbuf; 25643412Snewton struct socket *so; 25743412Snewton struct sockaddr *fromsa = 0; 25843412Snewton#ifdef KTRACE 25943412Snewton struct iovec *ktriov = NULL; 26062378Sgreen struct uio ktruio; 26143412Snewton#endif 26243412Snewton 26386487Sdillon if ((error = fgetsock(td, s, &so, NULL)) != 0) 26443412Snewton return (error); 26543412Snewton auio.uio_iov = mp->msg_iov; 26643412Snewton auio.uio_iovcnt = mp->msg_iovlen; 26743412Snewton auio.uio_segflg = UIO_USERSPACE; 26843412Snewton auio.uio_rw = UIO_READ; 26983366Sjulian auio.uio_td = td; 27043412Snewton auio.uio_offset = 0; /* XXX */ 27143412Snewton auio.uio_resid = 0; 27243412Snewton iov = mp->msg_iov; 27343412Snewton for (i = 0; i < mp->msg_iovlen; i++, iov++) { 27469084Sdillon if ((auio.uio_resid += iov->iov_len) < 0) { 27586487Sdillon error = EINVAL; 27686487Sdillon goto done1; 27769084Sdillon } 27843412Snewton } 27943412Snewton#ifdef KTRACE 28083366Sjulian if (KTRPOINT(td->td_proc, KTR_GENIO)) { 28143412Snewton int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 28243412Snewton 28343412Snewton MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 28443412Snewton bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 28562378Sgreen ktruio = auio; 28643412Snewton } 28743412Snewton#endif 28843412Snewton len = auio.uio_resid; 28943412Snewton error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, 29043412Snewton (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 29143412Snewton &mp->msg_flags); 29243412Snewton if (error) { 29343412Snewton if (auio.uio_resid != len && (error == ERESTART || 29443412Snewton error == EINTR || error == EWOULDBLOCK)) 29543412Snewton error = 0; 29643412Snewton } 29743412Snewton#ifdef KTRACE 29843412Snewton if (ktriov != NULL) { 29962378Sgreen if (error == 0) { 30062378Sgreen ktruio.uio_iov = ktriov; 30162378Sgreen ktruio.uio_resid = len - auio.uio_resid; 30283366Sjulian ktrgenio(td->td_proc->p_tracep, s, UIO_READ, &ktruio, error); 30362378Sgreen } 30443412Snewton FREE(ktriov, M_TEMP); 30543412Snewton } 30643412Snewton#endif 30743412Snewton if (error) 30843412Snewton goto out; 30983366Sjulian td->td_retval[0] = len - auio.uio_resid; 31043412Snewton if (mp->msg_name) { 31143412Snewton len = mp->msg_namelen; 31243412Snewton if (len <= 0 || fromsa == 0) 31343412Snewton len = 0; 31443412Snewton else { 31543412Snewton#ifndef MIN 31643412Snewton#define MIN(a,b) ((a)>(b)?(b):(a)) 31743412Snewton#endif 31843412Snewton /* save sa_len before it is destroyed by MSG_COMPAT */ 31943412Snewton len = MIN(len, fromsa->sa_len); 32043412Snewton error = copyout(fromsa, 32143412Snewton (caddr_t)mp->msg_name, (unsigned)len); 32243412Snewton if (error) 32343412Snewton goto out; 32443412Snewton } 32543412Snewton mp->msg_namelen = len; 32643412Snewton if (namelenp && 32743412Snewton (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 32843412Snewton goto out; 32943412Snewton } 33043412Snewton } 33143412Snewton if (mp->msg_control) { 33243412Snewton len = mp->msg_controllen; 33343412Snewton m = control; 33443412Snewton mp->msg_controllen = 0; 33543412Snewton ctlbuf = (caddr_t) mp->msg_control; 33643412Snewton 33743412Snewton while (m && len > 0) { 33843412Snewton unsigned int tocopy; 33943412Snewton 34043412Snewton if (len >= m->m_len) 34143412Snewton tocopy = m->m_len; 34243412Snewton else { 34343412Snewton mp->msg_flags |= MSG_CTRUNC; 34443412Snewton tocopy = len; 34543412Snewton } 34643412Snewton 34749267Snewton if ((error = copyout((caddr_t)mtod(m, caddr_t), 34849267Snewton ctlbuf, tocopy)) != 0) 34943412Snewton goto out; 35043412Snewton 35143412Snewton ctlbuf += tocopy; 35243412Snewton len -= tocopy; 35343412Snewton m = m->m_next; 35443412Snewton } 35553678Sphk mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control; 35643412Snewton } 35743412Snewtonout: 35843412Snewton if (fromsa) 35943412Snewton FREE(fromsa, M_SONAME); 36043412Snewton if (control) 36143412Snewton m_freem(control); 36286487Sdillondone1: 36386487Sdillon fputsock(so); 36443412Snewton return (error); 36543412Snewton} 36643412Snewton 36743412Snewton#ifdef DEBUG_SVR4 36892761Salfredstatic void bufprint(u_char *, size_t); 36992761Salfredstatic int show_ioc(const char *, struct svr4_strioctl *); 37092761Salfredstatic int show_strbuf(struct svr4_strbuf *); 37192761Salfredstatic void show_msg(const char *, int, struct svr4_strbuf *, 37292761Salfred struct svr4_strbuf *, int); 37343412Snewton 37443412Snewtonstatic void 37543412Snewtonbufprint(buf, len) 37643412Snewton u_char *buf; 37743412Snewton size_t len; 37843412Snewton{ 37943412Snewton size_t i; 38043412Snewton 38143412Snewton uprintf("\n\t"); 38243412Snewton for (i = 0; i < len; i++) { 38343412Snewton uprintf("%x ", buf[i]); 38443412Snewton if (i && (i % 16) == 0) 38543412Snewton uprintf("\n\t"); 38643412Snewton } 38743412Snewton} 38843412Snewton 38943412Snewtonstatic int 39043412Snewtonshow_ioc(str, ioc) 39143412Snewton const char *str; 39243412Snewton struct svr4_strioctl *ioc; 39343412Snewton{ 39443412Snewton u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK); 39543412Snewton int error; 39643412Snewton 39743412Snewton uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ", 39843412Snewton str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf); 39943412Snewton 40043412Snewton if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) { 40143412Snewton free((char *) ptr, M_TEMP); 40243412Snewton return error; 40343412Snewton } 40443412Snewton 40543412Snewton bufprint(ptr, ioc->len); 40643412Snewton 40743412Snewton uprintf("}\n"); 40843412Snewton 40943412Snewton free((char *) ptr, M_TEMP); 41043412Snewton return 0; 41143412Snewton} 41243412Snewton 41343412Snewton 41443412Snewtonstatic int 41543412Snewtonshow_strbuf(str) 41643412Snewton struct svr4_strbuf *str; 41743412Snewton{ 41843412Snewton int error; 41943412Snewton u_char *ptr = NULL; 42043412Snewton int maxlen = str->maxlen; 42143412Snewton int len = str->len; 42243412Snewton 42343412Snewton if (maxlen < 0) 42443412Snewton maxlen = 0; 42543412Snewton 42643412Snewton if (len >= maxlen) 42743412Snewton len = maxlen; 42843412Snewton 42943412Snewton if (len > 0) { 43043412Snewton ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK); 43143412Snewton 43243412Snewton if ((error = copyin(str->buf, ptr, len)) != 0) { 43343412Snewton free((char *) ptr, M_TEMP); 43443412Snewton return error; 43543412Snewton } 43643412Snewton } 43743412Snewton 43843412Snewton uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf); 43943412Snewton 44043412Snewton if (ptr) 44143412Snewton bufprint(ptr, len); 44243412Snewton 44343412Snewton uprintf("]}"); 44443412Snewton 44543412Snewton if (ptr) 44643412Snewton free((char *) ptr, M_TEMP); 44743412Snewton 44843412Snewton return 0; 44943412Snewton} 45043412Snewton 45143412Snewton 45243412Snewtonstatic void 45343412Snewtonshow_msg(str, fd, ctl, dat, flags) 45443412Snewton const char *str; 45543412Snewton int fd; 45643412Snewton struct svr4_strbuf *ctl; 45743412Snewton struct svr4_strbuf *dat; 45843412Snewton int flags; 45943412Snewton{ 46043412Snewton struct svr4_strbuf buf; 46143412Snewton int error; 46243412Snewton 46343412Snewton uprintf("%s(%d", str, fd); 46443412Snewton if (ctl != NULL) { 46543412Snewton if ((error = copyin(ctl, &buf, sizeof(buf))) != 0) 46643412Snewton return; 46743412Snewton show_strbuf(&buf); 46843412Snewton } 46943412Snewton else 47043412Snewton uprintf(", NULL"); 47143412Snewton 47243412Snewton if (dat != NULL) { 47343412Snewton if ((error = copyin(dat, &buf, sizeof(buf))) != 0) 47443412Snewton return; 47543412Snewton show_strbuf(&buf); 47643412Snewton } 47743412Snewton else 47843412Snewton uprintf(", NULL"); 47943412Snewton 48043412Snewton uprintf(", %x);\n", flags); 48143412Snewton} 48243412Snewton 48343412Snewton#endif /* DEBUG_SVR4 */ 48443412Snewton 48543412Snewton/* 48643412Snewton * We are faced with an interesting situation. On svr4 unix sockets 48743412Snewton * are really pipes. But we really have sockets, and we might as 48843412Snewton * well use them. At the point where svr4 calls TI_BIND, it has 48943412Snewton * already created a named pipe for the socket using mknod(2). 49043412Snewton * We need to create a socket with the same name when we bind, 49143412Snewton * so we need to remove the pipe before, otherwise we'll get address 49243412Snewton * already in use. So we *carefully* remove the pipe, to avoid 49343412Snewton * using this as a random file removal tool. We use system calls 49443412Snewton * to avoid code duplication. 49543412Snewton */ 49643412Snewtonstatic int 49783366Sjulianclean_pipe(td, path) 49883366Sjulian struct thread *td; 49943412Snewton const char *path; 50043412Snewton{ 50143412Snewton struct lstat_args la; 50243412Snewton struct unlink_args ua; 50343412Snewton struct stat st; 50443412Snewton int error; 50543412Snewton caddr_t sg = stackgap_init(); 50643412Snewton size_t l = strlen(path) + 1; 50743412Snewton void *tpath; 50843412Snewton 50943412Snewton tpath = stackgap_alloc(&sg, l); 51043412Snewton SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat)); 51143412Snewton 51243412Snewton if ((error = copyout(path, tpath, l)) != 0) 51343412Snewton return error; 51443412Snewton 51543412Snewton SCARG(&la, path) = tpath; 51643412Snewton 51783366Sjulian if ((error = lstat(td, &la)) != 0) 51843412Snewton return 0; 51943412Snewton 52043412Snewton if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0) 52143412Snewton return 0; 52243412Snewton 52343412Snewton /* 52443412Snewton * Make sure we are dealing with a mode 0 named pipe. 52543412Snewton */ 52643412Snewton if ((st.st_mode & S_IFMT) != S_IFIFO) 52743412Snewton return 0; 52843412Snewton 52943412Snewton if ((st.st_mode & ALLPERMS) != 0) 53043412Snewton return 0; 53143412Snewton 53243412Snewton SCARG(&ua, path) = SCARG(&la, path); 53343412Snewton 53483366Sjulian if ((error = unlink(td, &ua)) != 0) { 53543412Snewton DPRINTF(("clean_pipe: unlink failed %d\n", error)); 53643412Snewton return error; 53743412Snewton } 53843412Snewton 53943412Snewton return 0; 54043412Snewton} 54143412Snewton 54243412Snewton 54343412Snewtonstatic void 54443412Snewtonsockaddr_to_netaddr_in(sc, sain) 54543412Snewton struct svr4_strmcmd *sc; 54643412Snewton const struct sockaddr_in *sain; 54743412Snewton{ 54843412Snewton struct svr4_netaddr_in *na; 54943412Snewton na = SVR4_ADDROF(sc); 55043412Snewton 55143412Snewton na->family = sain->sin_family; 55243412Snewton na->port = sain->sin_port; 55343412Snewton na->addr = sain->sin_addr.s_addr; 55443412Snewton DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port, 55543412Snewton na->addr)); 55643412Snewton} 55743412Snewton 55843412Snewton 55943412Snewtonstatic void 56043412Snewtonsockaddr_to_netaddr_un(sc, saun) 56143412Snewton struct svr4_strmcmd *sc; 56243412Snewton const struct sockaddr_un *saun; 56343412Snewton{ 56443412Snewton struct svr4_netaddr_un *na; 56543412Snewton char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 - 56643412Snewton sizeof(*sc); 56743412Snewton const char *src; 56843412Snewton 56943412Snewton na = SVR4_ADDROF(sc); 57043412Snewton na->family = saun->sun_family; 57143412Snewton for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; ) 57243412Snewton if (dst == edst) 57343412Snewton break; 57443412Snewton DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path)); 57543412Snewton} 57643412Snewton 57743412Snewton 57843412Snewtonstatic void 57943412Snewtonnetaddr_to_sockaddr_in(sain, sc) 58043412Snewton struct sockaddr_in *sain; 58143412Snewton const struct svr4_strmcmd *sc; 58243412Snewton{ 58343412Snewton const struct svr4_netaddr_in *na; 58443412Snewton 58543412Snewton 58643412Snewton na = SVR4_C_ADDROF(sc); 58743412Snewton memset(sain, 0, sizeof(*sain)); 58843412Snewton sain->sin_len = sizeof(*sain); 58943412Snewton sain->sin_family = na->family; 59043412Snewton sain->sin_port = na->port; 59143412Snewton sain->sin_addr.s_addr = na->addr; 59243412Snewton DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family, 59343412Snewton sain->sin_port, sain->sin_addr.s_addr)); 59443412Snewton} 59543412Snewton 59643412Snewton 59743412Snewtonstatic void 59843412Snewtonnetaddr_to_sockaddr_un(saun, sc) 59943412Snewton struct sockaddr_un *saun; 60043412Snewton const struct svr4_strmcmd *sc; 60143412Snewton{ 60243412Snewton const struct svr4_netaddr_un *na; 60343412Snewton char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1]; 60443412Snewton const char *src; 60543412Snewton 60643412Snewton na = SVR4_C_ADDROF(sc); 60743412Snewton memset(saun, 0, sizeof(*saun)); 60843412Snewton saun->sun_family = na->family; 60943412Snewton for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; ) 61043412Snewton if (dst == edst) 61143412Snewton break; 61243412Snewton saun->sun_len = dst - saun->sun_path; 61343412Snewton DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family, 61443412Snewton saun->sun_path)); 61543412Snewton} 61643412Snewton 61743412Snewton 61843412Snewtonstatic void 61943412Snewtongetparm(fp, pa) 62043412Snewton struct file *fp; 62143412Snewton struct svr4_si_sockparms *pa; 62243412Snewton{ 62389306Salfred struct svr4_strm *st; 62489306Salfred struct socket *so; 62543412Snewton 62689306Salfred st = svr4_stream_get(fp); 62743412Snewton if (st == NULL) 62843412Snewton return; 62943412Snewton 63089306Salfred so = (struct socket *) fp->f_data; 63189306Salfred 63243412Snewton pa->family = st->s_family; 63343412Snewton 63443412Snewton switch (so->so_type) { 63543412Snewton case SOCK_DGRAM: 63643412Snewton pa->type = SVR4_T_CLTS; 63743412Snewton pa->protocol = IPPROTO_UDP; 63843412Snewton DPRINTF(("getparm(dgram)\n")); 63943412Snewton return; 64043412Snewton 64143412Snewton case SOCK_STREAM: 64243412Snewton pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */ 64343412Snewton pa->protocol = IPPROTO_IP; 64443412Snewton DPRINTF(("getparm(stream)\n")); 64543412Snewton return; 64643412Snewton 64743412Snewton case SOCK_RAW: 64843412Snewton pa->type = SVR4_T_CLTS; 64943412Snewton pa->protocol = IPPROTO_RAW; 65043412Snewton DPRINTF(("getparm(raw)\n")); 65143412Snewton return; 65243412Snewton 65343412Snewton default: 65443412Snewton pa->type = 0; 65543412Snewton pa->protocol = 0; 65643412Snewton DPRINTF(("getparm(type %d?)\n", so->so_type)); 65743412Snewton return; 65843412Snewton } 65943412Snewton} 66043412Snewton 66143412Snewton 66243412Snewtonstatic int 66383366Sjuliansi_ogetudata(fp, fd, ioc, td) 66443412Snewton struct file *fp; 66543412Snewton int fd; 66643412Snewton struct svr4_strioctl *ioc; 66783366Sjulian struct thread *td; 66843412Snewton{ 66943412Snewton int error; 67043412Snewton struct svr4_si_oudata ud; 67143412Snewton struct svr4_si_sockparms pa; 67243412Snewton 67343412Snewton if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) { 67443412Snewton DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n", 67543412Snewton sizeof(ud), ioc->len)); 67643412Snewton return EINVAL; 67743412Snewton } 67843412Snewton 67943412Snewton if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 68043412Snewton return error; 68143412Snewton 68243412Snewton getparm(fp, &pa); 68343412Snewton 68443412Snewton switch (pa.family) { 68543412Snewton case AF_INET: 68643412Snewton ud.tidusize = 16384; 68743412Snewton ud.addrsize = sizeof(struct svr4_sockaddr_in); 68843412Snewton if (pa.type == SVR4_SOCK_STREAM) 68943412Snewton ud.etsdusize = 1; 69043412Snewton else 69143412Snewton ud.etsdusize = 0; 69243412Snewton break; 69343412Snewton 69443412Snewton case AF_LOCAL: 69543412Snewton ud.tidusize = 65536; 69643412Snewton ud.addrsize = 128; 69743412Snewton ud.etsdusize = 128; 69843412Snewton break; 69943412Snewton 70043412Snewton default: 70143412Snewton DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n", 70243412Snewton pa.family)); 70343412Snewton return ENOSYS; 70443412Snewton } 70543412Snewton 70643412Snewton /* I have no idea what these should be! */ 70743412Snewton ud.optsize = 128; 70843412Snewton ud.tsdusize = 128; 70943412Snewton 71043412Snewton ud.servtype = pa.type; 71143412Snewton 71243412Snewton /* XXX: Fixme */ 71343412Snewton ud.so_state = 0; 71443412Snewton ud.so_options = 0; 71543412Snewton return copyout(&ud, ioc->buf, ioc->len); 71643412Snewton} 71743412Snewton 71843412Snewton 71943412Snewtonstatic int 72083366Sjuliansi_sockparams(fp, fd, ioc, td) 72143412Snewton struct file *fp; 72243412Snewton int fd; 72343412Snewton struct svr4_strioctl *ioc; 72483366Sjulian struct thread *td; 72543412Snewton{ 72643412Snewton struct svr4_si_sockparms pa; 72743412Snewton 72843412Snewton getparm(fp, &pa); 72943412Snewton return copyout(&pa, ioc->buf, sizeof(pa)); 73043412Snewton} 73143412Snewton 73243412Snewton 73343412Snewtonstatic int 73483366Sjuliansi_listen(fp, fd, ioc, td) 73543412Snewton struct file *fp; 73643412Snewton int fd; 73743412Snewton struct svr4_strioctl *ioc; 73883366Sjulian struct thread *td; 73943412Snewton{ 74043412Snewton int error; 74143412Snewton struct svr4_strm *st = svr4_stream_get(fp); 74243412Snewton struct svr4_strmcmd lst; 74343412Snewton struct listen_args la; 74443412Snewton 74543412Snewton if (st == NULL) 74643412Snewton return EINVAL; 74743412Snewton 74843412Snewton if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0) 74943412Snewton return error; 75043412Snewton 75143412Snewton if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) { 75243412Snewton DPRINTF(("si_listen: bad request %ld\n", lst.cmd)); 75343412Snewton return EINVAL; 75443412Snewton } 75543412Snewton 75643412Snewton /* 75743412Snewton * We are making assumptions again... 75843412Snewton */ 75943412Snewton SCARG(&la, s) = fd; 76043412Snewton DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5)); 76143412Snewton SCARG(&la, backlog) = 5; 76243412Snewton 76383366Sjulian if ((error = listen(td, &la)) != 0) { 76443412Snewton DPRINTF(("SI_LISTEN: listen failed %d\n", error)); 76543412Snewton return error; 76643412Snewton } 76743412Snewton 76843412Snewton st->s_cmd = SVR4_TI__ACCEPT_WAIT; 76943412Snewton lst.cmd = SVR4_TI_BIND_REPLY; 77043412Snewton 77143412Snewton switch (st->s_family) { 77243412Snewton case AF_INET: 77343412Snewton /* XXX: Fill the length here */ 77443412Snewton break; 77543412Snewton 77643412Snewton case AF_LOCAL: 77743412Snewton lst.len = 140; 77843412Snewton lst.pad[28] = 0x00000000; /* magic again */ 77943412Snewton lst.pad[29] = 0x00000800; /* magic again */ 78043412Snewton lst.pad[30] = 0x80001400; /* magic again */ 78143412Snewton break; 78243412Snewton 78343412Snewton default: 78443412Snewton DPRINTF(("SI_LISTEN: Unsupported address family %d\n", 78543412Snewton st->s_family)); 78643412Snewton return ENOSYS; 78743412Snewton } 78843412Snewton 78943412Snewton 79043412Snewton if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0) 79143412Snewton return error; 79243412Snewton 79343412Snewton return 0; 79443412Snewton} 79543412Snewton 79643412Snewton 79743412Snewtonstatic int 79883366Sjuliansi_getudata(fp, fd, ioc, td) 79943412Snewton struct file *fp; 80043412Snewton int fd; 80143412Snewton struct svr4_strioctl *ioc; 80283366Sjulian struct thread *td; 80343412Snewton{ 80443412Snewton int error; 80543412Snewton struct svr4_si_udata ud; 80643412Snewton 80743412Snewton if (sizeof(ud) != ioc->len) { 80843412Snewton DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n", 80943412Snewton sizeof(ud), ioc->len)); 81043412Snewton return EINVAL; 81143412Snewton } 81243412Snewton 81343412Snewton if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 81443412Snewton return error; 81543412Snewton 81643412Snewton getparm(fp, &ud.sockparms); 81743412Snewton 81843412Snewton switch (ud.sockparms.family) { 81943412Snewton case AF_INET: 82043412Snewton DPRINTF(("getudata_inet\n")); 82143412Snewton ud.tidusize = 16384; 82243412Snewton ud.tsdusize = 16384; 82343412Snewton ud.addrsize = sizeof(struct svr4_sockaddr_in); 82443412Snewton if (ud.sockparms.type == SVR4_SOCK_STREAM) 82543412Snewton ud.etsdusize = 1; 82643412Snewton else 82743412Snewton ud.etsdusize = 0; 82843412Snewton ud.optsize = 0; 82943412Snewton break; 83043412Snewton 83143412Snewton case AF_LOCAL: 83243412Snewton DPRINTF(("getudata_local\n")); 83343412Snewton ud.tidusize = 65536; 83443412Snewton ud.tsdusize = 128; 83543412Snewton ud.addrsize = 128; 83643412Snewton ud.etsdusize = 128; 83743412Snewton ud.optsize = 128; 83843412Snewton break; 83943412Snewton 84043412Snewton default: 84143412Snewton DPRINTF(("SI_GETUDATA: Unsupported address family %d\n", 84243412Snewton ud.sockparms.family)); 84343412Snewton return ENOSYS; 84443412Snewton } 84543412Snewton 84643412Snewton 84743412Snewton ud.servtype = ud.sockparms.type; 84843412Snewton DPRINTF(("ud.servtype = %d\n", ud.servtype)); 84943412Snewton /* XXX: Fixme */ 85043412Snewton ud.so_state = 0; 85143412Snewton ud.so_options = 0; 85243412Snewton return copyout(&ud, ioc->buf, sizeof(ud)); 85343412Snewton} 85443412Snewton 85543412Snewton 85643412Snewtonstatic int 85783366Sjuliansi_shutdown(fp, fd, ioc, td) 85843412Snewton struct file *fp; 85943412Snewton int fd; 86043412Snewton struct svr4_strioctl *ioc; 86183366Sjulian struct thread *td; 86243412Snewton{ 86343412Snewton int error; 86443412Snewton struct shutdown_args ap; 86543412Snewton 86643412Snewton if (ioc->len != sizeof(SCARG(&ap, how))) { 86743412Snewton DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n", 86843412Snewton sizeof(SCARG(&ap, how)), ioc->len)); 86943412Snewton return EINVAL; 87043412Snewton } 87143412Snewton 87243412Snewton if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0) 87343412Snewton return error; 87443412Snewton 87543412Snewton SCARG(&ap, s) = fd; 87643412Snewton 87783366Sjulian return shutdown(td, &ap); 87843412Snewton} 87943412Snewton 88043412Snewton 88143412Snewtonstatic int 88283366Sjuliansockmod(fp, fd, ioc, td) 88343412Snewton struct file *fp; 88443412Snewton int fd; 88543412Snewton struct svr4_strioctl *ioc; 88683366Sjulian struct thread *td; 88743412Snewton{ 88843412Snewton switch (ioc->cmd) { 88943412Snewton case SVR4_SI_OGETUDATA: 89043412Snewton DPRINTF(("SI_OGETUDATA\n")); 89183366Sjulian return si_ogetudata(fp, fd, ioc, td); 89243412Snewton 89343412Snewton case SVR4_SI_SHUTDOWN: 89443412Snewton DPRINTF(("SI_SHUTDOWN\n")); 89583366Sjulian return si_shutdown(fp, fd, ioc, td); 89643412Snewton 89743412Snewton case SVR4_SI_LISTEN: 89843412Snewton DPRINTF(("SI_LISTEN\n")); 89983366Sjulian return si_listen(fp, fd, ioc, td); 90043412Snewton 90143412Snewton case SVR4_SI_SETMYNAME: 90243412Snewton DPRINTF(("SI_SETMYNAME\n")); 90343412Snewton return 0; 90443412Snewton 90543412Snewton case SVR4_SI_SETPEERNAME: 90643412Snewton DPRINTF(("SI_SETPEERNAME\n")); 90743412Snewton return 0; 90843412Snewton 90943412Snewton case SVR4_SI_GETINTRANSIT: 91043412Snewton DPRINTF(("SI_GETINTRANSIT\n")); 91143412Snewton return 0; 91243412Snewton 91343412Snewton case SVR4_SI_TCL_LINK: 91443412Snewton DPRINTF(("SI_TCL_LINK\n")); 91543412Snewton return 0; 91643412Snewton 91743412Snewton case SVR4_SI_TCL_UNLINK: 91843412Snewton DPRINTF(("SI_TCL_UNLINK\n")); 91943412Snewton return 0; 92043412Snewton 92143412Snewton case SVR4_SI_SOCKPARAMS: 92243412Snewton DPRINTF(("SI_SOCKPARAMS\n")); 92383366Sjulian return si_sockparams(fp, fd, ioc, td); 92443412Snewton 92543412Snewton case SVR4_SI_GETUDATA: 92643412Snewton DPRINTF(("SI_GETUDATA\n")); 92783366Sjulian return si_getudata(fp, fd, ioc, td); 92843412Snewton 92943412Snewton default: 93043412Snewton DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd)); 93143412Snewton return 0; 93243412Snewton 93343412Snewton } 93443412Snewton} 93543412Snewton 93643412Snewton 93743412Snewtonstatic int 93883366Sjulianti_getinfo(fp, fd, ioc, td) 93943412Snewton struct file *fp; 94043412Snewton int fd; 94143412Snewton struct svr4_strioctl *ioc; 94283366Sjulian struct thread *td; 94343412Snewton{ 94443412Snewton int error; 94543412Snewton struct svr4_infocmd info; 94643412Snewton 94743412Snewton memset(&info, 0, sizeof(info)); 94843412Snewton 94943412Snewton if ((error = copyin(ioc->buf, &info, ioc->len)) != 0) 95043412Snewton return error; 95143412Snewton 95243412Snewton if (info.cmd != SVR4_TI_INFO_REQUEST) 95343412Snewton return EINVAL; 95443412Snewton 95543412Snewton info.cmd = SVR4_TI_INFO_REPLY; 95643412Snewton info.tsdu = 0; 95743412Snewton info.etsdu = 1; 95843412Snewton info.cdata = -2; 95943412Snewton info.ddata = -2; 96043412Snewton info.addr = 16; 96143412Snewton info.opt = -1; 96243412Snewton info.tidu = 16384; 96343412Snewton info.serv = 2; 96443412Snewton info.current = 0; 96543412Snewton info.provider = 2; 96643412Snewton 96743412Snewton ioc->len = sizeof(info); 96843412Snewton if ((error = copyout(&info, ioc->buf, ioc->len)) != 0) 96943412Snewton return error; 97043412Snewton 97143412Snewton return 0; 97243412Snewton} 97343412Snewton 97443412Snewton 97543412Snewtonstatic int 97683366Sjulianti_bind(fp, fd, ioc, td) 97743412Snewton struct file *fp; 97843412Snewton int fd; 97943412Snewton struct svr4_strioctl *ioc; 98083366Sjulian struct thread *td; 98143412Snewton{ 98243412Snewton int error; 98343412Snewton struct svr4_strm *st = svr4_stream_get(fp); 98443412Snewton struct sockaddr_in sain; 98543412Snewton struct sockaddr_un saun; 98643412Snewton caddr_t sg; 98743412Snewton void *skp, *sup = NULL; 98843412Snewton int sasize; 98943412Snewton struct svr4_strmcmd bnd; 99043412Snewton struct bind_args ba; 99143412Snewton 99243412Snewton if (st == NULL) { 99343412Snewton DPRINTF(("ti_bind: bad file descriptor\n")); 99443412Snewton return EINVAL; 99543412Snewton } 99643412Snewton 99743412Snewton if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0) 99843412Snewton return error; 99943412Snewton 100043412Snewton if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) { 100143412Snewton DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd)); 100243412Snewton return EINVAL; 100343412Snewton } 100443412Snewton 100543412Snewton switch (st->s_family) { 100643412Snewton case AF_INET: 100743412Snewton skp = &sain; 100843412Snewton sasize = sizeof(sain); 100943412Snewton 101043412Snewton if (bnd.offs == 0) 101143412Snewton goto reply; 101243412Snewton 101343412Snewton netaddr_to_sockaddr_in(&sain, &bnd); 101443412Snewton 101543412Snewton DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n", 101643412Snewton sain.sin_family, sain.sin_port, 101743412Snewton sain.sin_addr.s_addr)); 101843412Snewton break; 101943412Snewton 102043412Snewton case AF_LOCAL: 102143412Snewton skp = &saun; 102243412Snewton sasize = sizeof(saun); 102343412Snewton if (bnd.offs == 0) 102443412Snewton goto reply; 102543412Snewton 102643412Snewton netaddr_to_sockaddr_un(&saun, &bnd); 102743412Snewton 102843412Snewton if (saun.sun_path[0] == '\0') 102943412Snewton goto reply; 103043412Snewton 103143412Snewton DPRINTF(("TI_BIND: fam %d, path %s\n", 103243412Snewton saun.sun_family, saun.sun_path)); 103343412Snewton 103483366Sjulian if ((error = clean_pipe(td, saun.sun_path)) != 0) 103543412Snewton return error; 103643412Snewton 103743412Snewton bnd.pad[28] = 0x00001000; /* magic again */ 103843412Snewton break; 103943412Snewton 104043412Snewton default: 104143412Snewton DPRINTF(("TI_BIND: Unsupported address family %d\n", 104243412Snewton st->s_family)); 104343412Snewton return ENOSYS; 104443412Snewton } 104543412Snewton 104643412Snewton sg = stackgap_init(); 104743412Snewton sup = stackgap_alloc(&sg, sasize); 104843412Snewton 104943412Snewton if ((error = copyout(skp, sup, sasize)) != 0) 105043412Snewton return error; 105143412Snewton 105243412Snewton SCARG(&ba, s) = fd; 105343412Snewton DPRINTF(("TI_BIND: fileno %d\n", fd)); 105443412Snewton SCARG(&ba, name) = (void *) sup; 105543412Snewton SCARG(&ba, namelen) = sasize; 105643412Snewton 105783366Sjulian if ((error = bind(td, &ba)) != 0) { 105843412Snewton DPRINTF(("TI_BIND: bind failed %d\n", error)); 105943412Snewton return error; 106043412Snewton } 106143412Snewton 106243412Snewtonreply: 106343412Snewton if (sup == NULL) { 106443412Snewton memset(&bnd, 0, sizeof(bnd)); 106543412Snewton bnd.len = sasize + 4; 106643412Snewton bnd.offs = 0x10; /* XXX */ 106743412Snewton } 106843412Snewton 106943412Snewton bnd.cmd = SVR4_TI_BIND_REPLY; 107043412Snewton 107143412Snewton if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0) 107243412Snewton return error; 107343412Snewton 107443412Snewton return 0; 107543412Snewton} 107643412Snewton 107743412Snewton 107843412Snewtonstatic int 107983366Sjuliantimod(fp, fd, ioc, td) 108043412Snewton struct file *fp; 108143412Snewton int fd; 108243412Snewton struct svr4_strioctl *ioc; 108383366Sjulian struct thread *td; 108443412Snewton{ 108543412Snewton switch (ioc->cmd) { 108643412Snewton case SVR4_TI_GETINFO: 108743412Snewton DPRINTF(("TI_GETINFO\n")); 108883366Sjulian return ti_getinfo(fp, fd, ioc, td); 108943412Snewton 109043412Snewton case SVR4_TI_OPTMGMT: 109143412Snewton DPRINTF(("TI_OPTMGMT\n")); 109243412Snewton return 0; 109343412Snewton 109443412Snewton case SVR4_TI_BIND: 109543412Snewton DPRINTF(("TI_BIND\n")); 109683366Sjulian return ti_bind(fp, fd, ioc, td); 109743412Snewton 109843412Snewton case SVR4_TI_UNBIND: 109943412Snewton DPRINTF(("TI_UNBIND\n")); 110043412Snewton return 0; 110143412Snewton 110243412Snewton default: 110343412Snewton DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd)); 110443412Snewton return 0; 110543412Snewton } 110643412Snewton} 110743412Snewton 110843412Snewton 110943412Snewtonint 111083366Sjuliansvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat) 111143412Snewton struct file *fp; 111283366Sjulian struct thread *td; 111343412Snewton register_t *retval; 111443412Snewton int fd; 111543412Snewton u_long cmd; 111643412Snewton caddr_t dat; 111743412Snewton{ 111843412Snewton struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat; 111943412Snewton struct svr4_strm *st = svr4_stream_get(fp); 112043412Snewton int error; 112143412Snewton void *skp, *sup; 112243412Snewton struct sockaddr_in sain; 112343412Snewton struct sockaddr_un saun; 112443412Snewton struct svr4_strmcmd sc; 112543412Snewton int sasize; 112643412Snewton caddr_t sg; 112743412Snewton int *lenp; 112843412Snewton 112943412Snewton DPRINTF(("svr4_stream_ti_ioctl\n")); 113043412Snewton 113143412Snewton if (st == NULL) 113243412Snewton return EINVAL; 113343412Snewton 113443412Snewton sc.offs = 0x10; 113543412Snewton 113643412Snewton if ((error = copyin(sub, &skb, sizeof(skb))) != 0) { 113743412Snewton DPRINTF(("ti_ioctl: error copying in strbuf\n")); 113843412Snewton return error; 113943412Snewton } 114043412Snewton 114143412Snewton switch (st->s_family) { 114243412Snewton case AF_INET: 114343412Snewton skp = &sain; 114443412Snewton sasize = sizeof(sain); 114543412Snewton break; 114643412Snewton 114743412Snewton case AF_LOCAL: 114843412Snewton skp = &saun; 114943412Snewton sasize = sizeof(saun); 115043412Snewton break; 115143412Snewton 115243412Snewton default: 115343412Snewton DPRINTF(("ti_ioctl: Unsupported address family %d\n", 115443412Snewton st->s_family)); 115543412Snewton return ENOSYS; 115643412Snewton } 115743412Snewton 115843412Snewton sg = stackgap_init(); 115943412Snewton sup = stackgap_alloc(&sg, sasize); 116043412Snewton lenp = stackgap_alloc(&sg, sizeof(*lenp)); 116143412Snewton 116243412Snewton if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) { 116343412Snewton DPRINTF(("ti_ioctl: error copying out lenp\n")); 116443412Snewton return error; 116543412Snewton } 116643412Snewton 116743412Snewton switch (cmd) { 116843412Snewton case SVR4_TI_GETMYNAME: 116943412Snewton DPRINTF(("TI_GETMYNAME\n")); 117043412Snewton { 117143412Snewton struct getsockname_args ap; 117243412Snewton SCARG(&ap, fdes) = fd; 117343412Snewton SCARG(&ap, asa) = sup; 117443412Snewton SCARG(&ap, alen) = lenp; 117583366Sjulian if ((error = getsockname(td, &ap)) != 0) { 117643412Snewton DPRINTF(("ti_ioctl: getsockname error\n")); 117743412Snewton return error; 117843412Snewton } 117943412Snewton } 118043412Snewton break; 118143412Snewton 118243412Snewton case SVR4_TI_GETPEERNAME: 118343412Snewton DPRINTF(("TI_GETPEERNAME\n")); 118443412Snewton { 118543412Snewton struct getpeername_args ap; 118643412Snewton SCARG(&ap, fdes) = fd; 118743412Snewton SCARG(&ap, asa) = sup; 118843412Snewton SCARG(&ap, alen) = lenp; 118983366Sjulian if ((error = getpeername(td, &ap)) != 0) { 119043412Snewton DPRINTF(("ti_ioctl: getpeername error\n")); 119143412Snewton return error; 119243412Snewton } 119343412Snewton } 119443412Snewton break; 119543412Snewton 119643412Snewton case SVR4_TI_SETMYNAME: 119743412Snewton DPRINTF(("TI_SETMYNAME\n")); 119843412Snewton return 0; 119943412Snewton 120043412Snewton case SVR4_TI_SETPEERNAME: 120143412Snewton DPRINTF(("TI_SETPEERNAME\n")); 120243412Snewton return 0; 120343412Snewton default: 120443412Snewton DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd)); 120543412Snewton return ENOSYS; 120643412Snewton } 120743412Snewton 120843412Snewton if ((error = copyin(sup, skp, sasize)) != 0) { 120943412Snewton DPRINTF(("ti_ioctl: error copying in socket data\n")); 121043412Snewton return error; 121143412Snewton } 121243412Snewton 121343412Snewton if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) { 121443412Snewton DPRINTF(("ti_ioctl: error copying in socket size\n")); 121543412Snewton return error; 121643412Snewton } 121743412Snewton 121843412Snewton switch (st->s_family) { 121943412Snewton case AF_INET: 122043412Snewton sockaddr_to_netaddr_in(&sc, &sain); 122143412Snewton skb.len = sasize; 122243412Snewton break; 122343412Snewton 122443412Snewton case AF_LOCAL: 122543412Snewton sockaddr_to_netaddr_un(&sc, &saun); 122643412Snewton skb.len = sasize + 4; 122743412Snewton break; 122843412Snewton 122943412Snewton default: 123043412Snewton return ENOSYS; 123143412Snewton } 123243412Snewton 123343412Snewton 123443412Snewton if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) { 123543412Snewton DPRINTF(("ti_ioctl: error copying out socket data\n")); 123643412Snewton return error; 123743412Snewton } 123843412Snewton 123943412Snewton 124043412Snewton if ((error = copyout(&skb, sub, sizeof(skb))) != 0) { 124143412Snewton DPRINTF(("ti_ioctl: error copying out strbuf\n")); 124243412Snewton return error; 124343412Snewton } 124443412Snewton 124543412Snewton return error; 124643412Snewton} 124743412Snewton 124843412Snewton 124943412Snewton 125043412Snewton 125143412Snewtonstatic int 125283366Sjuliani_nread(fp, td, retval, fd, cmd, dat) 125343412Snewton struct file *fp; 125483366Sjulian struct thread *td; 125543412Snewton register_t *retval; 125643412Snewton int fd; 125743412Snewton u_long cmd; 125843412Snewton caddr_t dat; 125943412Snewton{ 126043412Snewton int error; 126143412Snewton int nread = 0; 126243412Snewton 126343412Snewton /* 126443412Snewton * We are supposed to return the message length in nread, and the 126543412Snewton * number of messages in retval. We don't have the notion of number 126643412Snewton * of stream messages, so we just find out if we have any bytes waiting 126743412Snewton * for us, and if we do, then we assume that we have at least one 126843412Snewton * message waiting for us. 126943412Snewton */ 127083366Sjulian if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td)) != 0) 127143412Snewton return error; 127243412Snewton 127343412Snewton if (nread != 0) 127443412Snewton *retval = 1; 127543412Snewton else 127643412Snewton *retval = 0; 127743412Snewton 127843412Snewton return copyout(&nread, dat, sizeof(nread)); 127943412Snewton} 128043412Snewton 128143412Snewtonstatic int 128283366Sjuliani_fdinsert(fp, td, retval, fd, cmd, dat) 128343412Snewton struct file *fp; 128483366Sjulian struct thread *td; 128543412Snewton register_t *retval; 128643412Snewton int fd; 128743412Snewton u_long cmd; 128843412Snewton caddr_t dat; 128943412Snewton{ 129043412Snewton /* 129143412Snewton * Major hack again here. We assume that we are using this to 129243412Snewton * implement accept(2). If that is the case, we have already 129343412Snewton * called accept, and we have stored the file descriptor in 129443412Snewton * afd. We find the file descriptor that the code wants to use 129543412Snewton * in fd insert, and then we dup2() our accepted file descriptor 129643412Snewton * to it. 129743412Snewton */ 129843412Snewton int error; 129943412Snewton struct svr4_strm *st = svr4_stream_get(fp); 130043412Snewton struct svr4_strfdinsert fdi; 130143412Snewton struct dup2_args d2p; 130243412Snewton struct close_args clp; 130343412Snewton 130443412Snewton if (st == NULL) { 130543412Snewton DPRINTF(("fdinsert: bad file type\n")); 130643412Snewton return EINVAL; 130743412Snewton } 130843412Snewton 130943412Snewton if (st->s_afd == -1) { 131043412Snewton DPRINTF(("fdinsert: accept fd not found\n")); 131143412Snewton return ENOENT; 131243412Snewton } 131343412Snewton 131443412Snewton if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) { 131543412Snewton DPRINTF(("fdinsert: copyin failed %d\n", error)); 131643412Snewton return error; 131743412Snewton } 131843412Snewton 131943412Snewton SCARG(&d2p, from) = st->s_afd; 132043412Snewton SCARG(&d2p, to) = fdi.fd; 132143412Snewton 132283366Sjulian if ((error = dup2(td, &d2p)) != 0) { 132343412Snewton DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n", 132443412Snewton st->s_afd, fdi.fd, error)); 132543412Snewton return error; 132643412Snewton } 132743412Snewton 132843412Snewton SCARG(&clp, fd) = st->s_afd; 132943412Snewton 133083366Sjulian if ((error = close(td, &clp)) != 0) { 133143412Snewton DPRINTF(("fdinsert: close(%d) failed %d\n", 133243412Snewton st->s_afd, error)); 133343412Snewton return error; 133443412Snewton } 133543412Snewton 133643412Snewton st->s_afd = -1; 133743412Snewton 133843412Snewton *retval = 0; 133943412Snewton return 0; 134043412Snewton} 134143412Snewton 134243412Snewton 134343412Snewtonstatic int 134483366Sjulian_i_bind_rsvd(fp, td, retval, fd, cmd, dat) 134543412Snewton struct file *fp; 134683366Sjulian struct thread *td; 134743412Snewton register_t *retval; 134843412Snewton int fd; 134943412Snewton u_long cmd; 135043412Snewton caddr_t dat; 135143412Snewton{ 135243412Snewton struct mkfifo_args ap; 135343412Snewton 135443412Snewton /* 135543412Snewton * This is a supposed to be a kernel and library only ioctl. 135643412Snewton * It gets called before ti_bind, when we have a unix 135743412Snewton * socket, to physically create the socket transport and 135843412Snewton * ``reserve'' it. I don't know how this get reserved inside 135943412Snewton * the kernel, but we are going to create it nevertheless. 136043412Snewton */ 136143412Snewton SCARG(&ap, path) = dat; 136243412Snewton SCARG(&ap, mode) = S_IFIFO; 136343412Snewton 136483366Sjulian return mkfifo(td, &ap); 136543412Snewton} 136643412Snewton 136743412Snewtonstatic int 136883366Sjulian_i_rele_rsvd(fp, td, retval, fd, cmd, dat) 136943412Snewton struct file *fp; 137083366Sjulian struct thread *td; 137143412Snewton register_t *retval; 137243412Snewton int fd; 137343412Snewton u_long cmd; 137443412Snewton caddr_t dat; 137543412Snewton{ 137643412Snewton struct unlink_args ap; 137743412Snewton 137843412Snewton /* 137943412Snewton * This is a supposed to be a kernel and library only ioctl. 138043412Snewton * I guess it is supposed to release the socket. 138143412Snewton */ 138243412Snewton SCARG(&ap, path) = dat; 138343412Snewton 138483366Sjulian return unlink(td, &ap); 138543412Snewton} 138643412Snewton 138743412Snewtonstatic int 138883366Sjuliani_str(fp, td, retval, fd, cmd, dat) 138943412Snewton struct file *fp; 139083366Sjulian struct thread *td; 139143412Snewton register_t *retval; 139243412Snewton int fd; 139343412Snewton u_long cmd; 139443412Snewton caddr_t dat; 139543412Snewton{ 139643412Snewton int error; 139743412Snewton struct svr4_strioctl ioc; 139843412Snewton 139943412Snewton if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0) 140043412Snewton return error; 140143412Snewton 140243412Snewton#ifdef DEBUG_SVR4 140343412Snewton if ((error = show_ioc(">", &ioc)) != 0) 140443412Snewton return error; 140543412Snewton#endif /* DEBUG_SVR4 */ 140643412Snewton 140743412Snewton switch (ioc.cmd & 0xff00) { 140843412Snewton case SVR4_SIMOD: 140983366Sjulian if ((error = sockmod(fp, fd, &ioc, td)) != 0) 141043412Snewton return error; 141143412Snewton break; 141243412Snewton 141343412Snewton case SVR4_TIMOD: 141483366Sjulian if ((error = timod(fp, fd, &ioc, td)) != 0) 141543412Snewton return error; 141643412Snewton break; 141743412Snewton 141843412Snewton default: 141943412Snewton DPRINTF(("Unimplemented module %c %ld\n", 142043412Snewton (char) (cmd >> 8), cmd & 0xff)); 142143412Snewton return 0; 142243412Snewton } 142343412Snewton 142443412Snewton#ifdef DEBUG_SVR4 142543412Snewton if ((error = show_ioc("<", &ioc)) != 0) 142643412Snewton return error; 142743412Snewton#endif /* DEBUG_SVR4 */ 142843412Snewton return copyout(&ioc, dat, sizeof(ioc)); 142943412Snewton} 143043412Snewton 143143412Snewtonstatic int 143283366Sjuliani_setsig(fp, td, retval, fd, cmd, dat) 143343412Snewton struct file *fp; 143483366Sjulian struct thread *td; 143543412Snewton register_t *retval; 143643412Snewton int fd; 143743412Snewton u_long cmd; 143843412Snewton caddr_t dat; 143943412Snewton{ 144043412Snewton /* 144143412Snewton * This is the best we can do for now; we cannot generate 144243412Snewton * signals only for specific events so the signal mask gets 144343412Snewton * ignored; we save it just to pass it to a possible I_GETSIG... 144443412Snewton * 144543412Snewton * We alse have to fix the O_ASYNC fcntl bit, so the 144643412Snewton * process will get SIGPOLLs. 144743412Snewton */ 144843412Snewton struct fcntl_args fa; 144943412Snewton int error; 145043412Snewton register_t oflags, flags; 145143412Snewton struct svr4_strm *st = svr4_stream_get(fp); 145243412Snewton 145343412Snewton if (st == NULL) { 145443412Snewton DPRINTF(("i_setsig: bad file descriptor\n")); 145543412Snewton return EINVAL; 145643412Snewton } 145743412Snewton /* get old status flags */ 145843412Snewton SCARG(&fa, fd) = fd; 145943412Snewton SCARG(&fa, cmd) = F_GETFL; 146083366Sjulian if ((error = fcntl(td, &fa)) != 0) 146143412Snewton return error; 146243412Snewton 146383366Sjulian oflags = td->td_retval[0]; 146443412Snewton 146543412Snewton /* update the flags */ 146643412Snewton if (dat != NULL) { 146743412Snewton int mask; 146843412Snewton 146943412Snewton flags = oflags | O_ASYNC; 147043412Snewton if ((error = copyin(dat, &mask, sizeof(mask))) != 0) { 147143412Snewton DPRINTF(("i_setsig: bad eventmask pointer\n")); 147243412Snewton return error; 147343412Snewton } 147443412Snewton if (mask & SVR4_S_ALLMASK) { 147543412Snewton DPRINTF(("i_setsig: bad eventmask data %x\n", mask)); 147643412Snewton return EINVAL; 147743412Snewton } 147843412Snewton st->s_eventmask = mask; 147943412Snewton } 148043412Snewton else { 148143412Snewton flags = oflags & ~O_ASYNC; 148243412Snewton st->s_eventmask = 0; 148343412Snewton } 148443412Snewton 148543412Snewton /* set the new flags, if changed */ 148643412Snewton if (flags != oflags) { 148743412Snewton SCARG(&fa, cmd) = F_SETFL; 148843412Snewton SCARG(&fa, arg) = (long) flags; 148983366Sjulian if ((error = fcntl(td, &fa)) != 0) 149043412Snewton return error; 149183366Sjulian flags = td->td_retval[0]; 149243412Snewton } 149343412Snewton 149443412Snewton /* set up SIGIO receiver if needed */ 149543412Snewton if (dat != NULL) { 149643412Snewton SCARG(&fa, cmd) = F_SETOWN; 149783366Sjulian SCARG(&fa, arg) = (long) td->td_proc->p_pid; 149883366Sjulian return fcntl(td, &fa); 149943412Snewton } 150043412Snewton return 0; 150143412Snewton} 150243412Snewton 150343412Snewtonstatic int 150483366Sjuliani_getsig(fp, td, retval, fd, cmd, dat) 150543412Snewton struct file *fp; 150683366Sjulian struct thread *td; 150743412Snewton register_t *retval; 150843412Snewton int fd; 150943412Snewton u_long cmd; 151043412Snewton caddr_t dat; 151143412Snewton{ 151243412Snewton int error; 151343412Snewton 151443412Snewton if (dat != NULL) { 151543412Snewton struct svr4_strm *st = svr4_stream_get(fp); 151643412Snewton 151743412Snewton if (st == NULL) { 151843412Snewton DPRINTF(("i_getsig: bad file descriptor\n")); 151943412Snewton return EINVAL; 152043412Snewton } 152143412Snewton if ((error = copyout(&st->s_eventmask, dat, 152243412Snewton sizeof(st->s_eventmask))) != 0) { 152343412Snewton DPRINTF(("i_getsig: bad eventmask pointer\n")); 152443412Snewton return error; 152543412Snewton } 152643412Snewton } 152743412Snewton return 0; 152843412Snewton} 152943412Snewton 153043412Snewtonint 153183366Sjuliansvr4_stream_ioctl(fp, td, retval, fd, cmd, dat) 153243412Snewton struct file *fp; 153383366Sjulian struct thread *td; 153443412Snewton register_t *retval; 153543412Snewton int fd; 153643412Snewton u_long cmd; 153743412Snewton caddr_t dat; 153843412Snewton{ 153943412Snewton *retval = 0; 154043412Snewton 154143412Snewton /* 154243412Snewton * All the following stuff assumes "sockmod" is pushed... 154343412Snewton */ 154443412Snewton switch (cmd) { 154543412Snewton case SVR4_I_NREAD: 154643412Snewton DPRINTF(("I_NREAD\n")); 154783366Sjulian return i_nread(fp, td, retval, fd, cmd, dat); 154843412Snewton 154943412Snewton case SVR4_I_PUSH: 155080114Sassar DPRINTF(("I_PUSH %p\n", dat)); 155143412Snewton#if defined(DEBUG_SVR4) 155280114Sassar show_strbuf((struct svr4_strbuf *)dat); 155343412Snewton#endif 155443412Snewton return 0; 155543412Snewton 155643412Snewton case SVR4_I_POP: 155743412Snewton DPRINTF(("I_POP\n")); 155843412Snewton return 0; 155943412Snewton 156043412Snewton case SVR4_I_LOOK: 156143412Snewton DPRINTF(("I_LOOK\n")); 156243412Snewton return 0; 156343412Snewton 156443412Snewton case SVR4_I_FLUSH: 156543412Snewton DPRINTF(("I_FLUSH\n")); 156643412Snewton return 0; 156743412Snewton 156843412Snewton case SVR4_I_SRDOPT: 156943412Snewton DPRINTF(("I_SRDOPT\n")); 157043412Snewton return 0; 157143412Snewton 157243412Snewton case SVR4_I_GRDOPT: 157343412Snewton DPRINTF(("I_GRDOPT\n")); 157443412Snewton return 0; 157543412Snewton 157643412Snewton case SVR4_I_STR: 157743412Snewton DPRINTF(("I_STR\n")); 157883366Sjulian return i_str(fp, td, retval, fd, cmd, dat); 157943412Snewton 158043412Snewton case SVR4_I_SETSIG: 158143412Snewton DPRINTF(("I_SETSIG\n")); 158283366Sjulian return i_setsig(fp, td, retval, fd, cmd, dat); 158343412Snewton 158443412Snewton case SVR4_I_GETSIG: 158543412Snewton DPRINTF(("I_GETSIG\n")); 158683366Sjulian return i_getsig(fp, td, retval, fd, cmd, dat); 158743412Snewton 158843412Snewton case SVR4_I_FIND: 158943412Snewton DPRINTF(("I_FIND\n")); 159043412Snewton /* 159143412Snewton * Here we are not pushing modules really, we just 159243412Snewton * pretend all are present 159343412Snewton */ 159443412Snewton *retval = 0; 159543412Snewton return 0; 159643412Snewton 159743412Snewton case SVR4_I_LINK: 159843412Snewton DPRINTF(("I_LINK\n")); 159943412Snewton return 0; 160043412Snewton 160143412Snewton case SVR4_I_UNLINK: 160243412Snewton DPRINTF(("I_UNLINK\n")); 160343412Snewton return 0; 160443412Snewton 160543412Snewton case SVR4_I_ERECVFD: 160643412Snewton DPRINTF(("I_ERECVFD\n")); 160743412Snewton return 0; 160843412Snewton 160943412Snewton case SVR4_I_PEEK: 161043412Snewton DPRINTF(("I_PEEK\n")); 161143412Snewton return 0; 161243412Snewton 161343412Snewton case SVR4_I_FDINSERT: 161443412Snewton DPRINTF(("I_FDINSERT\n")); 161583366Sjulian return i_fdinsert(fp, td, retval, fd, cmd, dat); 161643412Snewton 161743412Snewton case SVR4_I_SENDFD: 161843412Snewton DPRINTF(("I_SENDFD\n")); 161943412Snewton return 0; 162043412Snewton 162143412Snewton case SVR4_I_RECVFD: 162243412Snewton DPRINTF(("I_RECVFD\n")); 162343412Snewton return 0; 162443412Snewton 162543412Snewton case SVR4_I_SWROPT: 162643412Snewton DPRINTF(("I_SWROPT\n")); 162743412Snewton return 0; 162843412Snewton 162943412Snewton case SVR4_I_GWROPT: 163043412Snewton DPRINTF(("I_GWROPT\n")); 163143412Snewton return 0; 163243412Snewton 163343412Snewton case SVR4_I_LIST: 163443412Snewton DPRINTF(("I_LIST\n")); 163543412Snewton return 0; 163643412Snewton 163743412Snewton case SVR4_I_PLINK: 163843412Snewton DPRINTF(("I_PLINK\n")); 163943412Snewton return 0; 164043412Snewton 164143412Snewton case SVR4_I_PUNLINK: 164243412Snewton DPRINTF(("I_PUNLINK\n")); 164343412Snewton return 0; 164443412Snewton 164543412Snewton case SVR4_I_SETEV: 164643412Snewton DPRINTF(("I_SETEV\n")); 164743412Snewton return 0; 164843412Snewton 164943412Snewton case SVR4_I_GETEV: 165043412Snewton DPRINTF(("I_GETEV\n")); 165143412Snewton return 0; 165243412Snewton 165343412Snewton case SVR4_I_STREV: 165443412Snewton DPRINTF(("I_STREV\n")); 165543412Snewton return 0; 165643412Snewton 165743412Snewton case SVR4_I_UNSTREV: 165843412Snewton DPRINTF(("I_UNSTREV\n")); 165943412Snewton return 0; 166043412Snewton 166143412Snewton case SVR4_I_FLUSHBAND: 166243412Snewton DPRINTF(("I_FLUSHBAND\n")); 166343412Snewton return 0; 166443412Snewton 166543412Snewton case SVR4_I_CKBAND: 166643412Snewton DPRINTF(("I_CKBAND\n")); 166743412Snewton return 0; 166843412Snewton 166943412Snewton case SVR4_I_GETBAND: 167043412Snewton DPRINTF(("I_GETBANK\n")); 167143412Snewton return 0; 167243412Snewton 167343412Snewton case SVR4_I_ATMARK: 167443412Snewton DPRINTF(("I_ATMARK\n")); 167543412Snewton return 0; 167643412Snewton 167743412Snewton case SVR4_I_SETCLTIME: 167843412Snewton DPRINTF(("I_SETCLTIME\n")); 167943412Snewton return 0; 168043412Snewton 168143412Snewton case SVR4_I_GETCLTIME: 168243412Snewton DPRINTF(("I_GETCLTIME\n")); 168343412Snewton return 0; 168443412Snewton 168543412Snewton case SVR4_I_CANPUT: 168643412Snewton DPRINTF(("I_CANPUT\n")); 168743412Snewton return 0; 168843412Snewton 168943412Snewton case SVR4__I_BIND_RSVD: 169043412Snewton DPRINTF(("_I_BIND_RSVD\n")); 169183366Sjulian return _i_bind_rsvd(fp, td, retval, fd, cmd, dat); 169243412Snewton 169343412Snewton case SVR4__I_RELE_RSVD: 169443412Snewton DPRINTF(("_I_RELE_RSVD\n")); 169583366Sjulian return _i_rele_rsvd(fp, td, retval, fd, cmd, dat); 169643412Snewton 169743412Snewton default: 169843412Snewton DPRINTF(("unimpl cmd = %lx\n", cmd)); 169943412Snewton break; 170043412Snewton } 170143412Snewton 170243412Snewton return 0; 170343412Snewton} 170443412Snewton 170543412Snewton 170643412Snewton 170743412Snewtonint 170883366Sjuliansvr4_sys_putmsg(td, uap) 170983366Sjulian register struct thread *td; 171043412Snewton struct svr4_sys_putmsg_args *uap; 171143412Snewton{ 171289306Salfred struct file *fp; 171389306Salfred int error; 171489306Salfred 171589319Salfred if ((error = fget(td, uap->fd, &fp)) != 0) { 171689306Salfred#ifdef DEBUG_SVR4 171789306Salfred uprintf("putmsg: bad fp\n"); 171889306Salfred#endif 171989306Salfred return EBADF; 172089306Salfred } 172189306Salfred error = svr4_do_putmsg(td, uap, fp); 172289306Salfred fdrop(fp, td); 172389306Salfred return (error); 172489306Salfred} 172589306Salfred 172689306Salfredstatic int 172789306Salfredsvr4_do_putmsg(td, uap, fp) 172889306Salfred struct thread *td; 172989306Salfred struct svr4_sys_putmsg_args *uap; 173043412Snewton struct file *fp; 173189306Salfred{ 173243412Snewton struct svr4_strbuf dat, ctl; 173343412Snewton struct svr4_strmcmd sc; 173443412Snewton struct sockaddr_in sain; 173543412Snewton struct sockaddr_un saun; 173643412Snewton void *skp, *sup; 173743412Snewton int sasize, *retval; 173843412Snewton struct svr4_strm *st; 173943412Snewton int error; 174043412Snewton caddr_t sg; 174143412Snewton 174283366Sjulian retval = td->td_retval; 174354493Snewton 174443412Snewton#ifdef DEBUG_SVR4 174543412Snewton show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl), 174643412Snewton SCARG(uap, dat), SCARG(uap, flags)); 174743412Snewton#endif /* DEBUG_SVR4 */ 174843412Snewton 174989306Salfred FILE_LOCK_ASSERT(fp, MA_NOTOWNED); 175043412Snewton 175143412Snewton if (SCARG(uap, ctl) != NULL) { 175243412Snewton if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) { 175343412Snewton#ifdef DEBUG_SVR4 175443412Snewton uprintf("putmsg: copyin(): %d\n", error); 175543412Snewton#endif 175643412Snewton return error; 175743412Snewton } 175843412Snewton } 175943412Snewton else 176043412Snewton ctl.len = -1; 176143412Snewton 176243412Snewton if (SCARG(uap, dat) != NULL) { 176343412Snewton if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) { 176443412Snewton#ifdef DEBUG_SVR4 176543412Snewton uprintf("putmsg: copyin(): %d (2)\n", error); 176643412Snewton#endif 176743412Snewton return error; 176843412Snewton } 176943412Snewton } 177043412Snewton else 177143412Snewton dat.len = -1; 177243412Snewton 177343412Snewton /* 177443412Snewton * Only for sockets for now. 177543412Snewton */ 177643412Snewton if ((st = svr4_stream_get(fp)) == NULL) { 177743412Snewton DPRINTF(("putmsg: bad file type\n")); 177843412Snewton return EINVAL; 177943412Snewton } 178043412Snewton 178143412Snewton if (ctl.len > sizeof(sc)) { 178243412Snewton DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len, 178343412Snewton sizeof(struct svr4_strmcmd))); 178443412Snewton return EINVAL; 178543412Snewton } 178643412Snewton 178743412Snewton if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 178843412Snewton return error; 178943412Snewton 179043412Snewton switch (st->s_family) { 179143412Snewton case AF_INET: 179243412Snewton if (sc.len != sizeof(sain)) { 179343412Snewton if (sc.cmd == SVR4_TI_DATA_REQUEST) { 179443412Snewton struct write_args wa; 179543412Snewton 179643412Snewton /* Solaris seems to use sc.cmd = 3 to 179743412Snewton * send "expedited" data. telnet uses 179843412Snewton * this for options processing, sending EOF, 179943412Snewton * etc. I'm sure other things use it too. 180043412Snewton * I don't have any documentation 180143412Snewton * on it, so I'm making a guess that this 180243412Snewton * is how it works. newton@atdot.dotat.org XXX 180343412Snewton */ 180451844Speter DPRINTF(("sending expedited data ??\n")); 180543412Snewton SCARG(&wa, fd) = SCARG(uap, fd); 180643412Snewton SCARG(&wa, buf) = dat.buf; 180743412Snewton SCARG(&wa, nbyte) = dat.len; 180883366Sjulian return write(td, &wa); 180943412Snewton } 181043412Snewton DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len)); 181143412Snewton return EINVAL; 181243412Snewton } 181343412Snewton netaddr_to_sockaddr_in(&sain, &sc); 181443412Snewton skp = &sain; 181543412Snewton sasize = sizeof(sain); 181643412Snewton error = sain.sin_family != st->s_family; 181743412Snewton break; 181843412Snewton 181943412Snewton case AF_LOCAL: 182043412Snewton if (ctl.len == 8) { 182143412Snewton /* We are doing an accept; succeed */ 182243412Snewton DPRINTF(("putmsg: Do nothing\n")); 182343412Snewton *retval = 0; 182443412Snewton return 0; 182543412Snewton } 182643412Snewton else { 182743412Snewton /* Maybe we've been given a device/inode pair */ 182849267Snewton udev_t *dev = SVR4_ADDROF(&sc); 182943412Snewton ino_t *ino = (ino_t *) &dev[1]; 183083366Sjulian skp = svr4_find_socket(td, fp, *dev, *ino); 183143412Snewton if (skp == NULL) { 183243412Snewton skp = &saun; 183343412Snewton /* I guess we have it by name */ 183443412Snewton netaddr_to_sockaddr_un(skp, &sc); 183543412Snewton } 183643412Snewton sasize = sizeof(saun); 183743412Snewton } 183843412Snewton break; 183943412Snewton 184043412Snewton default: 184143412Snewton DPRINTF(("putmsg: Unsupported address family %d\n", 184243412Snewton st->s_family)); 184343412Snewton return ENOSYS; 184443412Snewton } 184543412Snewton 184643412Snewton sg = stackgap_init(); 184743412Snewton sup = stackgap_alloc(&sg, sasize); 184843412Snewton 184943412Snewton if ((error = copyout(skp, sup, sasize)) != 0) 185043412Snewton return error; 185143412Snewton 185243412Snewton switch (st->s_cmd = sc.cmd) { 185343412Snewton case SVR4_TI_CONNECT_REQUEST: /* connect */ 185443412Snewton { 185543412Snewton struct connect_args co; 185643412Snewton 185743412Snewton SCARG(&co, s) = SCARG(uap, fd); 185843412Snewton SCARG(&co, name) = (void *) sup; 185943412Snewton SCARG(&co, namelen) = (int) sasize; 186043412Snewton 186183366Sjulian return connect(td, &co); 186243412Snewton } 186343412Snewton 186443412Snewton case SVR4_TI_SENDTO_REQUEST: /* sendto */ 186543412Snewton { 186643412Snewton struct msghdr msg; 186743412Snewton struct iovec aiov; 186843412Snewton 186943412Snewton msg.msg_name = (caddr_t) sup; 187043412Snewton msg.msg_namelen = sasize; 187143412Snewton msg.msg_iov = &aiov; 187243412Snewton msg.msg_iovlen = 1; 187343412Snewton msg.msg_control = 0; 187443412Snewton msg.msg_flags = 0; 187543412Snewton aiov.iov_base = dat.buf; 187643412Snewton aiov.iov_len = dat.len; 187743412Snewton#if 0 187843412Snewton error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 187983366Sjulian uio, 0, 0, 0, uio->uio_td); 188043412Snewton#endif 188183366Sjulian error = svr4_sendit(td, SCARG(uap, fd), &msg, 188243412Snewton SCARG(uap, flags)); 188343412Snewton DPRINTF(("sendto_request error: %d\n", error)); 188443412Snewton *retval = 0; 188543412Snewton return error; 188643412Snewton } 188743412Snewton 188843412Snewton default: 188943412Snewton DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd)); 189043412Snewton return ENOSYS; 189143412Snewton } 189243412Snewton} 189343412Snewton 189443412Snewtonint 189589308Salfredsvr4_sys_getmsg(td, uap) 189689308Salfred struct thread *td; 189789306Salfred struct svr4_sys_getmsg_args *uap; 189889306Salfred{ 189989306Salfred struct file *fp; 190089306Salfred int error; 190189306Salfred 190289319Salfred if ((error = fget(td, uap->fd, &fp)) != 0) { 190389306Salfred#ifdef DEBUG_SVR4 190489306Salfred uprintf("getmsg: bad fp\n"); 190589306Salfred#endif 190689306Salfred return EBADF; 190789306Salfred } 190889308Salfred error = svr4_do_getmsg(td, uap, fp); 190989306Salfred fdrop(fp, td); 191089306Salfred return (error); 191189306Salfred} 191289306Salfred 191389306Salfredint 191489536Salfredsvr4_do_getmsg(td, uap, fp) 191583366Sjulian register struct thread *td; 191643412Snewton struct svr4_sys_getmsg_args *uap; 191789306Salfred struct file *fp; 191843412Snewton{ 191943412Snewton struct getpeername_args ga; 192043412Snewton struct accept_args aa; 192143412Snewton struct svr4_strbuf dat, ctl; 192243412Snewton struct svr4_strmcmd sc; 192343412Snewton int error, *retval; 192443412Snewton struct msghdr msg; 192543412Snewton struct iovec aiov; 192643412Snewton struct sockaddr_in sain; 192743412Snewton struct sockaddr_un saun; 192843412Snewton void *skp, *sup; 192943412Snewton int sasize; 193043412Snewton struct svr4_strm *st; 193143412Snewton int *flen; 193243412Snewton int fl; 193343412Snewton caddr_t sg; 193443412Snewton 193583366Sjulian retval = td->td_retval; 193654493Snewton 193789306Salfred FILE_LOCK_ASSERT(fp, MA_NOTOWNED); 193843412Snewton 193943412Snewton memset(&sc, 0, sizeof(sc)); 194043412Snewton 194143412Snewton#ifdef DEBUG_SVR4 194243412Snewton show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl), 194343412Snewton SCARG(uap, dat), 0); 194443412Snewton#endif /* DEBUG_SVR4 */ 194543412Snewton 194643412Snewton if (SCARG(uap, ctl) != NULL) { 194743412Snewton if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) 194843412Snewton return error; 194943412Snewton } 195043412Snewton else { 195143412Snewton ctl.len = -1; 195243412Snewton ctl.maxlen = 0; 195343412Snewton } 195443412Snewton 195543412Snewton if (SCARG(uap, dat) != NULL) { 195643412Snewton if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) 195743412Snewton return error; 195843412Snewton } 195943412Snewton else { 196043412Snewton dat.len = -1; 196143412Snewton dat.maxlen = 0; 196243412Snewton } 196343412Snewton 196443412Snewton /* 196543412Snewton * Only for sockets for now. 196643412Snewton */ 196743412Snewton if ((st = svr4_stream_get(fp)) == NULL) { 196843412Snewton DPRINTF(("getmsg: bad file type\n")); 196943412Snewton return EINVAL; 197043412Snewton } 197143412Snewton 197243412Snewton if (ctl.maxlen == -1 || dat.maxlen == -1) { 197343412Snewton DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n")); 197443412Snewton return ENOSYS; 197543412Snewton } 197643412Snewton 197743412Snewton switch (st->s_family) { 197843412Snewton case AF_INET: 197943412Snewton skp = &sain; 198043412Snewton sasize = sizeof(sain); 198143412Snewton break; 198243412Snewton 198343412Snewton case AF_LOCAL: 198443412Snewton skp = &saun; 198543412Snewton sasize = sizeof(saun); 198643412Snewton break; 198743412Snewton 198843412Snewton default: 198943412Snewton DPRINTF(("getmsg: Unsupported address family %d\n", 199043412Snewton st->s_family)); 199143412Snewton return ENOSYS; 199243412Snewton } 199343412Snewton 199443412Snewton sg = stackgap_init(); 199543412Snewton sup = stackgap_alloc(&sg, sasize); 199643412Snewton flen = (int *) stackgap_alloc(&sg, sizeof(*flen)); 199743412Snewton 199843412Snewton fl = sasize; 199943412Snewton if ((error = copyout(&fl, flen, sizeof(fl))) != 0) 200043412Snewton return error; 200143412Snewton 200243412Snewton switch (st->s_cmd) { 200343412Snewton case SVR4_TI_CONNECT_REQUEST: 200443412Snewton DPRINTF(("getmsg: TI_CONNECT_REQUEST\n")); 200543412Snewton /* 200643412Snewton * We do the connect in one step, so the putmsg should 200743412Snewton * have gotten the error. 200843412Snewton */ 200943412Snewton sc.cmd = SVR4_TI_OK_REPLY; 201043412Snewton sc.len = 0; 201143412Snewton 201243412Snewton ctl.len = 8; 201343412Snewton dat.len = -1; 201443412Snewton fl = 1; 201543412Snewton st->s_cmd = sc.cmd; 201643412Snewton break; 201743412Snewton 201843412Snewton case SVR4_TI_OK_REPLY: 201943412Snewton DPRINTF(("getmsg: TI_OK_REPLY\n")); 202043412Snewton /* 202143412Snewton * We are immediately after a connect reply, so we send 202243412Snewton * a connect verification. 202343412Snewton */ 202443412Snewton 202543412Snewton SCARG(&ga, fdes) = SCARG(uap, fd); 202643412Snewton SCARG(&ga, asa) = (void *) sup; 202743412Snewton SCARG(&ga, alen) = flen; 202843412Snewton 202983366Sjulian if ((error = getpeername(td, &ga)) != 0) { 203043412Snewton DPRINTF(("getmsg: getpeername failed %d\n", error)); 203143412Snewton return error; 203243412Snewton } 203343412Snewton 203443412Snewton if ((error = copyin(sup, skp, sasize)) != 0) 203543412Snewton return error; 203643412Snewton 203743412Snewton sc.cmd = SVR4_TI_CONNECT_REPLY; 203843412Snewton sc.pad[0] = 0x4; 203943412Snewton sc.offs = 0x18; 204043412Snewton sc.pad[1] = 0x14; 204143412Snewton sc.pad[2] = 0x04000402; 204243412Snewton 204343412Snewton switch (st->s_family) { 204443412Snewton case AF_INET: 204543412Snewton sc.len = sasize; 204643412Snewton sockaddr_to_netaddr_in(&sc, &sain); 204743412Snewton break; 204843412Snewton 204943412Snewton case AF_LOCAL: 205043412Snewton sc.len = sasize + 4; 205143412Snewton sockaddr_to_netaddr_un(&sc, &saun); 205243412Snewton break; 205343412Snewton 205443412Snewton default: 205543412Snewton return ENOSYS; 205643412Snewton } 205743412Snewton 205843412Snewton ctl.len = 40; 205943412Snewton dat.len = -1; 206043412Snewton fl = 0; 206143412Snewton st->s_cmd = sc.cmd; 206243412Snewton break; 206343412Snewton 206443412Snewton case SVR4_TI__ACCEPT_OK: 206543412Snewton DPRINTF(("getmsg: TI__ACCEPT_OK\n")); 206643412Snewton /* 206743412Snewton * We do the connect in one step, so the putmsg should 206843412Snewton * have gotten the error. 206943412Snewton */ 207043412Snewton sc.cmd = SVR4_TI_OK_REPLY; 207143412Snewton sc.len = 1; 207243412Snewton 207343412Snewton ctl.len = 8; 207443412Snewton dat.len = -1; 207543412Snewton fl = 1; 207643412Snewton st->s_cmd = SVR4_TI__ACCEPT_WAIT; 207743412Snewton break; 207843412Snewton 207943412Snewton case SVR4_TI__ACCEPT_WAIT: 208043412Snewton DPRINTF(("getmsg: TI__ACCEPT_WAIT\n")); 208143412Snewton /* 208243412Snewton * We are after a listen, so we try to accept... 208343412Snewton */ 208443412Snewton SCARG(&aa, s) = SCARG(uap, fd); 208543412Snewton SCARG(&aa, name) = (void *) sup; 208643412Snewton SCARG(&aa, anamelen) = flen; 208743412Snewton 208883366Sjulian if ((error = accept(td, &aa)) != 0) { 208943412Snewton DPRINTF(("getmsg: accept failed %d\n", error)); 209043412Snewton return error; 209143412Snewton } 209243412Snewton 209343412Snewton st->s_afd = *retval; 209443412Snewton 209543412Snewton DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd)); 209643412Snewton 209743412Snewton if ((error = copyin(sup, skp, sasize)) != 0) 209843412Snewton return error; 209943412Snewton 210043412Snewton sc.cmd = SVR4_TI_ACCEPT_REPLY; 210143412Snewton sc.offs = 0x18; 210243412Snewton sc.pad[0] = 0x0; 210343412Snewton 210443412Snewton switch (st->s_family) { 210543412Snewton case AF_INET: 210643412Snewton sc.pad[1] = 0x28; 210743412Snewton sockaddr_to_netaddr_in(&sc, &sain); 210843412Snewton ctl.len = 40; 210943412Snewton sc.len = sasize; 211043412Snewton break; 211143412Snewton 211243412Snewton case AF_LOCAL: 211343412Snewton sc.pad[1] = 0x00010000; 211443412Snewton sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */ 211543412Snewton sc.pad[3] = 0x00010000; 211643412Snewton ctl.len = 134; 211743412Snewton sc.len = sasize + 4; 211843412Snewton break; 211943412Snewton 212043412Snewton default: 212143412Snewton return ENOSYS; 212243412Snewton } 212343412Snewton 212443412Snewton dat.len = -1; 212543412Snewton fl = 0; 212643412Snewton st->s_cmd = SVR4_TI__ACCEPT_OK; 212743412Snewton break; 212843412Snewton 212943412Snewton case SVR4_TI_SENDTO_REQUEST: 213043412Snewton DPRINTF(("getmsg: TI_SENDTO_REQUEST\n")); 213143412Snewton if (ctl.maxlen > 36 && ctl.len < 36) 213243412Snewton ctl.len = 36; 213343412Snewton 213443412Snewton if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 213543412Snewton return error; 213643412Snewton 213743412Snewton switch (st->s_family) { 213843412Snewton case AF_INET: 213943412Snewton sockaddr_to_netaddr_in(&sc, &sain); 214043412Snewton break; 214143412Snewton 214243412Snewton case AF_LOCAL: 214343412Snewton sockaddr_to_netaddr_un(&sc, &saun); 214443412Snewton break; 214543412Snewton 214643412Snewton default: 214743412Snewton return ENOSYS; 214843412Snewton } 214943412Snewton 215043412Snewton msg.msg_name = (caddr_t) sup; 215143412Snewton msg.msg_namelen = sasize; 215243412Snewton msg.msg_iov = &aiov; 215343412Snewton msg.msg_iovlen = 1; 215443412Snewton msg.msg_control = 0; 215543412Snewton aiov.iov_base = dat.buf; 215643412Snewton aiov.iov_len = dat.maxlen; 215743412Snewton msg.msg_flags = 0; 215843412Snewton 215983366Sjulian error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen); 216043412Snewton 216143412Snewton if (error) { 216243412Snewton DPRINTF(("getmsg: recvit failed %d\n", error)); 216343412Snewton return error; 216443412Snewton } 216543412Snewton 216643412Snewton if ((error = copyin(msg.msg_name, skp, sasize)) != 0) 216743412Snewton return error; 216843412Snewton 216943412Snewton sc.cmd = SVR4_TI_RECVFROM_IND; 217043412Snewton 217143412Snewton switch (st->s_family) { 217243412Snewton case AF_INET: 217343412Snewton sc.len = sasize; 217443412Snewton sockaddr_to_netaddr_in(&sc, &sain); 217543412Snewton break; 217643412Snewton 217743412Snewton case AF_LOCAL: 217843412Snewton sc.len = sasize + 4; 217943412Snewton sockaddr_to_netaddr_un(&sc, &saun); 218043412Snewton break; 218143412Snewton 218243412Snewton default: 218343412Snewton return ENOSYS; 218443412Snewton } 218543412Snewton 218643412Snewton dat.len = *retval; 218743412Snewton fl = 0; 218843412Snewton st->s_cmd = sc.cmd; 218943412Snewton break; 219043412Snewton 219143412Snewton default: 219243412Snewton st->s_cmd = sc.cmd; 219343412Snewton if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) { 219443412Snewton struct read_args ra; 219543412Snewton 219672082Sasmodai /* More weirdness: Again, I can't find documentation 219743412Snewton * to back this up, but when a process does a generic 219843412Snewton * "getmsg()" call it seems that the command field is 219943412Snewton * zero and the length of the data area is zero. I 220043412Snewton * think processes expect getmsg() to fill in dat.len 220143412Snewton * after reading at most dat.maxlen octets from the 220243412Snewton * stream. Since we're using sockets I can let 220343412Snewton * read() look after it and frob return values 220443412Snewton * appropriately (or inappropriately :-) 220543412Snewton * -- newton@atdot.dotat.org XXX 220643412Snewton */ 220743412Snewton SCARG(&ra, fd) = SCARG(uap, fd); 220843412Snewton SCARG(&ra, buf) = dat.buf; 220943412Snewton SCARG(&ra, nbyte) = dat.maxlen; 221083366Sjulian if ((error = read(td, &ra)) != 0) { 221143412Snewton return error; 221243412Snewton } 221343412Snewton dat.len = *retval; 221443412Snewton *retval = 0; 221543412Snewton st->s_cmd = SVR4_TI_SENDTO_REQUEST; 221643412Snewton break; 221743412Snewton } 221843412Snewton DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd)); 221943412Snewton return EINVAL; 222043412Snewton } 222143412Snewton 222243412Snewton if (SCARG(uap, ctl)) { 222343412Snewton if (ctl.len != -1) 222443412Snewton if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0) 222543412Snewton return error; 222643412Snewton 222743412Snewton if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0) 222843412Snewton return error; 222943412Snewton } 223043412Snewton 223143412Snewton if (SCARG(uap, dat)) { 223243412Snewton if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0) 223343412Snewton return error; 223443412Snewton } 223543412Snewton 223643412Snewton if (SCARG(uap, flags)) { /* XXX: Need translation */ 223743412Snewton if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0) 223843412Snewton return error; 223943412Snewton } 224043412Snewton 224143412Snewton *retval = 0; 224243412Snewton 224343412Snewton#ifdef DEBUG_SVR4 224443412Snewton show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl), 224543412Snewton SCARG(uap, dat), fl); 224643412Snewton#endif /* DEBUG_SVR4 */ 224743412Snewton return error; 224843412Snewton} 224943412Snewton 225083366Sjulianint svr4_sys_send(td, uap) 225183366Sjulian struct thread *td; 225243412Snewton struct svr4_sys_send_args *uap; 225343412Snewton{ 225443412Snewton struct osend_args osa; 225543412Snewton SCARG(&osa, s) = SCARG(uap, s); 225643412Snewton SCARG(&osa, buf) = SCARG(uap, buf); 225743412Snewton SCARG(&osa, len) = SCARG(uap, len); 225843412Snewton SCARG(&osa, flags) = SCARG(uap, flags); 225983366Sjulian return osend(td, &osa); 226043412Snewton} 226143412Snewton 226283366Sjulianint svr4_sys_recv(td, uap) 226383366Sjulian struct thread *td; 226443412Snewton struct svr4_sys_recv_args *uap; 226543412Snewton{ 226643412Snewton struct orecv_args ora; 226743412Snewton SCARG(&ora, s) = SCARG(uap, s); 226843412Snewton SCARG(&ora, buf) = SCARG(uap, buf); 226943412Snewton SCARG(&ora, len) = SCARG(uap, len); 227043412Snewton SCARG(&ora, flags) = SCARG(uap, flags); 227183366Sjulian return orecv(td, &ora); 227243412Snewton} 227343412Snewton 227443412Snewton/* 227543412Snewton * XXX This isn't necessary, but it's handy for inserting debug code into 227643412Snewton * sendto(). Let's leave it here for now... 227743412Snewton */ 227843412Snewtonint 227983366Sjuliansvr4_sys_sendto(td, uap) 228083366Sjulian struct thread *td; 228143412Snewton struct svr4_sys_sendto_args *uap; 228243412Snewton{ 228343412Snewton struct sendto_args sa; 228443412Snewton 228543412Snewton SCARG(&sa, s) = SCARG(uap, s); 228643412Snewton SCARG(&sa, buf) = SCARG(uap, buf); 228743412Snewton SCARG(&sa, len) = SCARG(uap, len); 228843412Snewton SCARG(&sa, flags) = SCARG(uap, flags); 228980114Sassar SCARG(&sa, to) = (caddr_t)SCARG(uap, to); 229043412Snewton SCARG(&sa, tolen) = SCARG(uap, tolen); 229143412Snewton 229243412Snewton DPRINTF(("calling sendto()\n")); 229383366Sjulian return sendto(td, &sa); 229443412Snewton} 229543412Snewton 2296