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