svr4_stream.c revision 50477
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 50477 1999-08-28 01:08:13Z peter $ 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/kernel.h> 4443412Snewton#include <sys/systm.h> 4543412Snewton#include <sys/buf.h> 4643412Snewton#include <sys/malloc.h> 4743412Snewton#include <sys/tty.h> 4843412Snewton#include <sys/file.h> 4943412Snewton#include <sys/filedesc.h> 5043412Snewton#include <sys/unistd.h> 5143412Snewton#include <sys/fcntl.h> 5243412Snewton#include <sys/filio.h> 5343412Snewton#include <sys/select.h> 5443412Snewton#include <sys/socket.h> 5543412Snewton#include <sys/socketvar.h> 5643412Snewton#include <sys/un.h> 5743412Snewton#include <net/if.h> 5843412Snewton#include <netinet/in.h> 5943412Snewton#include <sys/mount.h> 6043412Snewton#include <sys/mbuf.h> 6143412Snewton#include <sys/protosw.h> 6243412Snewton#include <sys/signal.h> 6343412Snewton#include <sys/signalvar.h> 6443412Snewton#include <sys/uio.h> 6543412Snewton#include <sys/ktrace.h> 6643412Snewton#include <sys/proc.h> 6743412Snewton#include <sys/vnode.h> 6843412Snewton#include <sys/device.h> 6943412Snewton#include <sys/stat.h> 7043412Snewton 7143412Snewton#include <sys/sysproto.h> 7243412Snewton 7343412Snewton#include <svr4/svr4.h> 7443412Snewton#include <svr4/svr4_types.h> 7543412Snewton#include <svr4/svr4_util.h> 7643412Snewton#include <svr4/svr4_signal.h> 7743412Snewton#include <svr4/svr4_proto.h> 7843412Snewton#include <svr4/svr4_stropts.h> 7943412Snewton#include <svr4/svr4_timod.h> 8043412Snewton#include <svr4/svr4_sockmod.h> 8143412Snewton#include <svr4/svr4_ioctl.h> 8243412Snewton#include <svr4/svr4_socket.h> 8343412Snewton 8443412Snewton/* Utils */ 8543412Snewtonstatic int clean_pipe __P((struct proc *, const char *)); 8643412Snewtonstatic void getparm __P((struct file *, struct svr4_si_sockparms *)); 8743412Snewton 8843412Snewton/* Address Conversions */ 8943412Snewtonstatic void sockaddr_to_netaddr_in __P((struct svr4_strmcmd *, 9043412Snewton const struct sockaddr_in *)); 9143412Snewtonstatic void sockaddr_to_netaddr_un __P((struct svr4_strmcmd *, 9243412Snewton const struct sockaddr_un *)); 9343412Snewtonstatic void netaddr_to_sockaddr_in __P((struct sockaddr_in *, 9443412Snewton const struct svr4_strmcmd *)); 9543412Snewtonstatic void netaddr_to_sockaddr_un __P((struct sockaddr_un *, 9643412Snewton const struct svr4_strmcmd *)); 9743412Snewton 9843412Snewton/* stream ioctls */ 9943412Snewtonstatic int i_nread __P((struct file *, struct proc *, register_t *, int, 10043412Snewton u_long, caddr_t)); 10143412Snewtonstatic int i_fdinsert __P((struct file *, struct proc *, register_t *, int, 10243412Snewton u_long, caddr_t)); 10343412Snewtonstatic int i_str __P((struct file *, struct proc *, register_t *, int, 10443412Snewton u_long, caddr_t)); 10543412Snewtonstatic int i_setsig __P((struct file *, struct proc *, register_t *, int, 10643412Snewton u_long, caddr_t)); 10743412Snewtonstatic int i_getsig __P((struct file *, struct proc *, register_t *, int, 10843412Snewton u_long, caddr_t)); 10943412Snewtonstatic int _i_bind_rsvd __P((struct file *, struct proc *, register_t *, int, 11043412Snewton u_long, caddr_t)); 11143412Snewtonstatic int _i_rele_rsvd __P((struct file *, struct proc *, register_t *, int, 11243412Snewton u_long, caddr_t)); 11343412Snewton 11443412Snewton/* i_str sockmod calls */ 11543412Snewtonstatic int sockmod __P((struct file *, int, struct svr4_strioctl *, 11643412Snewton struct proc *)); 11743412Snewtonstatic int si_listen __P((struct file *, int, struct svr4_strioctl *, 11843412Snewton struct proc *)); 11943412Snewtonstatic int si_ogetudata __P((struct file *, int, struct svr4_strioctl *, 12043412Snewton struct proc *)); 12143412Snewtonstatic int si_sockparams __P((struct file *, int, struct svr4_strioctl *, 12243412Snewton struct proc *)); 12343412Snewtonstatic int si_shutdown __P((struct file *, int, struct svr4_strioctl *, 12443412Snewton struct proc *)); 12543412Snewtonstatic int si_getudata __P((struct file *, int, struct svr4_strioctl *, 12643412Snewton struct proc *)); 12743412Snewton 12843412Snewton/* i_str timod calls */ 12943412Snewtonstatic int timod __P((struct file *, int, struct svr4_strioctl *, 13043412Snewton struct proc *)); 13143412Snewtonstatic int ti_getinfo __P((struct file *, int, struct svr4_strioctl *, 13243412Snewton struct proc *)); 13343412Snewtonstatic int ti_bind __P((struct file *, int, struct svr4_strioctl *, 13443412Snewton struct proc *)); 13543412Snewton 13643412Snewton/* infrastructure */ 13743412Snewtonstatic int svr4_sendit __P((struct proc *p, int s, struct msghdr *mp, 13843412Snewton int flags)); 13943412Snewton 14043412Snewtonstatic int svr4_recvit __P((struct proc *p, int s, struct msghdr *mp, 14143412Snewton caddr_t namelenp)); 14243412Snewton 14343412Snewton/* <sigh> Ok, so we shouldn't use sendit() in uipc_syscalls.c because 14443412Snewton * it isn't part of a "public" interface; We're supposed to use 14543412Snewton * pru_sosend instead. Same goes for recvit()/pru_soreceive() for 14643412Snewton * that matter. Solution: Suck sendit()/recvit() into here where we 14743412Snewton * can do what we like. 14843412Snewton * 14943412Snewton * I hate code duplication. 15043412Snewton * 15143412Snewton * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though. 15243412Snewton */ 15343412Snewtonstatic int 15443412Snewtonsvr4_sendit(p, s, mp, flags) 15543412Snewton register struct proc *p; 15643412Snewton int s; 15743412Snewton register struct msghdr *mp; 15843412Snewton int flags; 15943412Snewton{ 16043412Snewton struct file *fp; 16143412Snewton struct uio auio; 16243412Snewton register struct iovec *iov; 16343412Snewton register int i; 16443412Snewton struct mbuf *control; 16543412Snewton struct sockaddr *to; 16643412Snewton int len, error; 16743412Snewton struct socket *so; 16843412Snewton#ifdef KTRACE 16943412Snewton struct iovec *ktriov = NULL; 17043412Snewton#endif 17143412Snewton 17243412Snewton error = getsock(p->p_fd, s, &fp); 17343412Snewton if (error) 17443412Snewton return (error); 17543412Snewton auio.uio_iov = mp->msg_iov; 17643412Snewton auio.uio_iovcnt = mp->msg_iovlen; 17743412Snewton auio.uio_segflg = UIO_USERSPACE; 17843412Snewton auio.uio_rw = UIO_WRITE; 17943412Snewton auio.uio_procp = p; 18043412Snewton auio.uio_offset = 0; /* XXX */ 18143412Snewton auio.uio_resid = 0; 18243412Snewton iov = mp->msg_iov; 18343412Snewton for (i = 0; i < mp->msg_iovlen; i++, iov++) { 18443412Snewton if ((auio.uio_resid += iov->iov_len) < 0) 18543412Snewton return (EINVAL); 18643412Snewton } 18743412Snewton if (mp->msg_name) { 18843412Snewton error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); 18943412Snewton if (error) 19043412Snewton return (error); 19143412Snewton } else 19243412Snewton to = 0; 19343412Snewton if (mp->msg_control) { 19443412Snewton if (mp->msg_controllen < sizeof(struct cmsghdr)) { 19543412Snewton error = EINVAL; 19643412Snewton goto bad; 19743412Snewton } 19843412Snewton error = sockargs(&control, mp->msg_control, 19943412Snewton mp->msg_controllen, MT_CONTROL); 20043412Snewton if (error) 20143412Snewton goto bad; 20243412Snewton } else 20343412Snewton control = 0; 20443412Snewton#ifdef KTRACE 20543412Snewton if (KTRPOINT(p, KTR_GENIO)) { 20643412Snewton int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 20743412Snewton 20843412Snewton MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 20943412Snewton bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 21043412Snewton } 21143412Snewton#endif 21243412Snewton len = auio.uio_resid; 21343412Snewton so = (struct socket *)fp->f_data; 21443412Snewton error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control, 21543412Snewton flags, p); 21643412Snewton if (error) { 21743412Snewton if (auio.uio_resid != len && (error == ERESTART || 21843412Snewton error == EINTR || error == EWOULDBLOCK)) 21943412Snewton error = 0; 22043412Snewton if (error == EPIPE) 22143412Snewton psignal(p, SIGPIPE); 22243412Snewton } 22343412Snewton if (error == 0) 22443412Snewton p->p_retval[0] = len - auio.uio_resid; 22543412Snewton#ifdef KTRACE 22643412Snewton if (ktriov != NULL) { 22743412Snewton if (error == 0) 22843412Snewton ktrgenio(p->p_tracep, s, UIO_WRITE, 22943412Snewton ktriov, p->p_retval[0], error); 23043412Snewton FREE(ktriov, M_TEMP); 23143412Snewton } 23243412Snewton#endif 23343412Snewtonbad: 23443412Snewton if (to) 23543412Snewton FREE(to, M_SONAME); 23643412Snewton return (error); 23743412Snewton} 23843412Snewton 23943412Snewtonstatic int 24043412Snewtonsvr4_recvit(p, s, mp, namelenp) 24143412Snewton register struct proc *p; 24243412Snewton int s; 24343412Snewton register struct msghdr *mp; 24443412Snewton caddr_t namelenp; 24543412Snewton{ 24643412Snewton struct file *fp; 24743412Snewton struct uio auio; 24843412Snewton register struct iovec *iov; 24943412Snewton register int i; 25043412Snewton int len, error; 25143412Snewton struct mbuf *m, *control = 0; 25243412Snewton caddr_t ctlbuf; 25343412Snewton struct socket *so; 25443412Snewton struct sockaddr *fromsa = 0; 25543412Snewton#ifdef KTRACE 25643412Snewton struct iovec *ktriov = NULL; 25743412Snewton#endif 25843412Snewton 25943412Snewton error = getsock(p->p_fd, s, &fp); 26043412Snewton if (error) 26143412Snewton return (error); 26243412Snewton auio.uio_iov = mp->msg_iov; 26343412Snewton auio.uio_iovcnt = mp->msg_iovlen; 26443412Snewton auio.uio_segflg = UIO_USERSPACE; 26543412Snewton auio.uio_rw = UIO_READ; 26643412Snewton auio.uio_procp = p; 26743412Snewton auio.uio_offset = 0; /* XXX */ 26843412Snewton auio.uio_resid = 0; 26943412Snewton iov = mp->msg_iov; 27043412Snewton for (i = 0; i < mp->msg_iovlen; i++, iov++) { 27143412Snewton if ((auio.uio_resid += iov->iov_len) < 0) 27243412Snewton return (EINVAL); 27343412Snewton } 27443412Snewton#ifdef KTRACE 27543412Snewton if (KTRPOINT(p, KTR_GENIO)) { 27643412Snewton int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 27743412Snewton 27843412Snewton MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 27943412Snewton bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 28043412Snewton } 28143412Snewton#endif 28243412Snewton len = auio.uio_resid; 28343412Snewton so = (struct socket *)fp->f_data; 28443412Snewton error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, 28543412Snewton (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 28643412Snewton &mp->msg_flags); 28743412Snewton if (error) { 28843412Snewton if (auio.uio_resid != len && (error == ERESTART || 28943412Snewton error == EINTR || error == EWOULDBLOCK)) 29043412Snewton error = 0; 29143412Snewton } 29243412Snewton#ifdef KTRACE 29343412Snewton if (ktriov != NULL) { 29443412Snewton if (error == 0) 29543412Snewton ktrgenio(p->p_tracep, s, UIO_READ, 29643412Snewton ktriov, len - auio.uio_resid, error); 29743412Snewton FREE(ktriov, M_TEMP); 29843412Snewton } 29943412Snewton#endif 30043412Snewton if (error) 30143412Snewton goto out; 30243412Snewton p->p_retval[0] = len - auio.uio_resid; 30343412Snewton if (mp->msg_name) { 30443412Snewton len = mp->msg_namelen; 30543412Snewton if (len <= 0 || fromsa == 0) 30643412Snewton len = 0; 30743412Snewton else { 30843412Snewton#ifndef MIN 30943412Snewton#define MIN(a,b) ((a)>(b)?(b):(a)) 31043412Snewton#endif 31143412Snewton /* save sa_len before it is destroyed by MSG_COMPAT */ 31243412Snewton len = MIN(len, fromsa->sa_len); 31343412Snewton error = copyout(fromsa, 31443412Snewton (caddr_t)mp->msg_name, (unsigned)len); 31543412Snewton if (error) 31643412Snewton goto out; 31743412Snewton } 31843412Snewton mp->msg_namelen = len; 31943412Snewton if (namelenp && 32043412Snewton (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 32143412Snewton goto out; 32243412Snewton } 32343412Snewton } 32443412Snewton if (mp->msg_control) { 32543412Snewton len = mp->msg_controllen; 32643412Snewton m = control; 32743412Snewton mp->msg_controllen = 0; 32843412Snewton ctlbuf = (caddr_t) mp->msg_control; 32943412Snewton 33043412Snewton while (m && len > 0) { 33143412Snewton unsigned int tocopy; 33243412Snewton 33343412Snewton if (len >= m->m_len) 33443412Snewton tocopy = m->m_len; 33543412Snewton else { 33643412Snewton mp->msg_flags |= MSG_CTRUNC; 33743412Snewton tocopy = len; 33843412Snewton } 33943412Snewton 34049267Snewton if ((error = copyout((caddr_t)mtod(m, caddr_t), 34149267Snewton ctlbuf, tocopy)) != 0) 34243412Snewton goto out; 34343412Snewton 34443412Snewton ctlbuf += tocopy; 34543412Snewton len -= tocopy; 34643412Snewton m = m->m_next; 34743412Snewton } 34843412Snewton mp->msg_controllen = ctlbuf - mp->msg_control; 34943412Snewton } 35043412Snewtonout: 35143412Snewton if (fromsa) 35243412Snewton FREE(fromsa, M_SONAME); 35343412Snewton if (control) 35443412Snewton m_freem(control); 35543412Snewton return (error); 35643412Snewton} 35743412Snewton 35843412Snewton#ifdef DEBUG_SVR4 35943412Snewtonstatic void bufprint __P((u_char *, size_t)); 36043412Snewtonstatic int show_ioc __P((const char *, struct svr4_strioctl *)); 36143412Snewtonstatic int show_strbuf __P((struct svr4_strbuf *)); 36243412Snewtonstatic void show_msg __P((const char *, int, struct svr4_strbuf *, 36343412Snewton struct svr4_strbuf *, int)); 36443412Snewton 36543412Snewtonstatic void 36643412Snewtonbufprint(buf, len) 36743412Snewton u_char *buf; 36843412Snewton size_t len; 36943412Snewton{ 37043412Snewton size_t i; 37143412Snewton 37243412Snewton uprintf("\n\t"); 37343412Snewton for (i = 0; i < len; i++) { 37443412Snewton uprintf("%x ", buf[i]); 37543412Snewton if (i && (i % 16) == 0) 37643412Snewton uprintf("\n\t"); 37743412Snewton } 37843412Snewton} 37943412Snewton 38043412Snewtonstatic int 38143412Snewtonshow_ioc(str, ioc) 38243412Snewton const char *str; 38343412Snewton struct svr4_strioctl *ioc; 38443412Snewton{ 38543412Snewton u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK); 38643412Snewton int error; 38743412Snewton 38843412Snewton uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ", 38943412Snewton str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf); 39043412Snewton 39143412Snewton if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) { 39243412Snewton free((char *) ptr, M_TEMP); 39343412Snewton return error; 39443412Snewton } 39543412Snewton 39643412Snewton bufprint(ptr, ioc->len); 39743412Snewton 39843412Snewton uprintf("}\n"); 39943412Snewton 40043412Snewton free((char *) ptr, M_TEMP); 40143412Snewton return 0; 40243412Snewton} 40343412Snewton 40443412Snewton 40543412Snewtonstatic int 40643412Snewtonshow_strbuf(str) 40743412Snewton struct svr4_strbuf *str; 40843412Snewton{ 40943412Snewton int error; 41043412Snewton u_char *ptr = NULL; 41143412Snewton int maxlen = str->maxlen; 41243412Snewton int len = str->len; 41343412Snewton 41443412Snewton if (maxlen < 0) 41543412Snewton maxlen = 0; 41643412Snewton 41743412Snewton if (len >= maxlen) 41843412Snewton len = maxlen; 41943412Snewton 42043412Snewton if (len > 0) { 42143412Snewton ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK); 42243412Snewton 42343412Snewton if ((error = copyin(str->buf, ptr, len)) != 0) { 42443412Snewton free((char *) ptr, M_TEMP); 42543412Snewton return error; 42643412Snewton } 42743412Snewton } 42843412Snewton 42943412Snewton uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf); 43043412Snewton 43143412Snewton if (ptr) 43243412Snewton bufprint(ptr, len); 43343412Snewton 43443412Snewton uprintf("]}"); 43543412Snewton 43643412Snewton if (ptr) 43743412Snewton free((char *) ptr, M_TEMP); 43843412Snewton 43943412Snewton return 0; 44043412Snewton} 44143412Snewton 44243412Snewton 44343412Snewtonstatic void 44443412Snewtonshow_msg(str, fd, ctl, dat, flags) 44543412Snewton const char *str; 44643412Snewton int fd; 44743412Snewton struct svr4_strbuf *ctl; 44843412Snewton struct svr4_strbuf *dat; 44943412Snewton int flags; 45043412Snewton{ 45143412Snewton struct svr4_strbuf buf; 45243412Snewton int error; 45343412Snewton 45443412Snewton uprintf("%s(%d", str, fd); 45543412Snewton if (ctl != NULL) { 45643412Snewton if ((error = copyin(ctl, &buf, sizeof(buf))) != 0) 45743412Snewton return; 45843412Snewton show_strbuf(&buf); 45943412Snewton } 46043412Snewton else 46143412Snewton uprintf(", NULL"); 46243412Snewton 46343412Snewton if (dat != NULL) { 46443412Snewton if ((error = copyin(dat, &buf, sizeof(buf))) != 0) 46543412Snewton return; 46643412Snewton show_strbuf(&buf); 46743412Snewton } 46843412Snewton else 46943412Snewton uprintf(", NULL"); 47043412Snewton 47143412Snewton uprintf(", %x);\n", flags); 47243412Snewton} 47343412Snewton 47443412Snewton#endif /* DEBUG_SVR4 */ 47543412Snewton 47643412Snewton/* 47743412Snewton * We are faced with an interesting situation. On svr4 unix sockets 47843412Snewton * are really pipes. But we really have sockets, and we might as 47943412Snewton * well use them. At the point where svr4 calls TI_BIND, it has 48043412Snewton * already created a named pipe for the socket using mknod(2). 48143412Snewton * We need to create a socket with the same name when we bind, 48243412Snewton * so we need to remove the pipe before, otherwise we'll get address 48343412Snewton * already in use. So we *carefully* remove the pipe, to avoid 48443412Snewton * using this as a random file removal tool. We use system calls 48543412Snewton * to avoid code duplication. 48643412Snewton */ 48743412Snewtonstatic int 48843412Snewtonclean_pipe(p, path) 48943412Snewton struct proc *p; 49043412Snewton const char *path; 49143412Snewton{ 49243412Snewton struct lstat_args la; 49343412Snewton struct unlink_args ua; 49443412Snewton struct stat st; 49543412Snewton int error; 49643412Snewton caddr_t sg = stackgap_init(); 49743412Snewton size_t l = strlen(path) + 1; 49843412Snewton void *tpath; 49943412Snewton 50043412Snewton tpath = stackgap_alloc(&sg, l); 50143412Snewton SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat)); 50243412Snewton 50343412Snewton if ((error = copyout(path, tpath, l)) != 0) 50443412Snewton return error; 50543412Snewton 50643412Snewton SCARG(&la, path) = tpath; 50743412Snewton 50843412Snewton if ((error = lstat(p, &la)) != 0) 50943412Snewton return 0; 51043412Snewton 51143412Snewton if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0) 51243412Snewton return 0; 51343412Snewton 51443412Snewton /* 51543412Snewton * Make sure we are dealing with a mode 0 named pipe. 51643412Snewton */ 51743412Snewton if ((st.st_mode & S_IFMT) != S_IFIFO) 51843412Snewton return 0; 51943412Snewton 52043412Snewton if ((st.st_mode & ALLPERMS) != 0) 52143412Snewton return 0; 52243412Snewton 52343412Snewton SCARG(&ua, path) = SCARG(&la, path); 52443412Snewton 52543412Snewton if ((error = unlink(p, &ua)) != 0) { 52643412Snewton DPRINTF(("clean_pipe: unlink failed %d\n", error)); 52743412Snewton return error; 52843412Snewton } 52943412Snewton 53043412Snewton return 0; 53143412Snewton} 53243412Snewton 53343412Snewton 53443412Snewtonstatic void 53543412Snewtonsockaddr_to_netaddr_in(sc, sain) 53643412Snewton struct svr4_strmcmd *sc; 53743412Snewton const struct sockaddr_in *sain; 53843412Snewton{ 53943412Snewton struct svr4_netaddr_in *na; 54043412Snewton na = SVR4_ADDROF(sc); 54143412Snewton 54243412Snewton na->family = sain->sin_family; 54343412Snewton na->port = sain->sin_port; 54443412Snewton na->addr = sain->sin_addr.s_addr; 54543412Snewton DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port, 54643412Snewton na->addr)); 54743412Snewton} 54843412Snewton 54943412Snewton 55043412Snewtonstatic void 55143412Snewtonsockaddr_to_netaddr_un(sc, saun) 55243412Snewton struct svr4_strmcmd *sc; 55343412Snewton const struct sockaddr_un *saun; 55443412Snewton{ 55543412Snewton struct svr4_netaddr_un *na; 55643412Snewton char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 - 55743412Snewton sizeof(*sc); 55843412Snewton const char *src; 55943412Snewton 56043412Snewton na = SVR4_ADDROF(sc); 56143412Snewton na->family = saun->sun_family; 56243412Snewton for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; ) 56343412Snewton if (dst == edst) 56443412Snewton break; 56543412Snewton DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path)); 56643412Snewton} 56743412Snewton 56843412Snewton 56943412Snewtonstatic void 57043412Snewtonnetaddr_to_sockaddr_in(sain, sc) 57143412Snewton struct sockaddr_in *sain; 57243412Snewton const struct svr4_strmcmd *sc; 57343412Snewton{ 57443412Snewton const struct svr4_netaddr_in *na; 57543412Snewton 57643412Snewton 57743412Snewton na = SVR4_C_ADDROF(sc); 57843412Snewton memset(sain, 0, sizeof(*sain)); 57943412Snewton sain->sin_len = sizeof(*sain); 58043412Snewton sain->sin_family = na->family; 58143412Snewton sain->sin_port = na->port; 58243412Snewton sain->sin_addr.s_addr = na->addr; 58343412Snewton DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family, 58443412Snewton sain->sin_port, sain->sin_addr.s_addr)); 58543412Snewton} 58643412Snewton 58743412Snewton 58843412Snewtonstatic void 58943412Snewtonnetaddr_to_sockaddr_un(saun, sc) 59043412Snewton struct sockaddr_un *saun; 59143412Snewton const struct svr4_strmcmd *sc; 59243412Snewton{ 59343412Snewton const struct svr4_netaddr_un *na; 59443412Snewton char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1]; 59543412Snewton const char *src; 59643412Snewton 59743412Snewton na = SVR4_C_ADDROF(sc); 59843412Snewton memset(saun, 0, sizeof(*saun)); 59943412Snewton saun->sun_family = na->family; 60043412Snewton for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; ) 60143412Snewton if (dst == edst) 60243412Snewton break; 60343412Snewton saun->sun_len = dst - saun->sun_path; 60443412Snewton DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family, 60543412Snewton saun->sun_path)); 60643412Snewton} 60743412Snewton 60843412Snewton 60943412Snewtonstatic void 61043412Snewtongetparm(fp, pa) 61143412Snewton struct file *fp; 61243412Snewton struct svr4_si_sockparms *pa; 61343412Snewton{ 61443412Snewton struct svr4_strm *st = svr4_stream_get(fp); 61543412Snewton struct socket *so = (struct socket *) fp->f_data; 61643412Snewton 61743412Snewton if (st == NULL) 61843412Snewton return; 61943412Snewton 62043412Snewton pa->family = st->s_family; 62143412Snewton 62243412Snewton switch (so->so_type) { 62343412Snewton case SOCK_DGRAM: 62443412Snewton pa->type = SVR4_T_CLTS; 62543412Snewton pa->protocol = IPPROTO_UDP; 62643412Snewton DPRINTF(("getparm(dgram)\n")); 62743412Snewton return; 62843412Snewton 62943412Snewton case SOCK_STREAM: 63043412Snewton pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */ 63143412Snewton pa->protocol = IPPROTO_IP; 63243412Snewton DPRINTF(("getparm(stream)\n")); 63343412Snewton return; 63443412Snewton 63543412Snewton case SOCK_RAW: 63643412Snewton pa->type = SVR4_T_CLTS; 63743412Snewton pa->protocol = IPPROTO_RAW; 63843412Snewton DPRINTF(("getparm(raw)\n")); 63943412Snewton return; 64043412Snewton 64143412Snewton default: 64243412Snewton pa->type = 0; 64343412Snewton pa->protocol = 0; 64443412Snewton DPRINTF(("getparm(type %d?)\n", so->so_type)); 64543412Snewton return; 64643412Snewton } 64743412Snewton} 64843412Snewton 64943412Snewton 65043412Snewtonstatic int 65143412Snewtonsi_ogetudata(fp, fd, ioc, p) 65243412Snewton struct file *fp; 65343412Snewton int fd; 65443412Snewton struct svr4_strioctl *ioc; 65543412Snewton struct proc *p; 65643412Snewton{ 65743412Snewton int error; 65843412Snewton struct svr4_si_oudata ud; 65943412Snewton struct svr4_si_sockparms pa; 66043412Snewton 66143412Snewton if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) { 66243412Snewton DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n", 66343412Snewton sizeof(ud), ioc->len)); 66443412Snewton return EINVAL; 66543412Snewton } 66643412Snewton 66743412Snewton if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 66843412Snewton return error; 66943412Snewton 67043412Snewton getparm(fp, &pa); 67143412Snewton 67243412Snewton switch (pa.family) { 67343412Snewton case AF_INET: 67443412Snewton ud.tidusize = 16384; 67543412Snewton ud.addrsize = sizeof(struct svr4_sockaddr_in); 67643412Snewton if (pa.type == SVR4_SOCK_STREAM) 67743412Snewton ud.etsdusize = 1; 67843412Snewton else 67943412Snewton ud.etsdusize = 0; 68043412Snewton break; 68143412Snewton 68243412Snewton case AF_LOCAL: 68343412Snewton ud.tidusize = 65536; 68443412Snewton ud.addrsize = 128; 68543412Snewton ud.etsdusize = 128; 68643412Snewton break; 68743412Snewton 68843412Snewton default: 68943412Snewton DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n", 69043412Snewton pa.family)); 69143412Snewton return ENOSYS; 69243412Snewton } 69343412Snewton 69443412Snewton /* I have no idea what these should be! */ 69543412Snewton ud.optsize = 128; 69643412Snewton ud.tsdusize = 128; 69743412Snewton 69843412Snewton ud.servtype = pa.type; 69943412Snewton 70043412Snewton /* XXX: Fixme */ 70143412Snewton ud.so_state = 0; 70243412Snewton ud.so_options = 0; 70343412Snewton return copyout(&ud, ioc->buf, ioc->len); 70443412Snewton} 70543412Snewton 70643412Snewton 70743412Snewtonstatic int 70843412Snewtonsi_sockparams(fp, fd, ioc, p) 70943412Snewton struct file *fp; 71043412Snewton int fd; 71143412Snewton struct svr4_strioctl *ioc; 71243412Snewton struct proc *p; 71343412Snewton{ 71443412Snewton struct svr4_si_sockparms pa; 71543412Snewton 71643412Snewton getparm(fp, &pa); 71743412Snewton return copyout(&pa, ioc->buf, sizeof(pa)); 71843412Snewton} 71943412Snewton 72043412Snewton 72143412Snewtonstatic int 72243412Snewtonsi_listen(fp, fd, ioc, p) 72343412Snewton struct file *fp; 72443412Snewton int fd; 72543412Snewton struct svr4_strioctl *ioc; 72643412Snewton struct proc *p; 72743412Snewton{ 72843412Snewton int error; 72943412Snewton struct svr4_strm *st = svr4_stream_get(fp); 73043412Snewton struct svr4_strmcmd lst; 73143412Snewton struct listen_args la; 73243412Snewton 73343412Snewton if (st == NULL) 73443412Snewton return EINVAL; 73543412Snewton 73643412Snewton if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0) 73743412Snewton return error; 73843412Snewton 73943412Snewton if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) { 74043412Snewton DPRINTF(("si_listen: bad request %ld\n", lst.cmd)); 74143412Snewton return EINVAL; 74243412Snewton } 74343412Snewton 74443412Snewton /* 74543412Snewton * We are making assumptions again... 74643412Snewton */ 74743412Snewton SCARG(&la, s) = fd; 74843412Snewton DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5)); 74943412Snewton SCARG(&la, backlog) = 5; 75043412Snewton 75143412Snewton if ((error = listen(p, &la)) != 0) { 75243412Snewton DPRINTF(("SI_LISTEN: listen failed %d\n", error)); 75343412Snewton return error; 75443412Snewton } 75543412Snewton 75643412Snewton st->s_cmd = SVR4_TI__ACCEPT_WAIT; 75743412Snewton lst.cmd = SVR4_TI_BIND_REPLY; 75843412Snewton 75943412Snewton switch (st->s_family) { 76043412Snewton case AF_INET: 76143412Snewton /* XXX: Fill the length here */ 76243412Snewton break; 76343412Snewton 76443412Snewton case AF_LOCAL: 76543412Snewton lst.len = 140; 76643412Snewton lst.pad[28] = 0x00000000; /* magic again */ 76743412Snewton lst.pad[29] = 0x00000800; /* magic again */ 76843412Snewton lst.pad[30] = 0x80001400; /* magic again */ 76943412Snewton break; 77043412Snewton 77143412Snewton default: 77243412Snewton DPRINTF(("SI_LISTEN: Unsupported address family %d\n", 77343412Snewton st->s_family)); 77443412Snewton return ENOSYS; 77543412Snewton } 77643412Snewton 77743412Snewton 77843412Snewton if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0) 77943412Snewton return error; 78043412Snewton 78143412Snewton return 0; 78243412Snewton} 78343412Snewton 78443412Snewton 78543412Snewtonstatic int 78643412Snewtonsi_getudata(fp, fd, ioc, p) 78743412Snewton struct file *fp; 78843412Snewton int fd; 78943412Snewton struct svr4_strioctl *ioc; 79043412Snewton struct proc *p; 79143412Snewton{ 79243412Snewton int error; 79343412Snewton struct svr4_si_udata ud; 79443412Snewton 79543412Snewton if (sizeof(ud) != ioc->len) { 79643412Snewton DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n", 79743412Snewton sizeof(ud), ioc->len)); 79843412Snewton return EINVAL; 79943412Snewton } 80043412Snewton 80143412Snewton if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 80243412Snewton return error; 80343412Snewton 80443412Snewton getparm(fp, &ud.sockparms); 80543412Snewton 80643412Snewton switch (ud.sockparms.family) { 80743412Snewton case AF_INET: 80843412Snewton DPRINTF(("getudata_inet\n")); 80943412Snewton ud.tidusize = 16384; 81043412Snewton ud.tsdusize = 16384; 81143412Snewton ud.addrsize = sizeof(struct svr4_sockaddr_in); 81243412Snewton if (ud.sockparms.type == SVR4_SOCK_STREAM) 81343412Snewton ud.etsdusize = 1; 81443412Snewton else 81543412Snewton ud.etsdusize = 0; 81643412Snewton ud.optsize = 0; 81743412Snewton break; 81843412Snewton 81943412Snewton case AF_LOCAL: 82043412Snewton DPRINTF(("getudata_local\n")); 82143412Snewton ud.tidusize = 65536; 82243412Snewton ud.tsdusize = 128; 82343412Snewton ud.addrsize = 128; 82443412Snewton ud.etsdusize = 128; 82543412Snewton ud.optsize = 128; 82643412Snewton break; 82743412Snewton 82843412Snewton default: 82943412Snewton DPRINTF(("SI_GETUDATA: Unsupported address family %d\n", 83043412Snewton ud.sockparms.family)); 83143412Snewton return ENOSYS; 83243412Snewton } 83343412Snewton 83443412Snewton 83543412Snewton ud.servtype = ud.sockparms.type; 83643412Snewton DPRINTF(("ud.servtype = %d\n", ud.servtype)); 83743412Snewton /* XXX: Fixme */ 83843412Snewton ud.so_state = 0; 83943412Snewton ud.so_options = 0; 84043412Snewton return copyout(&ud, ioc->buf, sizeof(ud)); 84143412Snewton} 84243412Snewton 84343412Snewton 84443412Snewtonstatic int 84543412Snewtonsi_shutdown(fp, fd, ioc, p) 84643412Snewton struct file *fp; 84743412Snewton int fd; 84843412Snewton struct svr4_strioctl *ioc; 84943412Snewton struct proc *p; 85043412Snewton{ 85143412Snewton int error; 85243412Snewton struct shutdown_args ap; 85343412Snewton 85443412Snewton if (ioc->len != sizeof(SCARG(&ap, how))) { 85543412Snewton DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n", 85643412Snewton sizeof(SCARG(&ap, how)), ioc->len)); 85743412Snewton return EINVAL; 85843412Snewton } 85943412Snewton 86043412Snewton if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0) 86143412Snewton return error; 86243412Snewton 86343412Snewton SCARG(&ap, s) = fd; 86443412Snewton 86543412Snewton return shutdown(p, &ap); 86643412Snewton} 86743412Snewton 86843412Snewton 86943412Snewtonstatic int 87043412Snewtonsockmod(fp, fd, ioc, p) 87143412Snewton struct file *fp; 87243412Snewton int fd; 87343412Snewton struct svr4_strioctl *ioc; 87443412Snewton struct proc *p; 87543412Snewton{ 87643412Snewton switch (ioc->cmd) { 87743412Snewton case SVR4_SI_OGETUDATA: 87843412Snewton DPRINTF(("SI_OGETUDATA\n")); 87943412Snewton return si_ogetudata(fp, fd, ioc, p); 88043412Snewton 88143412Snewton case SVR4_SI_SHUTDOWN: 88243412Snewton DPRINTF(("SI_SHUTDOWN\n")); 88343412Snewton return si_shutdown(fp, fd, ioc, p); 88443412Snewton 88543412Snewton case SVR4_SI_LISTEN: 88643412Snewton DPRINTF(("SI_LISTEN\n")); 88743412Snewton return si_listen(fp, fd, ioc, p); 88843412Snewton 88943412Snewton case SVR4_SI_SETMYNAME: 89043412Snewton DPRINTF(("SI_SETMYNAME\n")); 89143412Snewton return 0; 89243412Snewton 89343412Snewton case SVR4_SI_SETPEERNAME: 89443412Snewton DPRINTF(("SI_SETPEERNAME\n")); 89543412Snewton return 0; 89643412Snewton 89743412Snewton case SVR4_SI_GETINTRANSIT: 89843412Snewton DPRINTF(("SI_GETINTRANSIT\n")); 89943412Snewton return 0; 90043412Snewton 90143412Snewton case SVR4_SI_TCL_LINK: 90243412Snewton DPRINTF(("SI_TCL_LINK\n")); 90343412Snewton return 0; 90443412Snewton 90543412Snewton case SVR4_SI_TCL_UNLINK: 90643412Snewton DPRINTF(("SI_TCL_UNLINK\n")); 90743412Snewton return 0; 90843412Snewton 90943412Snewton case SVR4_SI_SOCKPARAMS: 91043412Snewton DPRINTF(("SI_SOCKPARAMS\n")); 91143412Snewton return si_sockparams(fp, fd, ioc, p); 91243412Snewton 91343412Snewton case SVR4_SI_GETUDATA: 91443412Snewton DPRINTF(("SI_GETUDATA\n")); 91543412Snewton return si_getudata(fp, fd, ioc, p); 91643412Snewton 91743412Snewton default: 91843412Snewton DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd)); 91943412Snewton return 0; 92043412Snewton 92143412Snewton } 92243412Snewton} 92343412Snewton 92443412Snewton 92543412Snewtonstatic int 92643412Snewtonti_getinfo(fp, fd, ioc, p) 92743412Snewton struct file *fp; 92843412Snewton int fd; 92943412Snewton struct svr4_strioctl *ioc; 93043412Snewton struct proc *p; 93143412Snewton{ 93243412Snewton int error; 93343412Snewton struct svr4_infocmd info; 93443412Snewton 93543412Snewton memset(&info, 0, sizeof(info)); 93643412Snewton 93743412Snewton if ((error = copyin(ioc->buf, &info, ioc->len)) != 0) 93843412Snewton return error; 93943412Snewton 94043412Snewton if (info.cmd != SVR4_TI_INFO_REQUEST) 94143412Snewton return EINVAL; 94243412Snewton 94343412Snewton info.cmd = SVR4_TI_INFO_REPLY; 94443412Snewton info.tsdu = 0; 94543412Snewton info.etsdu = 1; 94643412Snewton info.cdata = -2; 94743412Snewton info.ddata = -2; 94843412Snewton info.addr = 16; 94943412Snewton info.opt = -1; 95043412Snewton info.tidu = 16384; 95143412Snewton info.serv = 2; 95243412Snewton info.current = 0; 95343412Snewton info.provider = 2; 95443412Snewton 95543412Snewton ioc->len = sizeof(info); 95643412Snewton if ((error = copyout(&info, ioc->buf, ioc->len)) != 0) 95743412Snewton return error; 95843412Snewton 95943412Snewton return 0; 96043412Snewton} 96143412Snewton 96243412Snewton 96343412Snewtonstatic int 96443412Snewtonti_bind(fp, fd, ioc, p) 96543412Snewton struct file *fp; 96643412Snewton int fd; 96743412Snewton struct svr4_strioctl *ioc; 96843412Snewton struct proc *p; 96943412Snewton{ 97043412Snewton int error; 97143412Snewton struct svr4_strm *st = svr4_stream_get(fp); 97243412Snewton struct sockaddr_in sain; 97343412Snewton struct sockaddr_un saun; 97443412Snewton caddr_t sg; 97543412Snewton void *skp, *sup = NULL; 97643412Snewton int sasize; 97743412Snewton struct svr4_strmcmd bnd; 97843412Snewton struct bind_args ba; 97943412Snewton 98043412Snewton if (st == NULL) { 98143412Snewton DPRINTF(("ti_bind: bad file descriptor\n")); 98243412Snewton return EINVAL; 98343412Snewton } 98443412Snewton 98543412Snewton if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0) 98643412Snewton return error; 98743412Snewton 98843412Snewton if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) { 98943412Snewton DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd)); 99043412Snewton return EINVAL; 99143412Snewton } 99243412Snewton 99343412Snewton switch (st->s_family) { 99443412Snewton case AF_INET: 99543412Snewton skp = &sain; 99643412Snewton sasize = sizeof(sain); 99743412Snewton 99843412Snewton if (bnd.offs == 0) 99943412Snewton goto reply; 100043412Snewton 100143412Snewton netaddr_to_sockaddr_in(&sain, &bnd); 100243412Snewton 100343412Snewton DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n", 100443412Snewton sain.sin_family, sain.sin_port, 100543412Snewton sain.sin_addr.s_addr)); 100643412Snewton break; 100743412Snewton 100843412Snewton case AF_LOCAL: 100943412Snewton skp = &saun; 101043412Snewton sasize = sizeof(saun); 101143412Snewton if (bnd.offs == 0) 101243412Snewton goto reply; 101343412Snewton 101443412Snewton netaddr_to_sockaddr_un(&saun, &bnd); 101543412Snewton 101643412Snewton if (saun.sun_path[0] == '\0') 101743412Snewton goto reply; 101843412Snewton 101943412Snewton DPRINTF(("TI_BIND: fam %d, path %s\n", 102043412Snewton saun.sun_family, saun.sun_path)); 102143412Snewton 102243412Snewton if ((error = clean_pipe(p, saun.sun_path)) != 0) 102343412Snewton return error; 102443412Snewton 102543412Snewton bnd.pad[28] = 0x00001000; /* magic again */ 102643412Snewton break; 102743412Snewton 102843412Snewton default: 102943412Snewton DPRINTF(("TI_BIND: Unsupported address family %d\n", 103043412Snewton st->s_family)); 103143412Snewton return ENOSYS; 103243412Snewton } 103343412Snewton 103443412Snewton sg = stackgap_init(); 103543412Snewton sup = stackgap_alloc(&sg, sasize); 103643412Snewton 103743412Snewton if ((error = copyout(skp, sup, sasize)) != 0) 103843412Snewton return error; 103943412Snewton 104043412Snewton SCARG(&ba, s) = fd; 104143412Snewton DPRINTF(("TI_BIND: fileno %d\n", fd)); 104243412Snewton SCARG(&ba, name) = (void *) sup; 104343412Snewton SCARG(&ba, namelen) = sasize; 104443412Snewton 104543412Snewton if ((error = bind(p, &ba)) != 0) { 104643412Snewton DPRINTF(("TI_BIND: bind failed %d\n", error)); 104743412Snewton return error; 104843412Snewton } 104943412Snewton 105043412Snewtonreply: 105143412Snewton if (sup == NULL) { 105243412Snewton memset(&bnd, 0, sizeof(bnd)); 105343412Snewton bnd.len = sasize + 4; 105443412Snewton bnd.offs = 0x10; /* XXX */ 105543412Snewton } 105643412Snewton 105743412Snewton bnd.cmd = SVR4_TI_BIND_REPLY; 105843412Snewton 105943412Snewton if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0) 106043412Snewton return error; 106143412Snewton 106243412Snewton return 0; 106343412Snewton} 106443412Snewton 106543412Snewton 106643412Snewtonstatic int 106743412Snewtontimod(fp, fd, ioc, p) 106843412Snewton struct file *fp; 106943412Snewton int fd; 107043412Snewton struct svr4_strioctl *ioc; 107143412Snewton struct proc *p; 107243412Snewton{ 107343412Snewton switch (ioc->cmd) { 107443412Snewton case SVR4_TI_GETINFO: 107543412Snewton DPRINTF(("TI_GETINFO\n")); 107643412Snewton return ti_getinfo(fp, fd, ioc, p); 107743412Snewton 107843412Snewton case SVR4_TI_OPTMGMT: 107943412Snewton DPRINTF(("TI_OPTMGMT\n")); 108043412Snewton return 0; 108143412Snewton 108243412Snewton case SVR4_TI_BIND: 108343412Snewton DPRINTF(("TI_BIND\n")); 108443412Snewton return ti_bind(fp, fd, ioc, p); 108543412Snewton 108643412Snewton case SVR4_TI_UNBIND: 108743412Snewton DPRINTF(("TI_UNBIND\n")); 108843412Snewton return 0; 108943412Snewton 109043412Snewton default: 109143412Snewton DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd)); 109243412Snewton return 0; 109343412Snewton } 109443412Snewton} 109543412Snewton 109643412Snewton 109743412Snewtonint 109843412Snewtonsvr4_stream_ti_ioctl(fp, p, retval, fd, cmd, dat) 109943412Snewton struct file *fp; 110043412Snewton struct proc *p; 110143412Snewton register_t *retval; 110243412Snewton int fd; 110343412Snewton u_long cmd; 110443412Snewton caddr_t dat; 110543412Snewton{ 110643412Snewton struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat; 110743412Snewton struct svr4_strm *st = svr4_stream_get(fp); 110843412Snewton int error; 110943412Snewton void *skp, *sup; 111043412Snewton struct sockaddr_in sain; 111143412Snewton struct sockaddr_un saun; 111243412Snewton struct svr4_strmcmd sc; 111343412Snewton int sasize; 111443412Snewton caddr_t sg; 111543412Snewton int *lenp; 111643412Snewton 111743412Snewton DPRINTF(("svr4_stream_ti_ioctl\n")); 111843412Snewton 111943412Snewton if (st == NULL) 112043412Snewton return EINVAL; 112143412Snewton 112243412Snewton sc.offs = 0x10; 112343412Snewton 112443412Snewton if ((error = copyin(sub, &skb, sizeof(skb))) != 0) { 112543412Snewton DPRINTF(("ti_ioctl: error copying in strbuf\n")); 112643412Snewton return error; 112743412Snewton } 112843412Snewton 112943412Snewton switch (st->s_family) { 113043412Snewton case AF_INET: 113143412Snewton skp = &sain; 113243412Snewton sasize = sizeof(sain); 113343412Snewton break; 113443412Snewton 113543412Snewton case AF_LOCAL: 113643412Snewton skp = &saun; 113743412Snewton sasize = sizeof(saun); 113843412Snewton break; 113943412Snewton 114043412Snewton default: 114143412Snewton DPRINTF(("ti_ioctl: Unsupported address family %d\n", 114243412Snewton st->s_family)); 114343412Snewton return ENOSYS; 114443412Snewton } 114543412Snewton 114643412Snewton sg = stackgap_init(); 114743412Snewton sup = stackgap_alloc(&sg, sasize); 114843412Snewton lenp = stackgap_alloc(&sg, sizeof(*lenp)); 114943412Snewton 115043412Snewton if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) { 115143412Snewton DPRINTF(("ti_ioctl: error copying out lenp\n")); 115243412Snewton return error; 115343412Snewton } 115443412Snewton 115543412Snewton switch (cmd) { 115643412Snewton case SVR4_TI_GETMYNAME: 115743412Snewton DPRINTF(("TI_GETMYNAME\n")); 115843412Snewton { 115943412Snewton struct getsockname_args ap; 116043412Snewton SCARG(&ap, fdes) = fd; 116143412Snewton SCARG(&ap, asa) = sup; 116243412Snewton SCARG(&ap, alen) = lenp; 116343412Snewton if ((error = getsockname(p, &ap)) != 0) { 116443412Snewton DPRINTF(("ti_ioctl: getsockname error\n")); 116543412Snewton return error; 116643412Snewton } 116743412Snewton } 116843412Snewton break; 116943412Snewton 117043412Snewton case SVR4_TI_GETPEERNAME: 117143412Snewton DPRINTF(("TI_GETPEERNAME\n")); 117243412Snewton { 117343412Snewton struct getpeername_args ap; 117443412Snewton SCARG(&ap, fdes) = fd; 117543412Snewton SCARG(&ap, asa) = sup; 117643412Snewton SCARG(&ap, alen) = lenp; 117743412Snewton if ((error = getpeername(p, &ap)) != 0) { 117843412Snewton DPRINTF(("ti_ioctl: getpeername error\n")); 117943412Snewton return error; 118043412Snewton } 118143412Snewton } 118243412Snewton break; 118343412Snewton 118443412Snewton case SVR4_TI_SETMYNAME: 118543412Snewton DPRINTF(("TI_SETMYNAME\n")); 118643412Snewton return 0; 118743412Snewton 118843412Snewton case SVR4_TI_SETPEERNAME: 118943412Snewton DPRINTF(("TI_SETPEERNAME\n")); 119043412Snewton return 0; 119143412Snewton default: 119243412Snewton DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd)); 119343412Snewton return ENOSYS; 119443412Snewton } 119543412Snewton 119643412Snewton if ((error = copyin(sup, skp, sasize)) != 0) { 119743412Snewton DPRINTF(("ti_ioctl: error copying in socket data\n")); 119843412Snewton return error; 119943412Snewton } 120043412Snewton 120143412Snewton if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) { 120243412Snewton DPRINTF(("ti_ioctl: error copying in socket size\n")); 120343412Snewton return error; 120443412Snewton } 120543412Snewton 120643412Snewton switch (st->s_family) { 120743412Snewton case AF_INET: 120843412Snewton sockaddr_to_netaddr_in(&sc, &sain); 120943412Snewton skb.len = sasize; 121043412Snewton break; 121143412Snewton 121243412Snewton case AF_LOCAL: 121343412Snewton sockaddr_to_netaddr_un(&sc, &saun); 121443412Snewton skb.len = sasize + 4; 121543412Snewton break; 121643412Snewton 121743412Snewton default: 121843412Snewton return ENOSYS; 121943412Snewton } 122043412Snewton 122143412Snewton 122243412Snewton if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) { 122343412Snewton DPRINTF(("ti_ioctl: error copying out socket data\n")); 122443412Snewton return error; 122543412Snewton } 122643412Snewton 122743412Snewton 122843412Snewton if ((error = copyout(&skb, sub, sizeof(skb))) != 0) { 122943412Snewton DPRINTF(("ti_ioctl: error copying out strbuf\n")); 123043412Snewton return error; 123143412Snewton } 123243412Snewton 123343412Snewton return error; 123443412Snewton} 123543412Snewton 123643412Snewton 123743412Snewton 123843412Snewton 123943412Snewtonstatic int 124043412Snewtoni_nread(fp, p, retval, fd, cmd, dat) 124143412Snewton struct file *fp; 124243412Snewton struct proc *p; 124343412Snewton register_t *retval; 124443412Snewton int fd; 124543412Snewton u_long cmd; 124643412Snewton caddr_t dat; 124743412Snewton{ 124843412Snewton int error; 124943412Snewton int nread = 0; 125043412Snewton 125143412Snewton /* 125243412Snewton * We are supposed to return the message length in nread, and the 125343412Snewton * number of messages in retval. We don't have the notion of number 125443412Snewton * of stream messages, so we just find out if we have any bytes waiting 125543412Snewton * for us, and if we do, then we assume that we have at least one 125643412Snewton * message waiting for us. 125743412Snewton */ 125843412Snewton if ((error = (*fp->f_ops->fo_ioctl)(fp, FIONREAD, 125943412Snewton (caddr_t) &nread, p)) != 0) 126043412Snewton return error; 126143412Snewton 126243412Snewton if (nread != 0) 126343412Snewton *retval = 1; 126443412Snewton else 126543412Snewton *retval = 0; 126643412Snewton 126743412Snewton return copyout(&nread, dat, sizeof(nread)); 126843412Snewton} 126943412Snewton 127043412Snewtonstatic int 127143412Snewtoni_fdinsert(fp, p, retval, fd, cmd, dat) 127243412Snewton struct file *fp; 127343412Snewton struct proc *p; 127443412Snewton register_t *retval; 127543412Snewton int fd; 127643412Snewton u_long cmd; 127743412Snewton caddr_t dat; 127843412Snewton{ 127943412Snewton /* 128043412Snewton * Major hack again here. We assume that we are using this to 128143412Snewton * implement accept(2). If that is the case, we have already 128243412Snewton * called accept, and we have stored the file descriptor in 128343412Snewton * afd. We find the file descriptor that the code wants to use 128443412Snewton * in fd insert, and then we dup2() our accepted file descriptor 128543412Snewton * to it. 128643412Snewton */ 128743412Snewton int error; 128843412Snewton struct svr4_strm *st = svr4_stream_get(fp); 128943412Snewton struct svr4_strfdinsert fdi; 129043412Snewton struct dup2_args d2p; 129143412Snewton struct close_args clp; 129243412Snewton 129343412Snewton if (st == NULL) { 129443412Snewton DPRINTF(("fdinsert: bad file type\n")); 129543412Snewton return EINVAL; 129643412Snewton } 129743412Snewton 129843412Snewton if (st->s_afd == -1) { 129943412Snewton DPRINTF(("fdinsert: accept fd not found\n")); 130043412Snewton return ENOENT; 130143412Snewton } 130243412Snewton 130343412Snewton if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) { 130443412Snewton DPRINTF(("fdinsert: copyin failed %d\n", error)); 130543412Snewton return error; 130643412Snewton } 130743412Snewton 130843412Snewton SCARG(&d2p, from) = st->s_afd; 130943412Snewton SCARG(&d2p, to) = fdi.fd; 131043412Snewton 131143412Snewton if ((error = dup2(p, &d2p)) != 0) { 131243412Snewton DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n", 131343412Snewton st->s_afd, fdi.fd, error)); 131443412Snewton return error; 131543412Snewton } 131643412Snewton 131743412Snewton SCARG(&clp, fd) = st->s_afd; 131843412Snewton 131943412Snewton if ((error = close(p, &clp)) != 0) { 132043412Snewton DPRINTF(("fdinsert: close(%d) failed %d\n", 132143412Snewton st->s_afd, error)); 132243412Snewton return error; 132343412Snewton } 132443412Snewton 132543412Snewton st->s_afd = -1; 132643412Snewton 132743412Snewton *retval = 0; 132843412Snewton return 0; 132943412Snewton} 133043412Snewton 133143412Snewton 133243412Snewtonstatic int 133343412Snewton_i_bind_rsvd(fp, p, retval, fd, cmd, dat) 133443412Snewton struct file *fp; 133543412Snewton struct proc *p; 133643412Snewton register_t *retval; 133743412Snewton int fd; 133843412Snewton u_long cmd; 133943412Snewton caddr_t dat; 134043412Snewton{ 134143412Snewton struct mkfifo_args ap; 134243412Snewton 134343412Snewton /* 134443412Snewton * This is a supposed to be a kernel and library only ioctl. 134543412Snewton * It gets called before ti_bind, when we have a unix 134643412Snewton * socket, to physically create the socket transport and 134743412Snewton * ``reserve'' it. I don't know how this get reserved inside 134843412Snewton * the kernel, but we are going to create it nevertheless. 134943412Snewton */ 135043412Snewton SCARG(&ap, path) = dat; 135143412Snewton SCARG(&ap, mode) = S_IFIFO; 135243412Snewton 135343412Snewton return mkfifo(p, &ap); 135443412Snewton} 135543412Snewton 135643412Snewtonstatic int 135743412Snewton_i_rele_rsvd(fp, p, retval, fd, cmd, dat) 135843412Snewton struct file *fp; 135943412Snewton struct proc *p; 136043412Snewton register_t *retval; 136143412Snewton int fd; 136243412Snewton u_long cmd; 136343412Snewton caddr_t dat; 136443412Snewton{ 136543412Snewton struct unlink_args ap; 136643412Snewton 136743412Snewton /* 136843412Snewton * This is a supposed to be a kernel and library only ioctl. 136943412Snewton * I guess it is supposed to release the socket. 137043412Snewton */ 137143412Snewton SCARG(&ap, path) = dat; 137243412Snewton 137343412Snewton return unlink(p, &ap); 137443412Snewton} 137543412Snewton 137643412Snewtonstatic int 137743412Snewtoni_str(fp, p, retval, fd, cmd, dat) 137843412Snewton struct file *fp; 137943412Snewton struct proc *p; 138043412Snewton register_t *retval; 138143412Snewton int fd; 138243412Snewton u_long cmd; 138343412Snewton caddr_t dat; 138443412Snewton{ 138543412Snewton int error; 138643412Snewton struct svr4_strioctl ioc; 138743412Snewton 138843412Snewton if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0) 138943412Snewton return error; 139043412Snewton 139143412Snewton#ifdef DEBUG_SVR4 139243412Snewton if ((error = show_ioc(">", &ioc)) != 0) 139343412Snewton return error; 139443412Snewton#endif /* DEBUG_SVR4 */ 139543412Snewton 139643412Snewton switch (ioc.cmd & 0xff00) { 139743412Snewton case SVR4_SIMOD: 139843412Snewton if ((error = sockmod(fp, fd, &ioc, p)) != 0) 139943412Snewton return error; 140043412Snewton break; 140143412Snewton 140243412Snewton case SVR4_TIMOD: 140343412Snewton if ((error = timod(fp, fd, &ioc, p)) != 0) 140443412Snewton return error; 140543412Snewton break; 140643412Snewton 140743412Snewton default: 140843412Snewton DPRINTF(("Unimplemented module %c %ld\n", 140943412Snewton (char) (cmd >> 8), cmd & 0xff)); 141043412Snewton return 0; 141143412Snewton } 141243412Snewton 141343412Snewton#ifdef DEBUG_SVR4 141443412Snewton if ((error = show_ioc("<", &ioc)) != 0) 141543412Snewton return error; 141643412Snewton#endif /* DEBUG_SVR4 */ 141743412Snewton return copyout(&ioc, dat, sizeof(ioc)); 141843412Snewton} 141943412Snewton 142043412Snewtonstatic int 142143412Snewtoni_setsig(fp, p, retval, fd, cmd, dat) 142243412Snewton struct file *fp; 142343412Snewton struct proc *p; 142443412Snewton register_t *retval; 142543412Snewton int fd; 142643412Snewton u_long cmd; 142743412Snewton caddr_t dat; 142843412Snewton{ 142943412Snewton /* 143043412Snewton * This is the best we can do for now; we cannot generate 143143412Snewton * signals only for specific events so the signal mask gets 143243412Snewton * ignored; we save it just to pass it to a possible I_GETSIG... 143343412Snewton * 143443412Snewton * We alse have to fix the O_ASYNC fcntl bit, so the 143543412Snewton * process will get SIGPOLLs. 143643412Snewton */ 143743412Snewton struct fcntl_args fa; 143843412Snewton int error; 143943412Snewton register_t oflags, flags; 144043412Snewton struct svr4_strm *st = svr4_stream_get(fp); 144143412Snewton 144243412Snewton if (st == NULL) { 144343412Snewton DPRINTF(("i_setsig: bad file descriptor\n")); 144443412Snewton return EINVAL; 144543412Snewton } 144643412Snewton /* get old status flags */ 144743412Snewton SCARG(&fa, fd) = fd; 144843412Snewton SCARG(&fa, cmd) = F_GETFL; 144943412Snewton if ((error = fcntl(p, &fa)) != 0) 145043412Snewton return error; 145143412Snewton 145243412Snewton oflags = p->p_retval[0]; 145343412Snewton 145443412Snewton /* update the flags */ 145543412Snewton if (dat != NULL) { 145643412Snewton int mask; 145743412Snewton 145843412Snewton flags = oflags | O_ASYNC; 145943412Snewton if ((error = copyin(dat, &mask, sizeof(mask))) != 0) { 146043412Snewton DPRINTF(("i_setsig: bad eventmask pointer\n")); 146143412Snewton return error; 146243412Snewton } 146343412Snewton if (mask & SVR4_S_ALLMASK) { 146443412Snewton DPRINTF(("i_setsig: bad eventmask data %x\n", mask)); 146543412Snewton return EINVAL; 146643412Snewton } 146743412Snewton st->s_eventmask = mask; 146843412Snewton } 146943412Snewton else { 147043412Snewton flags = oflags & ~O_ASYNC; 147143412Snewton st->s_eventmask = 0; 147243412Snewton } 147343412Snewton 147443412Snewton /* set the new flags, if changed */ 147543412Snewton if (flags != oflags) { 147643412Snewton SCARG(&fa, cmd) = F_SETFL; 147743412Snewton SCARG(&fa, arg) = (long) flags; 147843412Snewton if ((error = fcntl(p, &fa)) != 0) 147943412Snewton return error; 148043412Snewton flags = p->p_retval[0]; 148143412Snewton } 148243412Snewton 148343412Snewton /* set up SIGIO receiver if needed */ 148443412Snewton if (dat != NULL) { 148543412Snewton SCARG(&fa, cmd) = F_SETOWN; 148643412Snewton SCARG(&fa, arg) = (long) p->p_pid; 148743412Snewton return fcntl(p, &fa); 148843412Snewton } 148943412Snewton return 0; 149043412Snewton} 149143412Snewton 149243412Snewtonstatic int 149343412Snewtoni_getsig(fp, p, retval, fd, cmd, dat) 149443412Snewton struct file *fp; 149543412Snewton struct proc *p; 149643412Snewton register_t *retval; 149743412Snewton int fd; 149843412Snewton u_long cmd; 149943412Snewton caddr_t dat; 150043412Snewton{ 150143412Snewton int error; 150243412Snewton 150343412Snewton if (dat != NULL) { 150443412Snewton struct svr4_strm *st = svr4_stream_get(fp); 150543412Snewton 150643412Snewton if (st == NULL) { 150743412Snewton DPRINTF(("i_getsig: bad file descriptor\n")); 150843412Snewton return EINVAL; 150943412Snewton } 151043412Snewton if ((error = copyout(&st->s_eventmask, dat, 151143412Snewton sizeof(st->s_eventmask))) != 0) { 151243412Snewton DPRINTF(("i_getsig: bad eventmask pointer\n")); 151343412Snewton return error; 151443412Snewton } 151543412Snewton } 151643412Snewton return 0; 151743412Snewton} 151843412Snewton 151943412Snewtonint 152043412Snewtonsvr4_stream_ioctl(fp, p, retval, fd, cmd, dat) 152143412Snewton struct file *fp; 152243412Snewton struct proc *p; 152343412Snewton register_t *retval; 152443412Snewton int fd; 152543412Snewton u_long cmd; 152643412Snewton caddr_t dat; 152743412Snewton{ 152843412Snewton *retval = 0; 152943412Snewton 153043412Snewton /* 153143412Snewton * All the following stuff assumes "sockmod" is pushed... 153243412Snewton */ 153343412Snewton switch (cmd) { 153443412Snewton case SVR4_I_NREAD: 153543412Snewton DPRINTF(("I_NREAD\n")); 153643412Snewton return i_nread(fp, p, retval, fd, cmd, dat); 153743412Snewton 153843412Snewton case SVR4_I_PUSH: 153943412Snewton DPRINTF(("I_PUSH %x\n", dat)); 154043412Snewton#if defined(DEBUG_SVR4) 154143412Snewton show_strbuf(dat); 154243412Snewton#endif 154343412Snewton return 0; 154443412Snewton 154543412Snewton case SVR4_I_POP: 154643412Snewton DPRINTF(("I_POP\n")); 154743412Snewton return 0; 154843412Snewton 154943412Snewton case SVR4_I_LOOK: 155043412Snewton DPRINTF(("I_LOOK\n")); 155143412Snewton return 0; 155243412Snewton 155343412Snewton case SVR4_I_FLUSH: 155443412Snewton DPRINTF(("I_FLUSH\n")); 155543412Snewton return 0; 155643412Snewton 155743412Snewton case SVR4_I_SRDOPT: 155843412Snewton DPRINTF(("I_SRDOPT\n")); 155943412Snewton return 0; 156043412Snewton 156143412Snewton case SVR4_I_GRDOPT: 156243412Snewton DPRINTF(("I_GRDOPT\n")); 156343412Snewton return 0; 156443412Snewton 156543412Snewton case SVR4_I_STR: 156643412Snewton DPRINTF(("I_STR\n")); 156743412Snewton return i_str(fp, p, retval, fd, cmd, dat); 156843412Snewton 156943412Snewton case SVR4_I_SETSIG: 157043412Snewton DPRINTF(("I_SETSIG\n")); 157143412Snewton return i_setsig(fp, p, retval, fd, cmd, dat); 157243412Snewton 157343412Snewton case SVR4_I_GETSIG: 157443412Snewton DPRINTF(("I_GETSIG\n")); 157543412Snewton return i_getsig(fp, p, retval, fd, cmd, dat); 157643412Snewton 157743412Snewton case SVR4_I_FIND: 157843412Snewton DPRINTF(("I_FIND\n")); 157943412Snewton /* 158043412Snewton * Here we are not pushing modules really, we just 158143412Snewton * pretend all are present 158243412Snewton */ 158343412Snewton *retval = 0; 158443412Snewton return 0; 158543412Snewton 158643412Snewton case SVR4_I_LINK: 158743412Snewton DPRINTF(("I_LINK\n")); 158843412Snewton return 0; 158943412Snewton 159043412Snewton case SVR4_I_UNLINK: 159143412Snewton DPRINTF(("I_UNLINK\n")); 159243412Snewton return 0; 159343412Snewton 159443412Snewton case SVR4_I_ERECVFD: 159543412Snewton DPRINTF(("I_ERECVFD\n")); 159643412Snewton return 0; 159743412Snewton 159843412Snewton case SVR4_I_PEEK: 159943412Snewton DPRINTF(("I_PEEK\n")); 160043412Snewton return 0; 160143412Snewton 160243412Snewton case SVR4_I_FDINSERT: 160343412Snewton DPRINTF(("I_FDINSERT\n")); 160443412Snewton return i_fdinsert(fp, p, retval, fd, cmd, dat); 160543412Snewton 160643412Snewton case SVR4_I_SENDFD: 160743412Snewton DPRINTF(("I_SENDFD\n")); 160843412Snewton return 0; 160943412Snewton 161043412Snewton case SVR4_I_RECVFD: 161143412Snewton DPRINTF(("I_RECVFD\n")); 161243412Snewton return 0; 161343412Snewton 161443412Snewton case SVR4_I_SWROPT: 161543412Snewton DPRINTF(("I_SWROPT\n")); 161643412Snewton return 0; 161743412Snewton 161843412Snewton case SVR4_I_GWROPT: 161943412Snewton DPRINTF(("I_GWROPT\n")); 162043412Snewton return 0; 162143412Snewton 162243412Snewton case SVR4_I_LIST: 162343412Snewton DPRINTF(("I_LIST\n")); 162443412Snewton return 0; 162543412Snewton 162643412Snewton case SVR4_I_PLINK: 162743412Snewton DPRINTF(("I_PLINK\n")); 162843412Snewton return 0; 162943412Snewton 163043412Snewton case SVR4_I_PUNLINK: 163143412Snewton DPRINTF(("I_PUNLINK\n")); 163243412Snewton return 0; 163343412Snewton 163443412Snewton case SVR4_I_SETEV: 163543412Snewton DPRINTF(("I_SETEV\n")); 163643412Snewton return 0; 163743412Snewton 163843412Snewton case SVR4_I_GETEV: 163943412Snewton DPRINTF(("I_GETEV\n")); 164043412Snewton return 0; 164143412Snewton 164243412Snewton case SVR4_I_STREV: 164343412Snewton DPRINTF(("I_STREV\n")); 164443412Snewton return 0; 164543412Snewton 164643412Snewton case SVR4_I_UNSTREV: 164743412Snewton DPRINTF(("I_UNSTREV\n")); 164843412Snewton return 0; 164943412Snewton 165043412Snewton case SVR4_I_FLUSHBAND: 165143412Snewton DPRINTF(("I_FLUSHBAND\n")); 165243412Snewton return 0; 165343412Snewton 165443412Snewton case SVR4_I_CKBAND: 165543412Snewton DPRINTF(("I_CKBAND\n")); 165643412Snewton return 0; 165743412Snewton 165843412Snewton case SVR4_I_GETBAND: 165943412Snewton DPRINTF(("I_GETBANK\n")); 166043412Snewton return 0; 166143412Snewton 166243412Snewton case SVR4_I_ATMARK: 166343412Snewton DPRINTF(("I_ATMARK\n")); 166443412Snewton return 0; 166543412Snewton 166643412Snewton case SVR4_I_SETCLTIME: 166743412Snewton DPRINTF(("I_SETCLTIME\n")); 166843412Snewton return 0; 166943412Snewton 167043412Snewton case SVR4_I_GETCLTIME: 167143412Snewton DPRINTF(("I_GETCLTIME\n")); 167243412Snewton return 0; 167343412Snewton 167443412Snewton case SVR4_I_CANPUT: 167543412Snewton DPRINTF(("I_CANPUT\n")); 167643412Snewton return 0; 167743412Snewton 167843412Snewton case SVR4__I_BIND_RSVD: 167943412Snewton DPRINTF(("_I_BIND_RSVD\n")); 168043412Snewton return _i_bind_rsvd(fp, p, retval, fd, cmd, dat); 168143412Snewton 168243412Snewton case SVR4__I_RELE_RSVD: 168343412Snewton DPRINTF(("_I_RELE_RSVD\n")); 168443412Snewton return _i_rele_rsvd(fp, p, retval, fd, cmd, dat); 168543412Snewton 168643412Snewton default: 168743412Snewton DPRINTF(("unimpl cmd = %lx\n", cmd)); 168843412Snewton break; 168943412Snewton } 169043412Snewton 169143412Snewton return 0; 169243412Snewton} 169343412Snewton 169443412Snewton 169543412Snewton 169643412Snewtonint 169743412Snewtonsvr4_sys_putmsg(p, uap) 169843412Snewton register struct proc *p; 169943412Snewton struct svr4_sys_putmsg_args *uap; 170043412Snewton{ 170143412Snewton struct filedesc *fdp = p->p_fd; 170243412Snewton struct file *fp; 170343412Snewton struct svr4_strbuf dat, ctl; 170443412Snewton struct svr4_strmcmd sc; 170543412Snewton struct sockaddr_in sain; 170643412Snewton struct sockaddr_un saun; 170743412Snewton void *skp, *sup; 170843412Snewton int sasize, *retval; 170943412Snewton struct svr4_strm *st; 171043412Snewton int error; 171143412Snewton caddr_t sg; 171243412Snewton 171343412Snewton retval = p->p_retval; 171443412Snewton if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 171543412Snewton (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) { 171643412Snewton#ifdef DEBUG_SVR4 171743412Snewton uprintf("putmsg: bad fp\n"); 171843412Snewton#endif 171943412Snewton return EBADF; 172043412Snewton } 172143412Snewton 172243412Snewton#ifdef DEBUG_SVR4 172343412Snewton show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl), 172443412Snewton SCARG(uap, dat), SCARG(uap, flags)); 172543412Snewton#endif /* DEBUG_SVR4 */ 172643412Snewton 172743412Snewton if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 172843412Snewton (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) { 172943412Snewton#ifdef DEBUG_SVR4 173043412Snewton uprintf("putmsg: bad fp(2)\n"); 173143412Snewton#endif 173243412Snewton return EBADF; 173343412Snewton } 173443412Snewton 173543412Snewton if (SCARG(uap, ctl) != NULL) { 173643412Snewton if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) { 173743412Snewton#ifdef DEBUG_SVR4 173843412Snewton uprintf("putmsg: copyin(): %d\n", error); 173943412Snewton#endif 174043412Snewton return error; 174143412Snewton } 174243412Snewton } 174343412Snewton else 174443412Snewton ctl.len = -1; 174543412Snewton 174643412Snewton if (SCARG(uap, dat) != NULL) { 174743412Snewton if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) { 174843412Snewton#ifdef DEBUG_SVR4 174943412Snewton uprintf("putmsg: copyin(): %d (2)\n", error); 175043412Snewton#endif 175143412Snewton return error; 175243412Snewton } 175343412Snewton } 175443412Snewton else 175543412Snewton dat.len = -1; 175643412Snewton 175743412Snewton /* 175843412Snewton * Only for sockets for now. 175943412Snewton */ 176043412Snewton if ((st = svr4_stream_get(fp)) == NULL) { 176143412Snewton DPRINTF(("putmsg: bad file type\n")); 176243412Snewton return EINVAL; 176343412Snewton } 176443412Snewton 176543412Snewton if (ctl.len > sizeof(sc)) { 176643412Snewton DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len, 176743412Snewton sizeof(struct svr4_strmcmd))); 176843412Snewton return EINVAL; 176943412Snewton } 177043412Snewton 177143412Snewton if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 177243412Snewton return error; 177343412Snewton 177443412Snewton switch (st->s_family) { 177543412Snewton case AF_INET: 177643412Snewton if (sc.len != sizeof(sain)) { 177743412Snewton if (sc.cmd == SVR4_TI_DATA_REQUEST) { 177843412Snewton struct write_args wa; 177943412Snewton 178043412Snewton /* Solaris seems to use sc.cmd = 3 to 178143412Snewton * send "expedited" data. telnet uses 178243412Snewton * this for options processing, sending EOF, 178343412Snewton * etc. I'm sure other things use it too. 178443412Snewton * I don't have any documentation 178543412Snewton * on it, so I'm making a guess that this 178643412Snewton * is how it works. newton@atdot.dotat.org XXX 178743412Snewton */ 178843412Snewton DPRINTF(("sending expedited data (???)\n")); 178943412Snewton SCARG(&wa, fd) = SCARG(uap, fd); 179043412Snewton SCARG(&wa, buf) = dat.buf; 179143412Snewton SCARG(&wa, nbyte) = dat.len; 179243412Snewton return write(p, &wa); 179343412Snewton } 179443412Snewton DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len)); 179543412Snewton return EINVAL; 179643412Snewton } 179743412Snewton netaddr_to_sockaddr_in(&sain, &sc); 179843412Snewton skp = &sain; 179943412Snewton sasize = sizeof(sain); 180043412Snewton error = sain.sin_family != st->s_family; 180143412Snewton break; 180243412Snewton 180343412Snewton case AF_LOCAL: 180443412Snewton if (ctl.len == 8) { 180543412Snewton /* We are doing an accept; succeed */ 180643412Snewton DPRINTF(("putmsg: Do nothing\n")); 180743412Snewton *retval = 0; 180843412Snewton return 0; 180943412Snewton } 181043412Snewton else { 181143412Snewton /* Maybe we've been given a device/inode pair */ 181249267Snewton udev_t *dev = SVR4_ADDROF(&sc); 181343412Snewton ino_t *ino = (ino_t *) &dev[1]; 181443412Snewton skp = svr4_find_socket(p, fp, *dev, *ino); 181543412Snewton if (skp == NULL) { 181643412Snewton skp = &saun; 181743412Snewton /* I guess we have it by name */ 181843412Snewton netaddr_to_sockaddr_un(skp, &sc); 181943412Snewton } 182043412Snewton sasize = sizeof(saun); 182143412Snewton } 182243412Snewton break; 182343412Snewton 182443412Snewton default: 182543412Snewton DPRINTF(("putmsg: Unsupported address family %d\n", 182643412Snewton st->s_family)); 182743412Snewton return ENOSYS; 182843412Snewton } 182943412Snewton 183043412Snewton sg = stackgap_init(); 183143412Snewton sup = stackgap_alloc(&sg, sasize); 183243412Snewton 183343412Snewton if ((error = copyout(skp, sup, sasize)) != 0) 183443412Snewton return error; 183543412Snewton 183643412Snewton switch (st->s_cmd = sc.cmd) { 183743412Snewton case SVR4_TI_CONNECT_REQUEST: /* connect */ 183843412Snewton { 183943412Snewton struct connect_args co; 184043412Snewton 184143412Snewton SCARG(&co, s) = SCARG(uap, fd); 184243412Snewton SCARG(&co, name) = (void *) sup; 184343412Snewton SCARG(&co, namelen) = (int) sasize; 184443412Snewton 184543412Snewton return connect(p, &co); 184643412Snewton } 184743412Snewton 184843412Snewton case SVR4_TI_SENDTO_REQUEST: /* sendto */ 184943412Snewton { 185043412Snewton struct msghdr msg; 185143412Snewton struct iovec aiov; 185243412Snewton 185343412Snewton msg.msg_name = (caddr_t) sup; 185443412Snewton msg.msg_namelen = sasize; 185543412Snewton msg.msg_iov = &aiov; 185643412Snewton msg.msg_iovlen = 1; 185743412Snewton msg.msg_control = 0; 185843412Snewton msg.msg_flags = 0; 185943412Snewton aiov.iov_base = dat.buf; 186043412Snewton aiov.iov_len = dat.len; 186143412Snewton#if 0 186243412Snewton error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 186343412Snewton uio, 0, 0, 0, uio->uio_procp); 186443412Snewton#endif 186543412Snewton error = svr4_sendit(p, SCARG(uap, fd), &msg, 186643412Snewton SCARG(uap, flags)); 186743412Snewton DPRINTF(("sendto_request error: %d\n", error)); 186843412Snewton *retval = 0; 186943412Snewton return error; 187043412Snewton } 187143412Snewton 187243412Snewton default: 187343412Snewton DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd)); 187443412Snewton return ENOSYS; 187543412Snewton } 187643412Snewton} 187743412Snewton 187843412Snewtonint 187943412Snewtonsvr4_sys_getmsg(p, uap) 188043412Snewton register struct proc *p; 188143412Snewton struct svr4_sys_getmsg_args *uap; 188243412Snewton{ 188343412Snewton struct filedesc *fdp = p->p_fd; 188443412Snewton struct file *fp; 188543412Snewton struct getpeername_args ga; 188643412Snewton struct accept_args aa; 188743412Snewton struct svr4_strbuf dat, ctl; 188843412Snewton struct svr4_strmcmd sc; 188943412Snewton int error, *retval; 189043412Snewton struct msghdr msg; 189143412Snewton struct iovec aiov; 189243412Snewton struct sockaddr_in sain; 189343412Snewton struct sockaddr_un saun; 189443412Snewton void *skp, *sup; 189543412Snewton int sasize; 189643412Snewton struct svr4_strm *st; 189743412Snewton int *flen; 189843412Snewton int fl; 189943412Snewton caddr_t sg; 190043412Snewton 190143412Snewton retval = p->p_retval; 190243412Snewton if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 190343412Snewton (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 190443412Snewton return EBADF; 190543412Snewton 190643412Snewton memset(&sc, 0, sizeof(sc)); 190743412Snewton 190843412Snewton#ifdef DEBUG_SVR4 190943412Snewton show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl), 191043412Snewton SCARG(uap, dat), 0); 191143412Snewton#endif /* DEBUG_SVR4 */ 191243412Snewton 191343412Snewton if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 191443412Snewton (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 191543412Snewton return EBADF; 191643412Snewton 191743412Snewton if (SCARG(uap, ctl) != NULL) { 191843412Snewton if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) 191943412Snewton return error; 192043412Snewton } 192143412Snewton else { 192243412Snewton ctl.len = -1; 192343412Snewton ctl.maxlen = 0; 192443412Snewton } 192543412Snewton 192643412Snewton if (SCARG(uap, dat) != NULL) { 192743412Snewton if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) 192843412Snewton return error; 192943412Snewton } 193043412Snewton else { 193143412Snewton dat.len = -1; 193243412Snewton dat.maxlen = 0; 193343412Snewton } 193443412Snewton 193543412Snewton /* 193643412Snewton * Only for sockets for now. 193743412Snewton */ 193843412Snewton if ((st = svr4_stream_get(fp)) == NULL) { 193943412Snewton DPRINTF(("getmsg: bad file type\n")); 194043412Snewton return EINVAL; 194143412Snewton } 194243412Snewton 194343412Snewton if (ctl.maxlen == -1 || dat.maxlen == -1) { 194443412Snewton DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n")); 194543412Snewton return ENOSYS; 194643412Snewton } 194743412Snewton 194843412Snewton switch (st->s_family) { 194943412Snewton case AF_INET: 195043412Snewton skp = &sain; 195143412Snewton sasize = sizeof(sain); 195243412Snewton break; 195343412Snewton 195443412Snewton case AF_LOCAL: 195543412Snewton skp = &saun; 195643412Snewton sasize = sizeof(saun); 195743412Snewton break; 195843412Snewton 195943412Snewton default: 196043412Snewton DPRINTF(("getmsg: Unsupported address family %d\n", 196143412Snewton st->s_family)); 196243412Snewton return ENOSYS; 196343412Snewton } 196443412Snewton 196543412Snewton sg = stackgap_init(); 196643412Snewton sup = stackgap_alloc(&sg, sasize); 196743412Snewton flen = (int *) stackgap_alloc(&sg, sizeof(*flen)); 196843412Snewton 196943412Snewton fl = sasize; 197043412Snewton if ((error = copyout(&fl, flen, sizeof(fl))) != 0) 197143412Snewton return error; 197243412Snewton 197343412Snewton switch (st->s_cmd) { 197443412Snewton case SVR4_TI_CONNECT_REQUEST: 197543412Snewton DPRINTF(("getmsg: TI_CONNECT_REQUEST\n")); 197643412Snewton /* 197743412Snewton * We do the connect in one step, so the putmsg should 197843412Snewton * have gotten the error. 197943412Snewton */ 198043412Snewton sc.cmd = SVR4_TI_OK_REPLY; 198143412Snewton sc.len = 0; 198243412Snewton 198343412Snewton ctl.len = 8; 198443412Snewton dat.len = -1; 198543412Snewton fl = 1; 198643412Snewton st->s_cmd = sc.cmd; 198743412Snewton break; 198843412Snewton 198943412Snewton case SVR4_TI_OK_REPLY: 199043412Snewton DPRINTF(("getmsg: TI_OK_REPLY\n")); 199143412Snewton /* 199243412Snewton * We are immediately after a connect reply, so we send 199343412Snewton * a connect verification. 199443412Snewton */ 199543412Snewton 199643412Snewton SCARG(&ga, fdes) = SCARG(uap, fd); 199743412Snewton SCARG(&ga, asa) = (void *) sup; 199843412Snewton SCARG(&ga, alen) = flen; 199943412Snewton 200043412Snewton if ((error = getpeername(p, &ga)) != 0) { 200143412Snewton DPRINTF(("getmsg: getpeername failed %d\n", error)); 200243412Snewton return error; 200343412Snewton } 200443412Snewton 200543412Snewton if ((error = copyin(sup, skp, sasize)) != 0) 200643412Snewton return error; 200743412Snewton 200843412Snewton sc.cmd = SVR4_TI_CONNECT_REPLY; 200943412Snewton sc.pad[0] = 0x4; 201043412Snewton sc.offs = 0x18; 201143412Snewton sc.pad[1] = 0x14; 201243412Snewton sc.pad[2] = 0x04000402; 201343412Snewton 201443412Snewton switch (st->s_family) { 201543412Snewton case AF_INET: 201643412Snewton sc.len = sasize; 201743412Snewton sockaddr_to_netaddr_in(&sc, &sain); 201843412Snewton break; 201943412Snewton 202043412Snewton case AF_LOCAL: 202143412Snewton sc.len = sasize + 4; 202243412Snewton sockaddr_to_netaddr_un(&sc, &saun); 202343412Snewton break; 202443412Snewton 202543412Snewton default: 202643412Snewton return ENOSYS; 202743412Snewton } 202843412Snewton 202943412Snewton ctl.len = 40; 203043412Snewton dat.len = -1; 203143412Snewton fl = 0; 203243412Snewton st->s_cmd = sc.cmd; 203343412Snewton break; 203443412Snewton 203543412Snewton case SVR4_TI__ACCEPT_OK: 203643412Snewton DPRINTF(("getmsg: TI__ACCEPT_OK\n")); 203743412Snewton /* 203843412Snewton * We do the connect in one step, so the putmsg should 203943412Snewton * have gotten the error. 204043412Snewton */ 204143412Snewton sc.cmd = SVR4_TI_OK_REPLY; 204243412Snewton sc.len = 1; 204343412Snewton 204443412Snewton ctl.len = 8; 204543412Snewton dat.len = -1; 204643412Snewton fl = 1; 204743412Snewton st->s_cmd = SVR4_TI__ACCEPT_WAIT; 204843412Snewton break; 204943412Snewton 205043412Snewton case SVR4_TI__ACCEPT_WAIT: 205143412Snewton DPRINTF(("getmsg: TI__ACCEPT_WAIT\n")); 205243412Snewton /* 205343412Snewton * We are after a listen, so we try to accept... 205443412Snewton */ 205543412Snewton SCARG(&aa, s) = SCARG(uap, fd); 205643412Snewton SCARG(&aa, name) = (void *) sup; 205743412Snewton SCARG(&aa, anamelen) = flen; 205843412Snewton 205943412Snewton if ((error = accept(p, &aa)) != 0) { 206043412Snewton DPRINTF(("getmsg: accept failed %d\n", error)); 206143412Snewton return error; 206243412Snewton } 206343412Snewton 206443412Snewton st->s_afd = *retval; 206543412Snewton 206643412Snewton DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd)); 206743412Snewton 206843412Snewton if ((error = copyin(sup, skp, sasize)) != 0) 206943412Snewton return error; 207043412Snewton 207143412Snewton sc.cmd = SVR4_TI_ACCEPT_REPLY; 207243412Snewton sc.offs = 0x18; 207343412Snewton sc.pad[0] = 0x0; 207443412Snewton 207543412Snewton switch (st->s_family) { 207643412Snewton case AF_INET: 207743412Snewton sc.pad[1] = 0x28; 207843412Snewton sockaddr_to_netaddr_in(&sc, &sain); 207943412Snewton ctl.len = 40; 208043412Snewton sc.len = sasize; 208143412Snewton break; 208243412Snewton 208343412Snewton case AF_LOCAL: 208443412Snewton sc.pad[1] = 0x00010000; 208543412Snewton sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */ 208643412Snewton sc.pad[3] = 0x00010000; 208743412Snewton ctl.len = 134; 208843412Snewton sc.len = sasize + 4; 208943412Snewton break; 209043412Snewton 209143412Snewton default: 209243412Snewton return ENOSYS; 209343412Snewton } 209443412Snewton 209543412Snewton dat.len = -1; 209643412Snewton fl = 0; 209743412Snewton st->s_cmd = SVR4_TI__ACCEPT_OK; 209843412Snewton break; 209943412Snewton 210043412Snewton case SVR4_TI_SENDTO_REQUEST: 210143412Snewton DPRINTF(("getmsg: TI_SENDTO_REQUEST\n")); 210243412Snewton if (ctl.maxlen > 36 && ctl.len < 36) 210343412Snewton ctl.len = 36; 210443412Snewton 210543412Snewton if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 210643412Snewton return error; 210743412Snewton 210843412Snewton switch (st->s_family) { 210943412Snewton case AF_INET: 211043412Snewton sockaddr_to_netaddr_in(&sc, &sain); 211143412Snewton break; 211243412Snewton 211343412Snewton case AF_LOCAL: 211443412Snewton sockaddr_to_netaddr_un(&sc, &saun); 211543412Snewton break; 211643412Snewton 211743412Snewton default: 211843412Snewton return ENOSYS; 211943412Snewton } 212043412Snewton 212143412Snewton msg.msg_name = (caddr_t) sup; 212243412Snewton msg.msg_namelen = sasize; 212343412Snewton msg.msg_iov = &aiov; 212443412Snewton msg.msg_iovlen = 1; 212543412Snewton msg.msg_control = 0; 212643412Snewton aiov.iov_base = dat.buf; 212743412Snewton aiov.iov_len = dat.maxlen; 212843412Snewton msg.msg_flags = 0; 212943412Snewton 213043412Snewton error = svr4_recvit(p, SCARG(uap, fd), &msg, (caddr_t) flen); 213143412Snewton 213243412Snewton if (error) { 213343412Snewton DPRINTF(("getmsg: recvit failed %d\n", error)); 213443412Snewton return error; 213543412Snewton } 213643412Snewton 213743412Snewton if ((error = copyin(msg.msg_name, skp, sasize)) != 0) 213843412Snewton return error; 213943412Snewton 214043412Snewton sc.cmd = SVR4_TI_RECVFROM_IND; 214143412Snewton 214243412Snewton switch (st->s_family) { 214343412Snewton case AF_INET: 214443412Snewton sc.len = sasize; 214543412Snewton sockaddr_to_netaddr_in(&sc, &sain); 214643412Snewton break; 214743412Snewton 214843412Snewton case AF_LOCAL: 214943412Snewton sc.len = sasize + 4; 215043412Snewton sockaddr_to_netaddr_un(&sc, &saun); 215143412Snewton break; 215243412Snewton 215343412Snewton default: 215443412Snewton return ENOSYS; 215543412Snewton } 215643412Snewton 215743412Snewton dat.len = *retval; 215843412Snewton fl = 0; 215943412Snewton st->s_cmd = sc.cmd; 216043412Snewton break; 216143412Snewton 216243412Snewton default: 216343412Snewton st->s_cmd = sc.cmd; 216443412Snewton if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) { 216543412Snewton struct read_args ra; 216643412Snewton 216743412Snewton /* More wierdness: Again, I can't find documentation 216843412Snewton * to back this up, but when a process does a generic 216943412Snewton * "getmsg()" call it seems that the command field is 217043412Snewton * zero and the length of the data area is zero. I 217143412Snewton * think processes expect getmsg() to fill in dat.len 217243412Snewton * after reading at most dat.maxlen octets from the 217343412Snewton * stream. Since we're using sockets I can let 217443412Snewton * read() look after it and frob return values 217543412Snewton * appropriately (or inappropriately :-) 217643412Snewton * -- newton@atdot.dotat.org XXX 217743412Snewton */ 217843412Snewton SCARG(&ra, fd) = SCARG(uap, fd); 217943412Snewton SCARG(&ra, buf) = dat.buf; 218043412Snewton SCARG(&ra, nbyte) = dat.maxlen; 218143412Snewton if ((error = read(p, &ra)) != 0) { 218243412Snewton return error; 218343412Snewton } 218443412Snewton dat.len = *retval; 218543412Snewton *retval = 0; 218643412Snewton st->s_cmd = SVR4_TI_SENDTO_REQUEST; 218743412Snewton break; 218843412Snewton } 218943412Snewton DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd)); 219043412Snewton return EINVAL; 219143412Snewton } 219243412Snewton 219343412Snewton if (SCARG(uap, ctl)) { 219443412Snewton if (ctl.len != -1) 219543412Snewton if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0) 219643412Snewton return error; 219743412Snewton 219843412Snewton if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0) 219943412Snewton return error; 220043412Snewton } 220143412Snewton 220243412Snewton if (SCARG(uap, dat)) { 220343412Snewton if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0) 220443412Snewton return error; 220543412Snewton } 220643412Snewton 220743412Snewton if (SCARG(uap, flags)) { /* XXX: Need translation */ 220843412Snewton if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0) 220943412Snewton return error; 221043412Snewton } 221143412Snewton 221243412Snewton *retval = 0; 221343412Snewton 221443412Snewton#ifdef DEBUG_SVR4 221543412Snewton show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl), 221643412Snewton SCARG(uap, dat), fl); 221743412Snewton#endif /* DEBUG_SVR4 */ 221843412Snewton return error; 221943412Snewton} 222043412Snewton 222143412Snewtonint svr4_sys_send(p, uap) 222243412Snewton struct proc *p; 222343412Snewton struct svr4_sys_send_args *uap; 222443412Snewton{ 222543412Snewton struct osend_args osa; 222643412Snewton SCARG(&osa, s) = SCARG(uap, s); 222743412Snewton SCARG(&osa, buf) = SCARG(uap, buf); 222843412Snewton SCARG(&osa, len) = SCARG(uap, len); 222943412Snewton SCARG(&osa, flags) = SCARG(uap, flags); 223043412Snewton return osend(p, &osa); 223143412Snewton} 223243412Snewton 223343412Snewtonint svr4_sys_recv(p, uap) 223443412Snewton struct proc *p; 223543412Snewton struct svr4_sys_recv_args *uap; 223643412Snewton{ 223743412Snewton struct orecv_args ora; 223843412Snewton SCARG(&ora, s) = SCARG(uap, s); 223943412Snewton SCARG(&ora, buf) = SCARG(uap, buf); 224043412Snewton SCARG(&ora, len) = SCARG(uap, len); 224143412Snewton SCARG(&ora, flags) = SCARG(uap, flags); 224243412Snewton return orecv(p, &ora); 224343412Snewton} 224443412Snewton 224543412Snewton/* 224643412Snewton * XXX This isn't necessary, but it's handy for inserting debug code into 224743412Snewton * sendto(). Let's leave it here for now... 224843412Snewton */ 224943412Snewtonint 225043412Snewtonsvr4_sys_sendto(p, uap) 225143412Snewton struct proc *p; 225243412Snewton struct svr4_sys_sendto_args *uap; 225343412Snewton{ 225443412Snewton struct sendto_args sa; 225543412Snewton 225643412Snewton SCARG(&sa, s) = SCARG(uap, s); 225743412Snewton SCARG(&sa, buf) = SCARG(uap, buf); 225843412Snewton SCARG(&sa, len) = SCARG(uap, len); 225943412Snewton SCARG(&sa, flags) = SCARG(uap, flags); 226043412Snewton SCARG(&sa, to) = SCARG(uap, to); 226143412Snewton SCARG(&sa, tolen) = SCARG(uap, tolen); 226243412Snewton 226343412Snewton DPRINTF(("calling sendto()\n")); 226443412Snewton return sendto(p, &sa); 226543412Snewton} 226643412Snewton 2267