svr4_stream.c revision 139743
1139743Simp/*- 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. 2943412Snewton */ 3043412Snewton 3143412Snewton/* 3243412Snewton * Pretend that we have streams... 3343412Snewton * Yes, this is gross. 3443412Snewton * 3543412Snewton * ToDo: The state machine for getmsg needs re-thinking 3643412Snewton */ 3743412Snewton 38116174Sobrien#include <sys/cdefs.h> 39116174Sobrien__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_stream.c 139743 2005-01-05 22:34:37Z imp $"); 40116174Sobrien 4143412Snewton#define COMPAT_43 1 4243412Snewton 43104571Srwatson#include "opt_mac.h" 44104571Srwatson 4543412Snewton#include <sys/param.h> 4643412Snewton#include <sys/systm.h> 4776166Smarkm#include <sys/fcntl.h> 4843412Snewton#include <sys/filedesc.h> 4943412Snewton#include <sys/filio.h> 5076166Smarkm#include <sys/lock.h> 5176166Smarkm#include <sys/malloc.h> 5276166Smarkm#include <sys/file.h> /* Must come after sys/malloc.h */ 53104571Srwatson#include <sys/mac.h> 5443412Snewton#include <sys/mbuf.h> 5576166Smarkm#include <sys/mutex.h> 5676166Smarkm#include <sys/proc.h> 5743412Snewton#include <sys/protosw.h> 5843412Snewton#include <sys/signal.h> 5943412Snewton#include <sys/signalvar.h> 6076166Smarkm#include <sys/socket.h> 6176166Smarkm#include <sys/socketvar.h> 6243412Snewton#include <sys/stat.h> 63134266Sjhb#include <sys/syscallsubr.h> 6443412Snewton#include <sys/sysproto.h> 6576166Smarkm#include <sys/uio.h> 6676166Smarkm#include <sys/ktrace.h> /* Must come after sys/uio.h */ 6776166Smarkm#include <sys/un.h> 6843412Snewton 6976166Smarkm#include <netinet/in.h> 7076166Smarkm 7165302Sobrien#include <compat/svr4/svr4.h> 7265302Sobrien#include <compat/svr4/svr4_types.h> 7365302Sobrien#include <compat/svr4/svr4_util.h> 7465302Sobrien#include <compat/svr4/svr4_signal.h> 7565302Sobrien#include <compat/svr4/svr4_proto.h> 7665302Sobrien#include <compat/svr4/svr4_stropts.h> 7765302Sobrien#include <compat/svr4/svr4_timod.h> 7865302Sobrien#include <compat/svr4/svr4_sockmod.h> 7965302Sobrien#include <compat/svr4/svr4_ioctl.h> 8065302Sobrien#include <compat/svr4/svr4_socket.h> 8143412Snewton 8243412Snewton/* Utils */ 8392761Salfredstatic int clean_pipe(struct thread *, const char *); 8492761Salfredstatic void getparm(struct file *, struct svr4_si_sockparms *); 8592761Salfredstatic int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *, 8692761Salfred struct file *); 8792761Salfredstatic int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *, 8892761Salfred struct file *); 8943412Snewton 9043412Snewton/* Address Conversions */ 9192761Salfredstatic void sockaddr_to_netaddr_in(struct svr4_strmcmd *, 9292761Salfred const struct sockaddr_in *); 9392761Salfredstatic void sockaddr_to_netaddr_un(struct svr4_strmcmd *, 9492761Salfred const struct sockaddr_un *); 9592761Salfredstatic void netaddr_to_sockaddr_in(struct sockaddr_in *, 9692761Salfred const struct svr4_strmcmd *); 9792761Salfredstatic void netaddr_to_sockaddr_un(struct sockaddr_un *, 9892761Salfred const struct svr4_strmcmd *); 9943412Snewton 10043412Snewton/* stream ioctls */ 10192761Salfredstatic int i_nread(struct file *, struct thread *, register_t *, int, 10292761Salfred u_long, caddr_t); 10392761Salfredstatic int i_fdinsert(struct file *, struct thread *, register_t *, int, 10492761Salfred u_long, caddr_t); 10592761Salfredstatic int i_str(struct file *, struct thread *, register_t *, int, 10692761Salfred u_long, caddr_t); 10792761Salfredstatic int i_setsig(struct file *, struct thread *, register_t *, int, 10892761Salfred u_long, caddr_t); 10992761Salfredstatic int i_getsig(struct file *, struct thread *, register_t *, int, 11092761Salfred u_long, caddr_t); 11192761Salfredstatic int _i_bind_rsvd(struct file *, struct thread *, register_t *, int, 11292761Salfred u_long, caddr_t); 11392761Salfredstatic int _i_rele_rsvd(struct file *, struct thread *, register_t *, int, 11492761Salfred u_long, caddr_t); 11543412Snewton 11643412Snewton/* i_str sockmod calls */ 11792761Salfredstatic int sockmod(struct file *, int, struct svr4_strioctl *, 11892761Salfred struct thread *); 11992761Salfredstatic int si_listen(struct file *, int, struct svr4_strioctl *, 12092761Salfred struct thread *); 12192761Salfredstatic int si_ogetudata(struct file *, int, struct svr4_strioctl *, 12292761Salfred struct thread *); 12392761Salfredstatic int si_sockparams(struct file *, int, struct svr4_strioctl *, 12492761Salfred struct thread *); 12592761Salfredstatic int si_shutdown (struct file *, int, struct svr4_strioctl *, 12692761Salfred struct thread *); 12792761Salfredstatic int si_getudata(struct file *, int, struct svr4_strioctl *, 12892761Salfred struct thread *); 12943412Snewton 13043412Snewton/* i_str timod calls */ 13192761Salfredstatic int timod(struct file *, int, struct svr4_strioctl *, struct thread *); 13292761Salfredstatic int ti_getinfo(struct file *, int, struct svr4_strioctl *, 13392761Salfred struct thread *); 13492761Salfredstatic int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *); 13543412Snewton 13643412Snewton/* infrastructure */ 13792761Salfredstatic int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags); 13843412Snewton 13992761Salfredstatic int svr4_recvit(struct thread *td, int s, struct msghdr *mp, 14092761Salfred caddr_t namelenp); 14143412Snewton 14243412Snewton/* <sigh> Ok, so we shouldn't use sendit() in uipc_syscalls.c because 14343412Snewton * it isn't part of a "public" interface; We're supposed to use 14443412Snewton * pru_sosend instead. Same goes for recvit()/pru_soreceive() for 14543412Snewton * that matter. Solution: Suck sendit()/recvit() into here where we 14643412Snewton * can do what we like. 14743412Snewton * 14843412Snewton * I hate code duplication. 14943412Snewton * 15043412Snewton * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though. 15143412Snewton */ 15243412Snewtonstatic int 15383366Sjuliansvr4_sendit(td, s, mp, flags) 15483366Sjulian register struct thread *td; 15543412Snewton int s; 15643412Snewton register struct msghdr *mp; 15743412Snewton int flags; 15843412Snewton{ 15943412Snewton struct uio auio; 16043412Snewton register struct iovec *iov; 16143412Snewton register int i; 16243412Snewton struct mbuf *control; 16343412Snewton struct sockaddr *to; 16443412Snewton int len, error; 16543412Snewton struct socket *so; 16643412Snewton#ifdef KTRACE 167131897Sphk struct uio *ktruio = NULL; 16843412Snewton#endif 16943412Snewton 17086487Sdillon if ((error = fgetsock(td, s, &so, NULL)) != 0) 17143412Snewton return (error); 172104571Srwatson 173104571Srwatson#ifdef MAC 174130398Srwatson SOCK_LOCK(so); 175104571Srwatson error = mac_check_socket_send(td->td_ucred, so); 176130398Srwatson SOCK_UNLOCK(so); 177104571Srwatson if (error) 178104571Srwatson goto done1; 179104571Srwatson#endif 180104571Srwatson 18143412Snewton auio.uio_iov = mp->msg_iov; 18243412Snewton auio.uio_iovcnt = mp->msg_iovlen; 18343412Snewton auio.uio_segflg = UIO_USERSPACE; 18443412Snewton auio.uio_rw = UIO_WRITE; 18583366Sjulian auio.uio_td = td; 18643412Snewton auio.uio_offset = 0; /* XXX */ 18743412Snewton auio.uio_resid = 0; 18843412Snewton iov = mp->msg_iov; 18943412Snewton for (i = 0; i < mp->msg_iovlen; i++, iov++) { 19069084Sdillon if ((auio.uio_resid += iov->iov_len) < 0) { 19186487Sdillon error = EINVAL; 19286487Sdillon goto done1; 19369084Sdillon } 19443412Snewton } 19543412Snewton if (mp->msg_name) { 19643412Snewton error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); 19786487Sdillon if (error) 19886487Sdillon goto done1; 19969084Sdillon } else { 20043412Snewton to = 0; 20169084Sdillon } 20243412Snewton if (mp->msg_control) { 20343412Snewton if (mp->msg_controllen < sizeof(struct cmsghdr)) { 20443412Snewton error = EINVAL; 20543412Snewton goto bad; 20643412Snewton } 20743412Snewton error = sockargs(&control, mp->msg_control, 20843412Snewton mp->msg_controllen, MT_CONTROL); 20943412Snewton if (error) 21043412Snewton goto bad; 21169084Sdillon } else { 21243412Snewton control = 0; 21369084Sdillon } 21443412Snewton#ifdef KTRACE 215131897Sphk if (KTRPOINT(td, KTR_GENIO)) 216131897Sphk ktruio = cloneuio(&auio); 21743412Snewton#endif 21843412Snewton len = auio.uio_resid; 21943412Snewton error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control, 22083366Sjulian flags, td); 22143412Snewton if (error) { 22243412Snewton if (auio.uio_resid != len && (error == ERESTART || 22343412Snewton error == EINTR || error == EWOULDBLOCK)) 22443412Snewton error = 0; 22573929Sjhb if (error == EPIPE) { 22683366Sjulian PROC_LOCK(td->td_proc); 22783366Sjulian psignal(td->td_proc, SIGPIPE); 22883366Sjulian PROC_UNLOCK(td->td_proc); 22973929Sjhb } 23043412Snewton } 23143412Snewton if (error == 0) 23283366Sjulian td->td_retval[0] = len - auio.uio_resid; 23343412Snewton#ifdef KTRACE 234131897Sphk if (ktruio != NULL) { 235131897Sphk ktruio->uio_resid = td->td_retval[0]; 236131897Sphk ktrgenio(s, UIO_WRITE, ktruio, error); 23743412Snewton } 23843412Snewton#endif 23943412Snewtonbad: 24043412Snewton if (to) 24143412Snewton FREE(to, M_SONAME); 24286487Sdillondone1: 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 263131897Sphk struct uio *ktruio = NULL; 26443412Snewton#endif 26543412Snewton 26686487Sdillon if ((error = fgetsock(td, s, &so, NULL)) != 0) 26743412Snewton return (error); 268104571Srwatson 269104571Srwatson#ifdef MAC 270130398Srwatson SOCK_LOCK(so); 271104571Srwatson error = mac_check_socket_receive(td->td_ucred, so); 272130398Srwatson SOCK_UNLOCK(so); 273104571Srwatson if (error) 274104571Srwatson goto done1; 275104571Srwatson#endif 276104571Srwatson 27743412Snewton auio.uio_iov = mp->msg_iov; 27843412Snewton auio.uio_iovcnt = mp->msg_iovlen; 27943412Snewton auio.uio_segflg = UIO_USERSPACE; 28043412Snewton auio.uio_rw = UIO_READ; 28183366Sjulian auio.uio_td = td; 28243412Snewton auio.uio_offset = 0; /* XXX */ 28343412Snewton auio.uio_resid = 0; 28443412Snewton iov = mp->msg_iov; 28543412Snewton for (i = 0; i < mp->msg_iovlen; i++, iov++) { 28669084Sdillon if ((auio.uio_resid += iov->iov_len) < 0) { 28786487Sdillon error = EINVAL; 28886487Sdillon goto done1; 28969084Sdillon } 29043412Snewton } 29143412Snewton#ifdef KTRACE 292131897Sphk if (KTRPOINT(td, KTR_GENIO)) 293131897Sphk ktruio = cloneuio(&auio); 29443412Snewton#endif 29543412Snewton len = auio.uio_resid; 29643412Snewton error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, 29743412Snewton (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 29843412Snewton &mp->msg_flags); 29943412Snewton if (error) { 30043412Snewton if (auio.uio_resid != len && (error == ERESTART || 30143412Snewton error == EINTR || error == EWOULDBLOCK)) 30243412Snewton error = 0; 30343412Snewton } 30443412Snewton#ifdef KTRACE 305131897Sphk if (ktruio != NULL) { 306131897Sphk ktruio->uio_resid = len - auio.uio_resid; 307131897Sphk ktrgenio(s, UIO_READ, ktruio, error); 30843412Snewton } 30943412Snewton#endif 31043412Snewton if (error) 31143412Snewton goto out; 31283366Sjulian td->td_retval[0] = len - auio.uio_resid; 31343412Snewton if (mp->msg_name) { 31443412Snewton len = mp->msg_namelen; 31543412Snewton if (len <= 0 || fromsa == 0) 31643412Snewton len = 0; 31743412Snewton else { 31843412Snewton /* save sa_len before it is destroyed by MSG_COMPAT */ 31943412Snewton len = MIN(len, fromsa->sa_len); 32043412Snewton error = copyout(fromsa, 32143412Snewton (caddr_t)mp->msg_name, (unsigned)len); 32243412Snewton if (error) 32343412Snewton goto out; 32443412Snewton } 32543412Snewton mp->msg_namelen = len; 32643412Snewton if (namelenp && 32743412Snewton (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 32843412Snewton goto out; 32943412Snewton } 33043412Snewton } 33143412Snewton if (mp->msg_control) { 33243412Snewton len = mp->msg_controllen; 33343412Snewton m = control; 33443412Snewton mp->msg_controllen = 0; 33543412Snewton ctlbuf = (caddr_t) mp->msg_control; 33643412Snewton 33743412Snewton while (m && len > 0) { 33843412Snewton unsigned int tocopy; 33943412Snewton 34043412Snewton if (len >= m->m_len) 34143412Snewton tocopy = m->m_len; 34243412Snewton else { 34343412Snewton mp->msg_flags |= MSG_CTRUNC; 34443412Snewton tocopy = len; 34543412Snewton } 34643412Snewton 34749267Snewton if ((error = copyout((caddr_t)mtod(m, caddr_t), 34849267Snewton ctlbuf, tocopy)) != 0) 34943412Snewton goto out; 35043412Snewton 35143412Snewton ctlbuf += tocopy; 35243412Snewton len -= tocopy; 35343412Snewton m = m->m_next; 35443412Snewton } 35553678Sphk mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control; 35643412Snewton } 35743412Snewtonout: 35843412Snewton if (fromsa) 35943412Snewton FREE(fromsa, M_SONAME); 36043412Snewton if (control) 36143412Snewton m_freem(control); 36286487Sdillondone1: 36386487Sdillon fputsock(so); 36443412Snewton return (error); 36543412Snewton} 36643412Snewton 36743412Snewton#ifdef DEBUG_SVR4 36892761Salfredstatic void bufprint(u_char *, size_t); 36992761Salfredstatic int show_ioc(const char *, struct svr4_strioctl *); 37092761Salfredstatic int show_strbuf(struct svr4_strbuf *); 37192761Salfredstatic void show_msg(const char *, int, struct svr4_strbuf *, 37292761Salfred struct svr4_strbuf *, int); 37343412Snewton 37443412Snewtonstatic void 37543412Snewtonbufprint(buf, len) 37643412Snewton u_char *buf; 37743412Snewton size_t len; 37843412Snewton{ 37943412Snewton size_t i; 38043412Snewton 38143412Snewton uprintf("\n\t"); 38243412Snewton for (i = 0; i < len; i++) { 38343412Snewton uprintf("%x ", buf[i]); 38443412Snewton if (i && (i % 16) == 0) 38543412Snewton uprintf("\n\t"); 38643412Snewton } 38743412Snewton} 38843412Snewton 38943412Snewtonstatic int 39043412Snewtonshow_ioc(str, ioc) 39143412Snewton const char *str; 39243412Snewton struct svr4_strioctl *ioc; 39343412Snewton{ 394121275Stjr u_char *ptr = NULL; 395121275Stjr int len; 39643412Snewton int error; 39743412Snewton 398121275Stjr len = ioc->len; 399121275Stjr if (len > 1024) 400121275Stjr len = 1024; 401121275Stjr 402121275Stjr if (len > 0) { 403121275Stjr ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK); 404121275Stjr if ((error = copyin(ioc->buf, ptr, len)) != 0) { 405121275Stjr free((char *) ptr, M_TEMP); 406121275Stjr return error; 407121275Stjr } 408121275Stjr } 409121275Stjr 41043412Snewton uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ", 41143412Snewton str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf); 41243412Snewton 413121275Stjr if (ptr != NULL) 414121275Stjr bufprint(ptr, len); 41543412Snewton 41643412Snewton uprintf("}\n"); 41743412Snewton 418121275Stjr if (ptr != NULL) 419121275Stjr free((char *) ptr, M_TEMP); 42043412Snewton return 0; 42143412Snewton} 42243412Snewton 42343412Snewton 42443412Snewtonstatic int 42543412Snewtonshow_strbuf(str) 42643412Snewton struct svr4_strbuf *str; 42743412Snewton{ 42843412Snewton int error; 42943412Snewton u_char *ptr = NULL; 43043412Snewton int maxlen = str->maxlen; 43143412Snewton int len = str->len; 43243412Snewton 433121275Stjr if (maxlen > 8192) 434121275Stjr maxlen = 8192; 435121275Stjr 43643412Snewton if (maxlen < 0) 43743412Snewton maxlen = 0; 43843412Snewton 43943412Snewton if (len >= maxlen) 44043412Snewton len = maxlen; 44143412Snewton 44243412Snewton if (len > 0) { 443111119Simp ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK); 44443412Snewton 44543412Snewton if ((error = copyin(str->buf, ptr, len)) != 0) { 44643412Snewton free((char *) ptr, M_TEMP); 44743412Snewton return error; 44843412Snewton } 44943412Snewton } 45043412Snewton 45143412Snewton uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf); 45243412Snewton 45343412Snewton if (ptr) 45443412Snewton bufprint(ptr, len); 45543412Snewton 45643412Snewton uprintf("]}"); 45743412Snewton 45843412Snewton if (ptr) 45943412Snewton free((char *) ptr, M_TEMP); 46043412Snewton 46143412Snewton return 0; 46243412Snewton} 46343412Snewton 46443412Snewton 46543412Snewtonstatic void 46643412Snewtonshow_msg(str, fd, ctl, dat, flags) 46743412Snewton const char *str; 46843412Snewton int fd; 46943412Snewton struct svr4_strbuf *ctl; 47043412Snewton struct svr4_strbuf *dat; 47143412Snewton int flags; 47243412Snewton{ 47343412Snewton struct svr4_strbuf buf; 47443412Snewton int error; 47543412Snewton 47643412Snewton uprintf("%s(%d", str, fd); 47743412Snewton if (ctl != NULL) { 47843412Snewton if ((error = copyin(ctl, &buf, sizeof(buf))) != 0) 47943412Snewton return; 48043412Snewton show_strbuf(&buf); 48143412Snewton } 48243412Snewton else 48343412Snewton uprintf(", NULL"); 48443412Snewton 48543412Snewton if (dat != NULL) { 48643412Snewton if ((error = copyin(dat, &buf, sizeof(buf))) != 0) 48743412Snewton return; 48843412Snewton show_strbuf(&buf); 48943412Snewton } 49043412Snewton else 49143412Snewton uprintf(", NULL"); 49243412Snewton 49343412Snewton uprintf(", %x);\n", flags); 49443412Snewton} 49543412Snewton 49643412Snewton#endif /* DEBUG_SVR4 */ 49743412Snewton 49843412Snewton/* 49943412Snewton * We are faced with an interesting situation. On svr4 unix sockets 50043412Snewton * are really pipes. But we really have sockets, and we might as 50143412Snewton * well use them. At the point where svr4 calls TI_BIND, it has 50243412Snewton * already created a named pipe for the socket using mknod(2). 50343412Snewton * We need to create a socket with the same name when we bind, 50443412Snewton * so we need to remove the pipe before, otherwise we'll get address 50543412Snewton * already in use. So we *carefully* remove the pipe, to avoid 50643412Snewton * using this as a random file removal tool. We use system calls 50743412Snewton * to avoid code duplication. 50843412Snewton */ 50943412Snewtonstatic int 51083366Sjulianclean_pipe(td, path) 51183366Sjulian struct thread *td; 51243412Snewton const char *path; 51343412Snewton{ 51443412Snewton struct lstat_args la; 51543412Snewton struct unlink_args ua; 51643412Snewton struct stat st; 51743412Snewton int error; 51843412Snewton caddr_t sg = stackgap_init(); 51943412Snewton size_t l = strlen(path) + 1; 52043412Snewton void *tpath; 52143412Snewton 522121275Stjr if ((tpath = stackgap_alloc(&sg, l)) == NULL) 523121275Stjr return ENAMETOOLONG; 524107849Salfred la.ub = stackgap_alloc(&sg, sizeof(struct stat)); 52543412Snewton 52643412Snewton if ((error = copyout(path, tpath, l)) != 0) 52743412Snewton return error; 52843412Snewton 529107849Salfred la.path = tpath; 53043412Snewton 53183366Sjulian if ((error = lstat(td, &la)) != 0) 53243412Snewton return 0; 53343412Snewton 534107849Salfred if ((error = copyin(la.ub, &st, sizeof(st))) != 0) 53543412Snewton return 0; 53643412Snewton 53743412Snewton /* 53843412Snewton * Make sure we are dealing with a mode 0 named pipe. 53943412Snewton */ 54043412Snewton if ((st.st_mode & S_IFMT) != S_IFIFO) 54143412Snewton return 0; 54243412Snewton 54343412Snewton if ((st.st_mode & ALLPERMS) != 0) 54443412Snewton return 0; 54543412Snewton 546107849Salfred ua.path = la.path; 54743412Snewton 54883366Sjulian if ((error = unlink(td, &ua)) != 0) { 54943412Snewton DPRINTF(("clean_pipe: unlink failed %d\n", error)); 55043412Snewton return error; 55143412Snewton } 55243412Snewton 55343412Snewton return 0; 55443412Snewton} 55543412Snewton 55643412Snewton 55743412Snewtonstatic void 55843412Snewtonsockaddr_to_netaddr_in(sc, sain) 55943412Snewton struct svr4_strmcmd *sc; 56043412Snewton const struct sockaddr_in *sain; 56143412Snewton{ 56243412Snewton struct svr4_netaddr_in *na; 56343412Snewton na = SVR4_ADDROF(sc); 56443412Snewton 56543412Snewton na->family = sain->sin_family; 56643412Snewton na->port = sain->sin_port; 56743412Snewton na->addr = sain->sin_addr.s_addr; 56843412Snewton DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port, 56943412Snewton na->addr)); 57043412Snewton} 57143412Snewton 57243412Snewton 57343412Snewtonstatic void 57443412Snewtonsockaddr_to_netaddr_un(sc, saun) 57543412Snewton struct svr4_strmcmd *sc; 57643412Snewton const struct sockaddr_un *saun; 57743412Snewton{ 57843412Snewton struct svr4_netaddr_un *na; 57943412Snewton char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 - 58043412Snewton sizeof(*sc); 58143412Snewton const char *src; 58243412Snewton 58343412Snewton na = SVR4_ADDROF(sc); 58443412Snewton na->family = saun->sun_family; 58543412Snewton for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; ) 58643412Snewton if (dst == edst) 58743412Snewton break; 58843412Snewton DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path)); 58943412Snewton} 59043412Snewton 59143412Snewton 59243412Snewtonstatic void 59343412Snewtonnetaddr_to_sockaddr_in(sain, sc) 59443412Snewton struct sockaddr_in *sain; 59543412Snewton const struct svr4_strmcmd *sc; 59643412Snewton{ 59743412Snewton const struct svr4_netaddr_in *na; 59843412Snewton 59943412Snewton 60043412Snewton na = SVR4_C_ADDROF(sc); 60143412Snewton memset(sain, 0, sizeof(*sain)); 60243412Snewton sain->sin_len = sizeof(*sain); 60343412Snewton sain->sin_family = na->family; 60443412Snewton sain->sin_port = na->port; 60543412Snewton sain->sin_addr.s_addr = na->addr; 60643412Snewton DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family, 60743412Snewton sain->sin_port, sain->sin_addr.s_addr)); 60843412Snewton} 60943412Snewton 61043412Snewton 61143412Snewtonstatic void 61243412Snewtonnetaddr_to_sockaddr_un(saun, sc) 61343412Snewton struct sockaddr_un *saun; 61443412Snewton const struct svr4_strmcmd *sc; 61543412Snewton{ 61643412Snewton const struct svr4_netaddr_un *na; 61743412Snewton char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1]; 61843412Snewton const char *src; 61943412Snewton 62043412Snewton na = SVR4_C_ADDROF(sc); 62143412Snewton memset(saun, 0, sizeof(*saun)); 62243412Snewton saun->sun_family = na->family; 62343412Snewton for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; ) 62443412Snewton if (dst == edst) 62543412Snewton break; 62643412Snewton saun->sun_len = dst - saun->sun_path; 62743412Snewton DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family, 62843412Snewton saun->sun_path)); 62943412Snewton} 63043412Snewton 63143412Snewton 63243412Snewtonstatic void 63343412Snewtongetparm(fp, pa) 63443412Snewton struct file *fp; 63543412Snewton struct svr4_si_sockparms *pa; 63643412Snewton{ 63789306Salfred struct svr4_strm *st; 63889306Salfred struct socket *so; 63943412Snewton 64089306Salfred st = svr4_stream_get(fp); 64143412Snewton if (st == NULL) 64243412Snewton return; 64343412Snewton 644109153Sdillon so = fp->f_data; 64589306Salfred 64643412Snewton pa->family = st->s_family; 64743412Snewton 64843412Snewton switch (so->so_type) { 64943412Snewton case SOCK_DGRAM: 65043412Snewton pa->type = SVR4_T_CLTS; 65143412Snewton pa->protocol = IPPROTO_UDP; 65243412Snewton DPRINTF(("getparm(dgram)\n")); 65343412Snewton return; 65443412Snewton 65543412Snewton case SOCK_STREAM: 65643412Snewton pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */ 65743412Snewton pa->protocol = IPPROTO_IP; 65843412Snewton DPRINTF(("getparm(stream)\n")); 65943412Snewton return; 66043412Snewton 66143412Snewton case SOCK_RAW: 66243412Snewton pa->type = SVR4_T_CLTS; 66343412Snewton pa->protocol = IPPROTO_RAW; 66443412Snewton DPRINTF(("getparm(raw)\n")); 66543412Snewton return; 66643412Snewton 66743412Snewton default: 66843412Snewton pa->type = 0; 66943412Snewton pa->protocol = 0; 67043412Snewton DPRINTF(("getparm(type %d?)\n", so->so_type)); 67143412Snewton return; 67243412Snewton } 67343412Snewton} 67443412Snewton 67543412Snewton 67643412Snewtonstatic int 67783366Sjuliansi_ogetudata(fp, fd, ioc, td) 67843412Snewton struct file *fp; 67943412Snewton int fd; 68043412Snewton struct svr4_strioctl *ioc; 68183366Sjulian struct thread *td; 68243412Snewton{ 68343412Snewton int error; 68443412Snewton struct svr4_si_oudata ud; 68543412Snewton struct svr4_si_sockparms pa; 68643412Snewton 68743412Snewton if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) { 68843412Snewton DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n", 68943412Snewton sizeof(ud), ioc->len)); 69043412Snewton return EINVAL; 69143412Snewton } 69243412Snewton 69343412Snewton if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 69443412Snewton return error; 69543412Snewton 69643412Snewton getparm(fp, &pa); 69743412Snewton 69843412Snewton switch (pa.family) { 69943412Snewton case AF_INET: 70043412Snewton ud.tidusize = 16384; 70143412Snewton ud.addrsize = sizeof(struct svr4_sockaddr_in); 70243412Snewton if (pa.type == SVR4_SOCK_STREAM) 70343412Snewton ud.etsdusize = 1; 70443412Snewton else 70543412Snewton ud.etsdusize = 0; 70643412Snewton break; 70743412Snewton 70843412Snewton case AF_LOCAL: 70943412Snewton ud.tidusize = 65536; 71043412Snewton ud.addrsize = 128; 71143412Snewton ud.etsdusize = 128; 71243412Snewton break; 71343412Snewton 71443412Snewton default: 71543412Snewton DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n", 71643412Snewton pa.family)); 71743412Snewton return ENOSYS; 71843412Snewton } 71943412Snewton 72043412Snewton /* I have no idea what these should be! */ 72143412Snewton ud.optsize = 128; 72243412Snewton ud.tsdusize = 128; 72343412Snewton 72443412Snewton ud.servtype = pa.type; 72543412Snewton 72643412Snewton /* XXX: Fixme */ 72743412Snewton ud.so_state = 0; 72843412Snewton ud.so_options = 0; 72943412Snewton return copyout(&ud, ioc->buf, ioc->len); 73043412Snewton} 73143412Snewton 73243412Snewton 73343412Snewtonstatic int 73483366Sjuliansi_sockparams(fp, fd, ioc, td) 73543412Snewton struct file *fp; 73643412Snewton int fd; 73743412Snewton struct svr4_strioctl *ioc; 73883366Sjulian struct thread *td; 73943412Snewton{ 74043412Snewton struct svr4_si_sockparms pa; 74143412Snewton 74243412Snewton getparm(fp, &pa); 74343412Snewton return copyout(&pa, ioc->buf, sizeof(pa)); 74443412Snewton} 74543412Snewton 74643412Snewton 74743412Snewtonstatic int 74883366Sjuliansi_listen(fp, fd, ioc, td) 74943412Snewton struct file *fp; 75043412Snewton int fd; 75143412Snewton struct svr4_strioctl *ioc; 75283366Sjulian struct thread *td; 75343412Snewton{ 75443412Snewton int error; 75543412Snewton struct svr4_strm *st = svr4_stream_get(fp); 75643412Snewton struct svr4_strmcmd lst; 75743412Snewton struct listen_args la; 75843412Snewton 75943412Snewton if (st == NULL) 76043412Snewton return EINVAL; 76143412Snewton 762121275Stjr if (ioc->len < 0 || ioc->len > sizeof(lst)) 763121275Stjr return EINVAL; 764121275Stjr 76543412Snewton if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0) 76643412Snewton return error; 76743412Snewton 76843412Snewton if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) { 76943412Snewton DPRINTF(("si_listen: bad request %ld\n", lst.cmd)); 77043412Snewton return EINVAL; 77143412Snewton } 77243412Snewton 77343412Snewton /* 77443412Snewton * We are making assumptions again... 77543412Snewton */ 776107849Salfred la.s = fd; 77743412Snewton DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5)); 778107849Salfred la.backlog = 5; 77943412Snewton 78083366Sjulian if ((error = listen(td, &la)) != 0) { 78143412Snewton DPRINTF(("SI_LISTEN: listen failed %d\n", error)); 78243412Snewton return error; 78343412Snewton } 78443412Snewton 78543412Snewton st->s_cmd = SVR4_TI__ACCEPT_WAIT; 78643412Snewton lst.cmd = SVR4_TI_BIND_REPLY; 78743412Snewton 78843412Snewton switch (st->s_family) { 78943412Snewton case AF_INET: 79043412Snewton /* XXX: Fill the length here */ 79143412Snewton break; 79243412Snewton 79343412Snewton case AF_LOCAL: 79443412Snewton lst.len = 140; 79543412Snewton lst.pad[28] = 0x00000000; /* magic again */ 79643412Snewton lst.pad[29] = 0x00000800; /* magic again */ 79743412Snewton lst.pad[30] = 0x80001400; /* magic again */ 79843412Snewton break; 79943412Snewton 80043412Snewton default: 80143412Snewton DPRINTF(("SI_LISTEN: Unsupported address family %d\n", 80243412Snewton st->s_family)); 80343412Snewton return ENOSYS; 80443412Snewton } 80543412Snewton 80643412Snewton 80743412Snewton if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0) 80843412Snewton return error; 80943412Snewton 81043412Snewton return 0; 81143412Snewton} 81243412Snewton 81343412Snewton 81443412Snewtonstatic int 81583366Sjuliansi_getudata(fp, fd, ioc, td) 81643412Snewton struct file *fp; 81743412Snewton int fd; 81843412Snewton struct svr4_strioctl *ioc; 81983366Sjulian struct thread *td; 82043412Snewton{ 82143412Snewton int error; 82243412Snewton struct svr4_si_udata ud; 82343412Snewton 82443412Snewton if (sizeof(ud) != ioc->len) { 82543412Snewton DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n", 82643412Snewton sizeof(ud), ioc->len)); 82743412Snewton return EINVAL; 82843412Snewton } 82943412Snewton 83043412Snewton if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 83143412Snewton return error; 83243412Snewton 83343412Snewton getparm(fp, &ud.sockparms); 83443412Snewton 83543412Snewton switch (ud.sockparms.family) { 83643412Snewton case AF_INET: 83743412Snewton DPRINTF(("getudata_inet\n")); 83843412Snewton ud.tidusize = 16384; 83943412Snewton ud.tsdusize = 16384; 84043412Snewton ud.addrsize = sizeof(struct svr4_sockaddr_in); 84143412Snewton if (ud.sockparms.type == SVR4_SOCK_STREAM) 84243412Snewton ud.etsdusize = 1; 84343412Snewton else 84443412Snewton ud.etsdusize = 0; 84543412Snewton ud.optsize = 0; 84643412Snewton break; 84743412Snewton 84843412Snewton case AF_LOCAL: 84943412Snewton DPRINTF(("getudata_local\n")); 85043412Snewton ud.tidusize = 65536; 85143412Snewton ud.tsdusize = 128; 85243412Snewton ud.addrsize = 128; 85343412Snewton ud.etsdusize = 128; 85443412Snewton ud.optsize = 128; 85543412Snewton break; 85643412Snewton 85743412Snewton default: 85843412Snewton DPRINTF(("SI_GETUDATA: Unsupported address family %d\n", 85943412Snewton ud.sockparms.family)); 86043412Snewton return ENOSYS; 86143412Snewton } 86243412Snewton 86343412Snewton 86443412Snewton ud.servtype = ud.sockparms.type; 86543412Snewton DPRINTF(("ud.servtype = %d\n", ud.servtype)); 86643412Snewton /* XXX: Fixme */ 86743412Snewton ud.so_state = 0; 86843412Snewton ud.so_options = 0; 86943412Snewton return copyout(&ud, ioc->buf, sizeof(ud)); 87043412Snewton} 87143412Snewton 87243412Snewton 87343412Snewtonstatic int 87483366Sjuliansi_shutdown(fp, fd, ioc, td) 87543412Snewton struct file *fp; 87643412Snewton int fd; 87743412Snewton struct svr4_strioctl *ioc; 87883366Sjulian struct thread *td; 87943412Snewton{ 88043412Snewton int error; 88143412Snewton struct shutdown_args ap; 88243412Snewton 883107849Salfred if (ioc->len != sizeof(ap.how)) { 88443412Snewton DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n", 885107849Salfred sizeof(ap.how), ioc->len)); 88643412Snewton return EINVAL; 88743412Snewton } 88843412Snewton 889107849Salfred if ((error = copyin(ioc->buf, &ap.how, ioc->len)) != 0) 89043412Snewton return error; 89143412Snewton 892107849Salfred ap.s = fd; 89343412Snewton 89483366Sjulian return shutdown(td, &ap); 89543412Snewton} 89643412Snewton 89743412Snewton 89843412Snewtonstatic int 89983366Sjuliansockmod(fp, fd, ioc, td) 90043412Snewton struct file *fp; 90143412Snewton int fd; 90243412Snewton struct svr4_strioctl *ioc; 90383366Sjulian struct thread *td; 90443412Snewton{ 90543412Snewton switch (ioc->cmd) { 90643412Snewton case SVR4_SI_OGETUDATA: 90743412Snewton DPRINTF(("SI_OGETUDATA\n")); 90883366Sjulian return si_ogetudata(fp, fd, ioc, td); 90943412Snewton 91043412Snewton case SVR4_SI_SHUTDOWN: 91143412Snewton DPRINTF(("SI_SHUTDOWN\n")); 91283366Sjulian return si_shutdown(fp, fd, ioc, td); 91343412Snewton 91443412Snewton case SVR4_SI_LISTEN: 91543412Snewton DPRINTF(("SI_LISTEN\n")); 91683366Sjulian return si_listen(fp, fd, ioc, td); 91743412Snewton 91843412Snewton case SVR4_SI_SETMYNAME: 91943412Snewton DPRINTF(("SI_SETMYNAME\n")); 92043412Snewton return 0; 92143412Snewton 92243412Snewton case SVR4_SI_SETPEERNAME: 92343412Snewton DPRINTF(("SI_SETPEERNAME\n")); 92443412Snewton return 0; 92543412Snewton 92643412Snewton case SVR4_SI_GETINTRANSIT: 92743412Snewton DPRINTF(("SI_GETINTRANSIT\n")); 92843412Snewton return 0; 92943412Snewton 93043412Snewton case SVR4_SI_TCL_LINK: 93143412Snewton DPRINTF(("SI_TCL_LINK\n")); 93243412Snewton return 0; 93343412Snewton 93443412Snewton case SVR4_SI_TCL_UNLINK: 93543412Snewton DPRINTF(("SI_TCL_UNLINK\n")); 93643412Snewton return 0; 93743412Snewton 93843412Snewton case SVR4_SI_SOCKPARAMS: 93943412Snewton DPRINTF(("SI_SOCKPARAMS\n")); 94083366Sjulian return si_sockparams(fp, fd, ioc, td); 94143412Snewton 94243412Snewton case SVR4_SI_GETUDATA: 94343412Snewton DPRINTF(("SI_GETUDATA\n")); 94483366Sjulian return si_getudata(fp, fd, ioc, td); 94543412Snewton 94643412Snewton default: 94743412Snewton DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd)); 94843412Snewton return 0; 94943412Snewton 95043412Snewton } 95143412Snewton} 95243412Snewton 95343412Snewton 95443412Snewtonstatic int 95583366Sjulianti_getinfo(fp, fd, ioc, td) 95643412Snewton struct file *fp; 95743412Snewton int fd; 95843412Snewton struct svr4_strioctl *ioc; 95983366Sjulian struct thread *td; 96043412Snewton{ 96143412Snewton int error; 96243412Snewton struct svr4_infocmd info; 96343412Snewton 96443412Snewton memset(&info, 0, sizeof(info)); 96543412Snewton 966121275Stjr if (ioc->len < 0 || ioc->len > sizeof(info)) 967121275Stjr return EINVAL; 968121275Stjr 96943412Snewton if ((error = copyin(ioc->buf, &info, ioc->len)) != 0) 97043412Snewton return error; 97143412Snewton 97243412Snewton if (info.cmd != SVR4_TI_INFO_REQUEST) 97343412Snewton return EINVAL; 97443412Snewton 97543412Snewton info.cmd = SVR4_TI_INFO_REPLY; 97643412Snewton info.tsdu = 0; 97743412Snewton info.etsdu = 1; 97843412Snewton info.cdata = -2; 97943412Snewton info.ddata = -2; 98043412Snewton info.addr = 16; 98143412Snewton info.opt = -1; 98243412Snewton info.tidu = 16384; 98343412Snewton info.serv = 2; 98443412Snewton info.current = 0; 98543412Snewton info.provider = 2; 98643412Snewton 98743412Snewton ioc->len = sizeof(info); 98843412Snewton if ((error = copyout(&info, ioc->buf, ioc->len)) != 0) 98943412Snewton return error; 99043412Snewton 99143412Snewton return 0; 99243412Snewton} 99343412Snewton 99443412Snewton 99543412Snewtonstatic int 99683366Sjulianti_bind(fp, fd, ioc, td) 99743412Snewton struct file *fp; 99843412Snewton int fd; 99943412Snewton struct svr4_strioctl *ioc; 100083366Sjulian struct thread *td; 100143412Snewton{ 100243412Snewton int error; 100343412Snewton struct svr4_strm *st = svr4_stream_get(fp); 100443412Snewton struct sockaddr_in sain; 100543412Snewton struct sockaddr_un saun; 100643412Snewton caddr_t sg; 100743412Snewton void *skp, *sup = NULL; 100843412Snewton int sasize; 100943412Snewton struct svr4_strmcmd bnd; 101043412Snewton struct bind_args ba; 101143412Snewton 101243412Snewton if (st == NULL) { 101343412Snewton DPRINTF(("ti_bind: bad file descriptor\n")); 101443412Snewton return EINVAL; 101543412Snewton } 101643412Snewton 1017121275Stjr if (ioc->len < 0 || ioc->len > sizeof(bnd)) 1018121275Stjr return EINVAL; 1019121275Stjr 102043412Snewton if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0) 102143412Snewton return error; 102243412Snewton 102343412Snewton if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) { 102443412Snewton DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd)); 102543412Snewton return EINVAL; 102643412Snewton } 102743412Snewton 102843412Snewton switch (st->s_family) { 102943412Snewton case AF_INET: 103043412Snewton skp = &sain; 103143412Snewton sasize = sizeof(sain); 103243412Snewton 103343412Snewton if (bnd.offs == 0) 103443412Snewton goto reply; 103543412Snewton 103643412Snewton netaddr_to_sockaddr_in(&sain, &bnd); 103743412Snewton 103843412Snewton DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n", 103943412Snewton sain.sin_family, sain.sin_port, 104043412Snewton sain.sin_addr.s_addr)); 104143412Snewton break; 104243412Snewton 104343412Snewton case AF_LOCAL: 104443412Snewton skp = &saun; 104543412Snewton sasize = sizeof(saun); 104643412Snewton if (bnd.offs == 0) 104743412Snewton goto reply; 104843412Snewton 104943412Snewton netaddr_to_sockaddr_un(&saun, &bnd); 105043412Snewton 105143412Snewton if (saun.sun_path[0] == '\0') 105243412Snewton goto reply; 105343412Snewton 105443412Snewton DPRINTF(("TI_BIND: fam %d, path %s\n", 105543412Snewton saun.sun_family, saun.sun_path)); 105643412Snewton 105783366Sjulian if ((error = clean_pipe(td, saun.sun_path)) != 0) 105843412Snewton return error; 105943412Snewton 106043412Snewton bnd.pad[28] = 0x00001000; /* magic again */ 106143412Snewton break; 106243412Snewton 106343412Snewton default: 106443412Snewton DPRINTF(("TI_BIND: Unsupported address family %d\n", 106543412Snewton st->s_family)); 106643412Snewton return ENOSYS; 106743412Snewton } 106843412Snewton 106943412Snewton sg = stackgap_init(); 107043412Snewton sup = stackgap_alloc(&sg, sasize); 107143412Snewton 107243412Snewton if ((error = copyout(skp, sup, sasize)) != 0) 107343412Snewton return error; 107443412Snewton 1075107849Salfred ba.s = fd; 107643412Snewton DPRINTF(("TI_BIND: fileno %d\n", fd)); 1077107849Salfred ba.name = (void *) sup; 1078107849Salfred ba.namelen = sasize; 107943412Snewton 108083366Sjulian if ((error = bind(td, &ba)) != 0) { 108143412Snewton DPRINTF(("TI_BIND: bind failed %d\n", error)); 108243412Snewton return error; 108343412Snewton } 108443412Snewton 108543412Snewtonreply: 108643412Snewton if (sup == NULL) { 108743412Snewton memset(&bnd, 0, sizeof(bnd)); 108843412Snewton bnd.len = sasize + 4; 108943412Snewton bnd.offs = 0x10; /* XXX */ 109043412Snewton } 109143412Snewton 109243412Snewton bnd.cmd = SVR4_TI_BIND_REPLY; 109343412Snewton 109443412Snewton if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0) 109543412Snewton return error; 109643412Snewton 109743412Snewton return 0; 109843412Snewton} 109943412Snewton 110043412Snewton 110143412Snewtonstatic int 110283366Sjuliantimod(fp, fd, ioc, td) 110343412Snewton struct file *fp; 110443412Snewton int fd; 110543412Snewton struct svr4_strioctl *ioc; 110683366Sjulian struct thread *td; 110743412Snewton{ 110843412Snewton switch (ioc->cmd) { 110943412Snewton case SVR4_TI_GETINFO: 111043412Snewton DPRINTF(("TI_GETINFO\n")); 111183366Sjulian return ti_getinfo(fp, fd, ioc, td); 111243412Snewton 111343412Snewton case SVR4_TI_OPTMGMT: 111443412Snewton DPRINTF(("TI_OPTMGMT\n")); 111543412Snewton return 0; 111643412Snewton 111743412Snewton case SVR4_TI_BIND: 111843412Snewton DPRINTF(("TI_BIND\n")); 111983366Sjulian return ti_bind(fp, fd, ioc, td); 112043412Snewton 112143412Snewton case SVR4_TI_UNBIND: 112243412Snewton DPRINTF(("TI_UNBIND\n")); 112343412Snewton return 0; 112443412Snewton 112543412Snewton default: 112643412Snewton DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd)); 112743412Snewton return 0; 112843412Snewton } 112943412Snewton} 113043412Snewton 113143412Snewton 113243412Snewtonint 113383366Sjuliansvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat) 113443412Snewton struct file *fp; 113583366Sjulian struct thread *td; 113643412Snewton register_t *retval; 113743412Snewton int fd; 113843412Snewton u_long cmd; 113943412Snewton caddr_t dat; 114043412Snewton{ 114143412Snewton struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat; 114243412Snewton struct svr4_strm *st = svr4_stream_get(fp); 114343412Snewton int error; 114443412Snewton void *skp, *sup; 114543412Snewton struct sockaddr_in sain; 114643412Snewton struct sockaddr_un saun; 114743412Snewton struct svr4_strmcmd sc; 1148121275Stjr int sasize, oldsasize; 114943412Snewton caddr_t sg; 115043412Snewton int *lenp; 115143412Snewton 115243412Snewton DPRINTF(("svr4_stream_ti_ioctl\n")); 115343412Snewton 115443412Snewton if (st == NULL) 115543412Snewton return EINVAL; 115643412Snewton 115743412Snewton sc.offs = 0x10; 115843412Snewton 115943412Snewton if ((error = copyin(sub, &skb, sizeof(skb))) != 0) { 116043412Snewton DPRINTF(("ti_ioctl: error copying in strbuf\n")); 116143412Snewton return error; 116243412Snewton } 116343412Snewton 116443412Snewton switch (st->s_family) { 116543412Snewton case AF_INET: 116643412Snewton skp = &sain; 116743412Snewton sasize = sizeof(sain); 116843412Snewton break; 116943412Snewton 117043412Snewton case AF_LOCAL: 117143412Snewton skp = &saun; 117243412Snewton sasize = sizeof(saun); 117343412Snewton break; 117443412Snewton 117543412Snewton default: 117643412Snewton DPRINTF(("ti_ioctl: Unsupported address family %d\n", 117743412Snewton st->s_family)); 117843412Snewton return ENOSYS; 117943412Snewton } 118043412Snewton 118143412Snewton sg = stackgap_init(); 118243412Snewton sup = stackgap_alloc(&sg, sasize); 118343412Snewton lenp = stackgap_alloc(&sg, sizeof(*lenp)); 118443412Snewton 118543412Snewton if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) { 118643412Snewton DPRINTF(("ti_ioctl: error copying out lenp\n")); 118743412Snewton return error; 118843412Snewton } 118943412Snewton 119043412Snewton switch (cmd) { 119143412Snewton case SVR4_TI_GETMYNAME: 119243412Snewton DPRINTF(("TI_GETMYNAME\n")); 119343412Snewton { 119443412Snewton struct getsockname_args ap; 1195107849Salfred ap.fdes = fd; 1196107849Salfred ap.asa = sup; 1197107849Salfred ap.alen = lenp; 119883366Sjulian if ((error = getsockname(td, &ap)) != 0) { 119943412Snewton DPRINTF(("ti_ioctl: getsockname error\n")); 120043412Snewton return error; 120143412Snewton } 120243412Snewton } 120343412Snewton break; 120443412Snewton 120543412Snewton case SVR4_TI_GETPEERNAME: 120643412Snewton DPRINTF(("TI_GETPEERNAME\n")); 120743412Snewton { 120843412Snewton struct getpeername_args ap; 1209107849Salfred ap.fdes = fd; 1210107849Salfred ap.asa = sup; 1211107849Salfred ap.alen = lenp; 121283366Sjulian if ((error = getpeername(td, &ap)) != 0) { 121343412Snewton DPRINTF(("ti_ioctl: getpeername error\n")); 121443412Snewton return error; 121543412Snewton } 121643412Snewton } 121743412Snewton break; 121843412Snewton 121943412Snewton case SVR4_TI_SETMYNAME: 122043412Snewton DPRINTF(("TI_SETMYNAME\n")); 122143412Snewton return 0; 122243412Snewton 122343412Snewton case SVR4_TI_SETPEERNAME: 122443412Snewton DPRINTF(("TI_SETPEERNAME\n")); 122543412Snewton return 0; 122643412Snewton default: 122743412Snewton DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd)); 122843412Snewton return ENOSYS; 122943412Snewton } 123043412Snewton 123143412Snewton if ((error = copyin(sup, skp, sasize)) != 0) { 123243412Snewton DPRINTF(("ti_ioctl: error copying in socket data\n")); 123343412Snewton return error; 123443412Snewton } 123543412Snewton 1236121275Stjr oldsasize = sasize; 1237121275Stjr 123843412Snewton if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) { 123943412Snewton DPRINTF(("ti_ioctl: error copying in socket size\n")); 124043412Snewton return error; 124143412Snewton } 124243412Snewton 1243121275Stjr if (sasize < 0 || sasize > oldsasize) 1244121275Stjr return EINVAL; 1245121275Stjr 124643412Snewton switch (st->s_family) { 124743412Snewton case AF_INET: 124843412Snewton sockaddr_to_netaddr_in(&sc, &sain); 124943412Snewton skb.len = sasize; 125043412Snewton break; 125143412Snewton 125243412Snewton case AF_LOCAL: 125343412Snewton sockaddr_to_netaddr_un(&sc, &saun); 125443412Snewton skb.len = sasize + 4; 125543412Snewton break; 125643412Snewton 125743412Snewton default: 125843412Snewton return ENOSYS; 125943412Snewton } 126043412Snewton 126143412Snewton 126243412Snewton if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) { 126343412Snewton DPRINTF(("ti_ioctl: error copying out socket data\n")); 126443412Snewton return error; 126543412Snewton } 126643412Snewton 126743412Snewton 126843412Snewton if ((error = copyout(&skb, sub, sizeof(skb))) != 0) { 126943412Snewton DPRINTF(("ti_ioctl: error copying out strbuf\n")); 127043412Snewton return error; 127143412Snewton } 127243412Snewton 127343412Snewton return error; 127443412Snewton} 127543412Snewton 127643412Snewton 127743412Snewton 127843412Snewton 127943412Snewtonstatic int 128083366Sjuliani_nread(fp, td, retval, fd, cmd, dat) 128143412Snewton struct file *fp; 128283366Sjulian struct thread *td; 128343412Snewton register_t *retval; 128443412Snewton int fd; 128543412Snewton u_long cmd; 128643412Snewton caddr_t dat; 128743412Snewton{ 128843412Snewton int error; 128943412Snewton int nread = 0; 129043412Snewton 129143412Snewton /* 129243412Snewton * We are supposed to return the message length in nread, and the 129343412Snewton * number of messages in retval. We don't have the notion of number 129443412Snewton * of stream messages, so we just find out if we have any bytes waiting 129543412Snewton * for us, and if we do, then we assume that we have at least one 129643412Snewton * message waiting for us. 129743412Snewton */ 1298102003Srwatson if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td->td_ucred, 1299102003Srwatson td)) != 0) 130043412Snewton return error; 130143412Snewton 130243412Snewton if (nread != 0) 130343412Snewton *retval = 1; 130443412Snewton else 130543412Snewton *retval = 0; 130643412Snewton 130743412Snewton return copyout(&nread, dat, sizeof(nread)); 130843412Snewton} 130943412Snewton 131043412Snewtonstatic int 131183366Sjuliani_fdinsert(fp, td, retval, fd, cmd, dat) 131243412Snewton struct file *fp; 131383366Sjulian struct thread *td; 131443412Snewton register_t *retval; 131543412Snewton int fd; 131643412Snewton u_long cmd; 131743412Snewton caddr_t dat; 131843412Snewton{ 131943412Snewton /* 132043412Snewton * Major hack again here. We assume that we are using this to 132143412Snewton * implement accept(2). If that is the case, we have already 132243412Snewton * called accept, and we have stored the file descriptor in 132343412Snewton * afd. We find the file descriptor that the code wants to use 132443412Snewton * in fd insert, and then we dup2() our accepted file descriptor 132543412Snewton * to it. 132643412Snewton */ 132743412Snewton int error; 132843412Snewton struct svr4_strm *st = svr4_stream_get(fp); 132943412Snewton struct svr4_strfdinsert fdi; 133043412Snewton struct dup2_args d2p; 133143412Snewton struct close_args clp; 133243412Snewton 133343412Snewton if (st == NULL) { 133443412Snewton DPRINTF(("fdinsert: bad file type\n")); 133543412Snewton return EINVAL; 133643412Snewton } 133743412Snewton 133843412Snewton if (st->s_afd == -1) { 133943412Snewton DPRINTF(("fdinsert: accept fd not found\n")); 134043412Snewton return ENOENT; 134143412Snewton } 134243412Snewton 134343412Snewton if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) { 134443412Snewton DPRINTF(("fdinsert: copyin failed %d\n", error)); 134543412Snewton return error; 134643412Snewton } 134743412Snewton 1348107849Salfred d2p.from = st->s_afd; 1349107849Salfred d2p.to = fdi.fd; 135043412Snewton 135183366Sjulian if ((error = dup2(td, &d2p)) != 0) { 135243412Snewton DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n", 135343412Snewton st->s_afd, fdi.fd, error)); 135443412Snewton return error; 135543412Snewton } 135643412Snewton 1357107849Salfred clp.fd = st->s_afd; 135843412Snewton 135983366Sjulian if ((error = close(td, &clp)) != 0) { 136043412Snewton DPRINTF(("fdinsert: close(%d) failed %d\n", 136143412Snewton st->s_afd, error)); 136243412Snewton return error; 136343412Snewton } 136443412Snewton 136543412Snewton st->s_afd = -1; 136643412Snewton 136743412Snewton *retval = 0; 136843412Snewton return 0; 136943412Snewton} 137043412Snewton 137143412Snewton 137243412Snewtonstatic int 137383366Sjulian_i_bind_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 mkfifo_args ap; 138243412Snewton 138343412Snewton /* 138443412Snewton * This is a supposed to be a kernel and library only ioctl. 138543412Snewton * It gets called before ti_bind, when we have a unix 138643412Snewton * socket, to physically create the socket transport and 138743412Snewton * ``reserve'' it. I don't know how this get reserved inside 138843412Snewton * the kernel, but we are going to create it nevertheless. 138943412Snewton */ 1390107849Salfred ap.path = dat; 1391107849Salfred ap.mode = S_IFIFO; 139243412Snewton 139383366Sjulian return mkfifo(td, &ap); 139443412Snewton} 139543412Snewton 139643412Snewtonstatic int 139783366Sjulian_i_rele_rsvd(fp, td, retval, fd, cmd, dat) 139843412Snewton struct file *fp; 139983366Sjulian struct thread *td; 140043412Snewton register_t *retval; 140143412Snewton int fd; 140243412Snewton u_long cmd; 140343412Snewton caddr_t dat; 140443412Snewton{ 140543412Snewton struct unlink_args ap; 140643412Snewton 140743412Snewton /* 140843412Snewton * This is a supposed to be a kernel and library only ioctl. 140943412Snewton * I guess it is supposed to release the socket. 141043412Snewton */ 1411107849Salfred ap.path = dat; 141243412Snewton 141383366Sjulian return unlink(td, &ap); 141443412Snewton} 141543412Snewton 141643412Snewtonstatic int 141783366Sjuliani_str(fp, td, retval, fd, cmd, dat) 141843412Snewton struct file *fp; 141983366Sjulian struct thread *td; 142043412Snewton register_t *retval; 142143412Snewton int fd; 142243412Snewton u_long cmd; 142343412Snewton caddr_t dat; 142443412Snewton{ 142543412Snewton int error; 142643412Snewton struct svr4_strioctl ioc; 142743412Snewton 142843412Snewton if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0) 142943412Snewton return error; 143043412Snewton 143143412Snewton#ifdef DEBUG_SVR4 143243412Snewton if ((error = show_ioc(">", &ioc)) != 0) 143343412Snewton return error; 143443412Snewton#endif /* DEBUG_SVR4 */ 143543412Snewton 143643412Snewton switch (ioc.cmd & 0xff00) { 143743412Snewton case SVR4_SIMOD: 143883366Sjulian if ((error = sockmod(fp, fd, &ioc, td)) != 0) 143943412Snewton return error; 144043412Snewton break; 144143412Snewton 144243412Snewton case SVR4_TIMOD: 144383366Sjulian if ((error = timod(fp, fd, &ioc, td)) != 0) 144443412Snewton return error; 144543412Snewton break; 144643412Snewton 144743412Snewton default: 144843412Snewton DPRINTF(("Unimplemented module %c %ld\n", 144943412Snewton (char) (cmd >> 8), cmd & 0xff)); 145043412Snewton return 0; 145143412Snewton } 145243412Snewton 145343412Snewton#ifdef DEBUG_SVR4 145443412Snewton if ((error = show_ioc("<", &ioc)) != 0) 145543412Snewton return error; 145643412Snewton#endif /* DEBUG_SVR4 */ 145743412Snewton return copyout(&ioc, dat, sizeof(ioc)); 145843412Snewton} 145943412Snewton 146043412Snewtonstatic int 146183366Sjuliani_setsig(fp, td, retval, fd, cmd, dat) 146243412Snewton struct file *fp; 146383366Sjulian struct thread *td; 146443412Snewton register_t *retval; 146543412Snewton int fd; 146643412Snewton u_long cmd; 146743412Snewton caddr_t dat; 146843412Snewton{ 146943412Snewton /* 147043412Snewton * This is the best we can do for now; we cannot generate 147143412Snewton * signals only for specific events so the signal mask gets 147243412Snewton * ignored; we save it just to pass it to a possible I_GETSIG... 147343412Snewton * 147443412Snewton * We alse have to fix the O_ASYNC fcntl bit, so the 147543412Snewton * process will get SIGPOLLs. 147643412Snewton */ 147743412Snewton int error; 147843412Snewton register_t oflags, flags; 147943412Snewton struct svr4_strm *st = svr4_stream_get(fp); 148043412Snewton 148143412Snewton if (st == NULL) { 148243412Snewton DPRINTF(("i_setsig: bad file descriptor\n")); 148343412Snewton return EINVAL; 148443412Snewton } 148543412Snewton /* get old status flags */ 1486134266Sjhb error = kern_fcntl(td, fd, F_GETFL, 0); 1487134266Sjhb if (error) 1488134266Sjhb return (error); 148943412Snewton 149083366Sjulian oflags = td->td_retval[0]; 149143412Snewton 149243412Snewton /* update the flags */ 149343412Snewton if (dat != NULL) { 149443412Snewton int mask; 149543412Snewton 149643412Snewton flags = oflags | O_ASYNC; 149743412Snewton if ((error = copyin(dat, &mask, sizeof(mask))) != 0) { 149843412Snewton DPRINTF(("i_setsig: bad eventmask pointer\n")); 149943412Snewton return error; 150043412Snewton } 150143412Snewton if (mask & SVR4_S_ALLMASK) { 150243412Snewton DPRINTF(("i_setsig: bad eventmask data %x\n", mask)); 150343412Snewton return EINVAL; 150443412Snewton } 150543412Snewton st->s_eventmask = mask; 150643412Snewton } 150743412Snewton else { 150843412Snewton flags = oflags & ~O_ASYNC; 150943412Snewton st->s_eventmask = 0; 151043412Snewton } 151143412Snewton 151243412Snewton /* set the new flags, if changed */ 151343412Snewton if (flags != oflags) { 1514134266Sjhb error = kern_fcntl(td, fd, F_SETFL, flags); 1515134266Sjhb if (error) 1516134266Sjhb return (error); 151783366Sjulian flags = td->td_retval[0]; 151843412Snewton } 151943412Snewton 152043412Snewton /* set up SIGIO receiver if needed */ 1521134266Sjhb if (dat != NULL) 1522134266Sjhb return (kern_fcntl(td, fd, F_SETOWN, td->td_proc->p_pid)); 152343412Snewton return 0; 152443412Snewton} 152543412Snewton 152643412Snewtonstatic int 152783366Sjuliani_getsig(fp, td, retval, fd, cmd, dat) 152843412Snewton struct file *fp; 152983366Sjulian struct thread *td; 153043412Snewton register_t *retval; 153143412Snewton int fd; 153243412Snewton u_long cmd; 153343412Snewton caddr_t dat; 153443412Snewton{ 153543412Snewton int error; 153643412Snewton 153743412Snewton if (dat != NULL) { 153843412Snewton struct svr4_strm *st = svr4_stream_get(fp); 153943412Snewton 154043412Snewton if (st == NULL) { 154143412Snewton DPRINTF(("i_getsig: bad file descriptor\n")); 154243412Snewton return EINVAL; 154343412Snewton } 154443412Snewton if ((error = copyout(&st->s_eventmask, dat, 154543412Snewton sizeof(st->s_eventmask))) != 0) { 154643412Snewton DPRINTF(("i_getsig: bad eventmask pointer\n")); 154743412Snewton return error; 154843412Snewton } 154943412Snewton } 155043412Snewton return 0; 155143412Snewton} 155243412Snewton 155343412Snewtonint 155483366Sjuliansvr4_stream_ioctl(fp, td, retval, fd, cmd, dat) 155543412Snewton struct file *fp; 155683366Sjulian struct thread *td; 155743412Snewton register_t *retval; 155843412Snewton int fd; 155943412Snewton u_long cmd; 156043412Snewton caddr_t dat; 156143412Snewton{ 156243412Snewton *retval = 0; 156343412Snewton 156443412Snewton /* 156543412Snewton * All the following stuff assumes "sockmod" is pushed... 156643412Snewton */ 156743412Snewton switch (cmd) { 156843412Snewton case SVR4_I_NREAD: 156943412Snewton DPRINTF(("I_NREAD\n")); 157083366Sjulian return i_nread(fp, td, retval, fd, cmd, dat); 157143412Snewton 157243412Snewton case SVR4_I_PUSH: 157380114Sassar DPRINTF(("I_PUSH %p\n", dat)); 157443412Snewton#if defined(DEBUG_SVR4) 157580114Sassar show_strbuf((struct svr4_strbuf *)dat); 157643412Snewton#endif 157743412Snewton return 0; 157843412Snewton 157943412Snewton case SVR4_I_POP: 158043412Snewton DPRINTF(("I_POP\n")); 158143412Snewton return 0; 158243412Snewton 158343412Snewton case SVR4_I_LOOK: 158443412Snewton DPRINTF(("I_LOOK\n")); 158543412Snewton return 0; 158643412Snewton 158743412Snewton case SVR4_I_FLUSH: 158843412Snewton DPRINTF(("I_FLUSH\n")); 158943412Snewton return 0; 159043412Snewton 159143412Snewton case SVR4_I_SRDOPT: 159243412Snewton DPRINTF(("I_SRDOPT\n")); 159343412Snewton return 0; 159443412Snewton 159543412Snewton case SVR4_I_GRDOPT: 159643412Snewton DPRINTF(("I_GRDOPT\n")); 159743412Snewton return 0; 159843412Snewton 159943412Snewton case SVR4_I_STR: 160043412Snewton DPRINTF(("I_STR\n")); 160183366Sjulian return i_str(fp, td, retval, fd, cmd, dat); 160243412Snewton 160343412Snewton case SVR4_I_SETSIG: 160443412Snewton DPRINTF(("I_SETSIG\n")); 160583366Sjulian return i_setsig(fp, td, retval, fd, cmd, dat); 160643412Snewton 160743412Snewton case SVR4_I_GETSIG: 160843412Snewton DPRINTF(("I_GETSIG\n")); 160983366Sjulian return i_getsig(fp, td, retval, fd, cmd, dat); 161043412Snewton 161143412Snewton case SVR4_I_FIND: 161243412Snewton DPRINTF(("I_FIND\n")); 161343412Snewton /* 161443412Snewton * Here we are not pushing modules really, we just 161543412Snewton * pretend all are present 161643412Snewton */ 161743412Snewton *retval = 0; 161843412Snewton return 0; 161943412Snewton 162043412Snewton case SVR4_I_LINK: 162143412Snewton DPRINTF(("I_LINK\n")); 162243412Snewton return 0; 162343412Snewton 162443412Snewton case SVR4_I_UNLINK: 162543412Snewton DPRINTF(("I_UNLINK\n")); 162643412Snewton return 0; 162743412Snewton 162843412Snewton case SVR4_I_ERECVFD: 162943412Snewton DPRINTF(("I_ERECVFD\n")); 163043412Snewton return 0; 163143412Snewton 163243412Snewton case SVR4_I_PEEK: 163343412Snewton DPRINTF(("I_PEEK\n")); 163443412Snewton return 0; 163543412Snewton 163643412Snewton case SVR4_I_FDINSERT: 163743412Snewton DPRINTF(("I_FDINSERT\n")); 163883366Sjulian return i_fdinsert(fp, td, retval, fd, cmd, dat); 163943412Snewton 164043412Snewton case SVR4_I_SENDFD: 164143412Snewton DPRINTF(("I_SENDFD\n")); 164243412Snewton return 0; 164343412Snewton 164443412Snewton case SVR4_I_RECVFD: 164543412Snewton DPRINTF(("I_RECVFD\n")); 164643412Snewton return 0; 164743412Snewton 164843412Snewton case SVR4_I_SWROPT: 164943412Snewton DPRINTF(("I_SWROPT\n")); 165043412Snewton return 0; 165143412Snewton 165243412Snewton case SVR4_I_GWROPT: 165343412Snewton DPRINTF(("I_GWROPT\n")); 165443412Snewton return 0; 165543412Snewton 165643412Snewton case SVR4_I_LIST: 165743412Snewton DPRINTF(("I_LIST\n")); 165843412Snewton return 0; 165943412Snewton 166043412Snewton case SVR4_I_PLINK: 166143412Snewton DPRINTF(("I_PLINK\n")); 166243412Snewton return 0; 166343412Snewton 166443412Snewton case SVR4_I_PUNLINK: 166543412Snewton DPRINTF(("I_PUNLINK\n")); 166643412Snewton return 0; 166743412Snewton 166843412Snewton case SVR4_I_SETEV: 166943412Snewton DPRINTF(("I_SETEV\n")); 167043412Snewton return 0; 167143412Snewton 167243412Snewton case SVR4_I_GETEV: 167343412Snewton DPRINTF(("I_GETEV\n")); 167443412Snewton return 0; 167543412Snewton 167643412Snewton case SVR4_I_STREV: 167743412Snewton DPRINTF(("I_STREV\n")); 167843412Snewton return 0; 167943412Snewton 168043412Snewton case SVR4_I_UNSTREV: 168143412Snewton DPRINTF(("I_UNSTREV\n")); 168243412Snewton return 0; 168343412Snewton 168443412Snewton case SVR4_I_FLUSHBAND: 168543412Snewton DPRINTF(("I_FLUSHBAND\n")); 168643412Snewton return 0; 168743412Snewton 168843412Snewton case SVR4_I_CKBAND: 168943412Snewton DPRINTF(("I_CKBAND\n")); 169043412Snewton return 0; 169143412Snewton 169243412Snewton case SVR4_I_GETBAND: 169343412Snewton DPRINTF(("I_GETBANK\n")); 169443412Snewton return 0; 169543412Snewton 169643412Snewton case SVR4_I_ATMARK: 169743412Snewton DPRINTF(("I_ATMARK\n")); 169843412Snewton return 0; 169943412Snewton 170043412Snewton case SVR4_I_SETCLTIME: 170143412Snewton DPRINTF(("I_SETCLTIME\n")); 170243412Snewton return 0; 170343412Snewton 170443412Snewton case SVR4_I_GETCLTIME: 170543412Snewton DPRINTF(("I_GETCLTIME\n")); 170643412Snewton return 0; 170743412Snewton 170843412Snewton case SVR4_I_CANPUT: 170943412Snewton DPRINTF(("I_CANPUT\n")); 171043412Snewton return 0; 171143412Snewton 171243412Snewton case SVR4__I_BIND_RSVD: 171343412Snewton DPRINTF(("_I_BIND_RSVD\n")); 171483366Sjulian return _i_bind_rsvd(fp, td, retval, fd, cmd, dat); 171543412Snewton 171643412Snewton case SVR4__I_RELE_RSVD: 171743412Snewton DPRINTF(("_I_RELE_RSVD\n")); 171883366Sjulian return _i_rele_rsvd(fp, td, retval, fd, cmd, dat); 171943412Snewton 172043412Snewton default: 172143412Snewton DPRINTF(("unimpl cmd = %lx\n", cmd)); 172243412Snewton break; 172343412Snewton } 172443412Snewton 172543412Snewton return 0; 172643412Snewton} 172743412Snewton 172843412Snewton 172943412Snewton 173043412Snewtonint 173183366Sjuliansvr4_sys_putmsg(td, uap) 173283366Sjulian register struct thread *td; 173343412Snewton struct svr4_sys_putmsg_args *uap; 173443412Snewton{ 173589306Salfred struct file *fp; 173689306Salfred int error; 173789306Salfred 173889319Salfred if ((error = fget(td, uap->fd, &fp)) != 0) { 173989306Salfred#ifdef DEBUG_SVR4 174089306Salfred uprintf("putmsg: bad fp\n"); 174189306Salfred#endif 174289306Salfred return EBADF; 174389306Salfred } 174489306Salfred error = svr4_do_putmsg(td, uap, fp); 174589306Salfred fdrop(fp, td); 174689306Salfred return (error); 174789306Salfred} 174889306Salfred 174989306Salfredstatic int 175089306Salfredsvr4_do_putmsg(td, uap, fp) 175189306Salfred struct thread *td; 175289306Salfred struct svr4_sys_putmsg_args *uap; 175343412Snewton struct file *fp; 175489306Salfred{ 175543412Snewton struct svr4_strbuf dat, ctl; 175643412Snewton struct svr4_strmcmd sc; 175743412Snewton struct sockaddr_in sain; 175843412Snewton struct sockaddr_un saun; 175943412Snewton void *skp, *sup; 176043412Snewton int sasize, *retval; 176143412Snewton struct svr4_strm *st; 176243412Snewton int error; 176343412Snewton caddr_t sg; 176443412Snewton 176583366Sjulian retval = td->td_retval; 176654493Snewton 176743412Snewton#ifdef DEBUG_SVR4 1768107849Salfred show_msg(">putmsg", uap->fd, uap->ctl, 1769107849Salfred uap->dat, uap->flags); 177043412Snewton#endif /* DEBUG_SVR4 */ 177143412Snewton 177289306Salfred FILE_LOCK_ASSERT(fp, MA_NOTOWNED); 177343412Snewton 1774107849Salfred if (uap->ctl != NULL) { 1775107849Salfred if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) { 177643412Snewton#ifdef DEBUG_SVR4 177743412Snewton uprintf("putmsg: copyin(): %d\n", error); 177843412Snewton#endif 177943412Snewton return error; 178043412Snewton } 178143412Snewton } 178243412Snewton else 178343412Snewton ctl.len = -1; 178443412Snewton 1785107849Salfred if (uap->dat != NULL) { 1786107849Salfred if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) { 178743412Snewton#ifdef DEBUG_SVR4 178843412Snewton uprintf("putmsg: copyin(): %d (2)\n", error); 178943412Snewton#endif 179043412Snewton return error; 179143412Snewton } 179243412Snewton } 179343412Snewton else 179443412Snewton dat.len = -1; 179543412Snewton 179643412Snewton /* 179743412Snewton * Only for sockets for now. 179843412Snewton */ 179943412Snewton if ((st = svr4_stream_get(fp)) == NULL) { 180043412Snewton DPRINTF(("putmsg: bad file type\n")); 180143412Snewton return EINVAL; 180243412Snewton } 180343412Snewton 1804121275Stjr if (ctl.len < 0 || ctl.len > sizeof(sc)) { 180543412Snewton DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len, 180643412Snewton sizeof(struct svr4_strmcmd))); 180743412Snewton return EINVAL; 180843412Snewton } 180943412Snewton 181043412Snewton if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 181143412Snewton return error; 181243412Snewton 181343412Snewton switch (st->s_family) { 181443412Snewton case AF_INET: 181543412Snewton if (sc.len != sizeof(sain)) { 181643412Snewton if (sc.cmd == SVR4_TI_DATA_REQUEST) { 181743412Snewton struct write_args wa; 181843412Snewton 181943412Snewton /* Solaris seems to use sc.cmd = 3 to 182043412Snewton * send "expedited" data. telnet uses 182143412Snewton * this for options processing, sending EOF, 182243412Snewton * etc. I'm sure other things use it too. 182343412Snewton * I don't have any documentation 182443412Snewton * on it, so I'm making a guess that this 182543412Snewton * is how it works. newton@atdot.dotat.org XXX 182643412Snewton */ 182751844Speter DPRINTF(("sending expedited data ??\n")); 1828107849Salfred wa.fd = uap->fd; 1829107849Salfred wa.buf = dat.buf; 1830107849Salfred wa.nbyte = dat.len; 183183366Sjulian return write(td, &wa); 183243412Snewton } 183343412Snewton DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len)); 183443412Snewton return EINVAL; 183543412Snewton } 183643412Snewton netaddr_to_sockaddr_in(&sain, &sc); 183743412Snewton skp = &sain; 183843412Snewton sasize = sizeof(sain); 183943412Snewton error = sain.sin_family != st->s_family; 184043412Snewton break; 184143412Snewton 184243412Snewton case AF_LOCAL: 184343412Snewton if (ctl.len == 8) { 184443412Snewton /* We are doing an accept; succeed */ 184543412Snewton DPRINTF(("putmsg: Do nothing\n")); 184643412Snewton *retval = 0; 184743412Snewton return 0; 184843412Snewton } 184943412Snewton else { 185043412Snewton /* Maybe we've been given a device/inode pair */ 1851130640Sphk dev_t *dev = SVR4_ADDROF(&sc); 185243412Snewton ino_t *ino = (ino_t *) &dev[1]; 185383366Sjulian skp = svr4_find_socket(td, fp, *dev, *ino); 185443412Snewton if (skp == NULL) { 185543412Snewton skp = &saun; 185643412Snewton /* I guess we have it by name */ 185743412Snewton netaddr_to_sockaddr_un(skp, &sc); 185843412Snewton } 185943412Snewton sasize = sizeof(saun); 186043412Snewton } 186143412Snewton break; 186243412Snewton 186343412Snewton default: 186443412Snewton DPRINTF(("putmsg: Unsupported address family %d\n", 186543412Snewton st->s_family)); 186643412Snewton return ENOSYS; 186743412Snewton } 186843412Snewton 186943412Snewton sg = stackgap_init(); 187043412Snewton sup = stackgap_alloc(&sg, sasize); 187143412Snewton 187243412Snewton if ((error = copyout(skp, sup, sasize)) != 0) 187343412Snewton return error; 187443412Snewton 187543412Snewton switch (st->s_cmd = sc.cmd) { 187643412Snewton case SVR4_TI_CONNECT_REQUEST: /* connect */ 187743412Snewton { 187843412Snewton struct connect_args co; 187943412Snewton 1880107849Salfred co.s = uap->fd; 1881107849Salfred co.name = (void *) sup; 1882107849Salfred co.namelen = (int) sasize; 188343412Snewton 188483366Sjulian return connect(td, &co); 188543412Snewton } 188643412Snewton 188743412Snewton case SVR4_TI_SENDTO_REQUEST: /* sendto */ 188843412Snewton { 188943412Snewton struct msghdr msg; 189043412Snewton struct iovec aiov; 189143412Snewton 189243412Snewton msg.msg_name = (caddr_t) sup; 189343412Snewton msg.msg_namelen = sasize; 189443412Snewton msg.msg_iov = &aiov; 189543412Snewton msg.msg_iovlen = 1; 189643412Snewton msg.msg_control = 0; 189743412Snewton msg.msg_flags = 0; 189843412Snewton aiov.iov_base = dat.buf; 189943412Snewton aiov.iov_len = dat.len; 190043412Snewton#if 0 190143412Snewton error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 190283366Sjulian uio, 0, 0, 0, uio->uio_td); 190343412Snewton#endif 1904107849Salfred error = svr4_sendit(td, uap->fd, &msg, 1905107849Salfred uap->flags); 190643412Snewton DPRINTF(("sendto_request error: %d\n", error)); 190743412Snewton *retval = 0; 190843412Snewton return error; 190943412Snewton } 191043412Snewton 191143412Snewton default: 191243412Snewton DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd)); 191343412Snewton return ENOSYS; 191443412Snewton } 191543412Snewton} 191643412Snewton 191743412Snewtonint 191889308Salfredsvr4_sys_getmsg(td, uap) 191989308Salfred struct thread *td; 192089306Salfred struct svr4_sys_getmsg_args *uap; 192189306Salfred{ 192289306Salfred struct file *fp; 192389306Salfred int error; 192489306Salfred 192589319Salfred if ((error = fget(td, uap->fd, &fp)) != 0) { 192689306Salfred#ifdef DEBUG_SVR4 192789306Salfred uprintf("getmsg: bad fp\n"); 192889306Salfred#endif 192989306Salfred return EBADF; 193089306Salfred } 193189308Salfred error = svr4_do_getmsg(td, uap, fp); 193289306Salfred fdrop(fp, td); 193389306Salfred return (error); 193489306Salfred} 193589306Salfred 193689306Salfredint 193789536Salfredsvr4_do_getmsg(td, uap, fp) 193883366Sjulian register struct thread *td; 193943412Snewton struct svr4_sys_getmsg_args *uap; 194089306Salfred struct file *fp; 194143412Snewton{ 194243412Snewton struct getpeername_args ga; 194343412Snewton struct accept_args aa; 194443412Snewton struct svr4_strbuf dat, ctl; 194543412Snewton struct svr4_strmcmd sc; 194643412Snewton int error, *retval; 194743412Snewton struct msghdr msg; 194843412Snewton struct iovec aiov; 194943412Snewton struct sockaddr_in sain; 195043412Snewton struct sockaddr_un saun; 195143412Snewton void *skp, *sup; 195243412Snewton int sasize; 195343412Snewton struct svr4_strm *st; 195443412Snewton int *flen; 195543412Snewton int fl; 195643412Snewton caddr_t sg; 195743412Snewton 195883366Sjulian retval = td->td_retval; 195954493Snewton 196089306Salfred FILE_LOCK_ASSERT(fp, MA_NOTOWNED); 196143412Snewton 196243412Snewton memset(&sc, 0, sizeof(sc)); 196343412Snewton 196443412Snewton#ifdef DEBUG_SVR4 1965107849Salfred show_msg(">getmsg", uap->fd, uap->ctl, 1966107849Salfred uap->dat, 0); 196743412Snewton#endif /* DEBUG_SVR4 */ 196843412Snewton 1969107849Salfred if (uap->ctl != NULL) { 1970107849Salfred if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) 197143412Snewton return error; 1972121275Stjr if (ctl.len < 0) 1973121275Stjr return EINVAL; 197443412Snewton } 197543412Snewton else { 197643412Snewton ctl.len = -1; 197743412Snewton ctl.maxlen = 0; 197843412Snewton } 197943412Snewton 1980107849Salfred if (uap->dat != NULL) { 1981107849Salfred if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) 198243412Snewton return error; 198343412Snewton } 198443412Snewton else { 198543412Snewton dat.len = -1; 198643412Snewton dat.maxlen = 0; 198743412Snewton } 198843412Snewton 198943412Snewton /* 199043412Snewton * Only for sockets for now. 199143412Snewton */ 199243412Snewton if ((st = svr4_stream_get(fp)) == NULL) { 199343412Snewton DPRINTF(("getmsg: bad file type\n")); 199443412Snewton return EINVAL; 199543412Snewton } 199643412Snewton 199743412Snewton if (ctl.maxlen == -1 || dat.maxlen == -1) { 199843412Snewton DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n")); 199943412Snewton return ENOSYS; 200043412Snewton } 200143412Snewton 200243412Snewton switch (st->s_family) { 200343412Snewton case AF_INET: 200443412Snewton skp = &sain; 200543412Snewton sasize = sizeof(sain); 200643412Snewton break; 200743412Snewton 200843412Snewton case AF_LOCAL: 200943412Snewton skp = &saun; 201043412Snewton sasize = sizeof(saun); 201143412Snewton break; 201243412Snewton 201343412Snewton default: 201443412Snewton DPRINTF(("getmsg: Unsupported address family %d\n", 201543412Snewton st->s_family)); 201643412Snewton return ENOSYS; 201743412Snewton } 201843412Snewton 201943412Snewton sg = stackgap_init(); 202043412Snewton sup = stackgap_alloc(&sg, sasize); 202143412Snewton flen = (int *) stackgap_alloc(&sg, sizeof(*flen)); 202243412Snewton 202343412Snewton fl = sasize; 202443412Snewton if ((error = copyout(&fl, flen, sizeof(fl))) != 0) 202543412Snewton return error; 202643412Snewton 202743412Snewton switch (st->s_cmd) { 202843412Snewton case SVR4_TI_CONNECT_REQUEST: 202943412Snewton DPRINTF(("getmsg: TI_CONNECT_REQUEST\n")); 203043412Snewton /* 203143412Snewton * We do the connect in one step, so the putmsg should 203243412Snewton * have gotten the error. 203343412Snewton */ 203443412Snewton sc.cmd = SVR4_TI_OK_REPLY; 203543412Snewton sc.len = 0; 203643412Snewton 203743412Snewton ctl.len = 8; 203843412Snewton dat.len = -1; 203943412Snewton fl = 1; 204043412Snewton st->s_cmd = sc.cmd; 204143412Snewton break; 204243412Snewton 204343412Snewton case SVR4_TI_OK_REPLY: 204443412Snewton DPRINTF(("getmsg: TI_OK_REPLY\n")); 204543412Snewton /* 204643412Snewton * We are immediately after a connect reply, so we send 204743412Snewton * a connect verification. 204843412Snewton */ 204943412Snewton 2050107849Salfred ga.fdes = uap->fd; 2051107849Salfred ga.asa = (void *) sup; 2052107849Salfred ga.alen = flen; 205343412Snewton 205483366Sjulian if ((error = getpeername(td, &ga)) != 0) { 205543412Snewton DPRINTF(("getmsg: getpeername failed %d\n", error)); 205643412Snewton return error; 205743412Snewton } 205843412Snewton 205943412Snewton if ((error = copyin(sup, skp, sasize)) != 0) 206043412Snewton return error; 206143412Snewton 206243412Snewton sc.cmd = SVR4_TI_CONNECT_REPLY; 206343412Snewton sc.pad[0] = 0x4; 206443412Snewton sc.offs = 0x18; 206543412Snewton sc.pad[1] = 0x14; 206643412Snewton sc.pad[2] = 0x04000402; 206743412Snewton 206843412Snewton switch (st->s_family) { 206943412Snewton case AF_INET: 207043412Snewton sc.len = sasize; 207143412Snewton sockaddr_to_netaddr_in(&sc, &sain); 207243412Snewton break; 207343412Snewton 207443412Snewton case AF_LOCAL: 207543412Snewton sc.len = sasize + 4; 207643412Snewton sockaddr_to_netaddr_un(&sc, &saun); 207743412Snewton break; 207843412Snewton 207943412Snewton default: 208043412Snewton return ENOSYS; 208143412Snewton } 208243412Snewton 208343412Snewton ctl.len = 40; 208443412Snewton dat.len = -1; 208543412Snewton fl = 0; 208643412Snewton st->s_cmd = sc.cmd; 208743412Snewton break; 208843412Snewton 208943412Snewton case SVR4_TI__ACCEPT_OK: 209043412Snewton DPRINTF(("getmsg: TI__ACCEPT_OK\n")); 209143412Snewton /* 209243412Snewton * We do the connect in one step, so the putmsg should 209343412Snewton * have gotten the error. 209443412Snewton */ 209543412Snewton sc.cmd = SVR4_TI_OK_REPLY; 209643412Snewton sc.len = 1; 209743412Snewton 209843412Snewton ctl.len = 8; 209943412Snewton dat.len = -1; 210043412Snewton fl = 1; 210143412Snewton st->s_cmd = SVR4_TI__ACCEPT_WAIT; 210243412Snewton break; 210343412Snewton 210443412Snewton case SVR4_TI__ACCEPT_WAIT: 210543412Snewton DPRINTF(("getmsg: TI__ACCEPT_WAIT\n")); 210643412Snewton /* 210743412Snewton * We are after a listen, so we try to accept... 210843412Snewton */ 2109107849Salfred aa.s = uap->fd; 2110107849Salfred aa.name = (void *) sup; 2111107849Salfred aa.anamelen = flen; 211243412Snewton 211383366Sjulian if ((error = accept(td, &aa)) != 0) { 211443412Snewton DPRINTF(("getmsg: accept failed %d\n", error)); 211543412Snewton return error; 211643412Snewton } 211743412Snewton 211843412Snewton st->s_afd = *retval; 211943412Snewton 212043412Snewton DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd)); 212143412Snewton 212243412Snewton if ((error = copyin(sup, skp, sasize)) != 0) 212343412Snewton return error; 212443412Snewton 212543412Snewton sc.cmd = SVR4_TI_ACCEPT_REPLY; 212643412Snewton sc.offs = 0x18; 212743412Snewton sc.pad[0] = 0x0; 212843412Snewton 212943412Snewton switch (st->s_family) { 213043412Snewton case AF_INET: 213143412Snewton sc.pad[1] = 0x28; 213243412Snewton sockaddr_to_netaddr_in(&sc, &sain); 213343412Snewton ctl.len = 40; 213443412Snewton sc.len = sasize; 213543412Snewton break; 213643412Snewton 213743412Snewton case AF_LOCAL: 213843412Snewton sc.pad[1] = 0x00010000; 213943412Snewton sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */ 214043412Snewton sc.pad[3] = 0x00010000; 214143412Snewton ctl.len = 134; 214243412Snewton sc.len = sasize + 4; 214343412Snewton break; 214443412Snewton 214543412Snewton default: 214643412Snewton return ENOSYS; 214743412Snewton } 214843412Snewton 214943412Snewton dat.len = -1; 215043412Snewton fl = 0; 215143412Snewton st->s_cmd = SVR4_TI__ACCEPT_OK; 215243412Snewton break; 215343412Snewton 215443412Snewton case SVR4_TI_SENDTO_REQUEST: 215543412Snewton DPRINTF(("getmsg: TI_SENDTO_REQUEST\n")); 215643412Snewton if (ctl.maxlen > 36 && ctl.len < 36) 215743412Snewton ctl.len = 36; 215843412Snewton 2159121275Stjr if (ctl.len > sizeof(sc)) 2160121275Stjr ctl.len = sizeof(sc); 2161121275Stjr 216243412Snewton if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 216343412Snewton return error; 216443412Snewton 216543412Snewton switch (st->s_family) { 216643412Snewton case AF_INET: 216743412Snewton sockaddr_to_netaddr_in(&sc, &sain); 216843412Snewton break; 216943412Snewton 217043412Snewton case AF_LOCAL: 217143412Snewton sockaddr_to_netaddr_un(&sc, &saun); 217243412Snewton break; 217343412Snewton 217443412Snewton default: 217543412Snewton return ENOSYS; 217643412Snewton } 217743412Snewton 217843412Snewton msg.msg_name = (caddr_t) sup; 217943412Snewton msg.msg_namelen = sasize; 218043412Snewton msg.msg_iov = &aiov; 218143412Snewton msg.msg_iovlen = 1; 218243412Snewton msg.msg_control = 0; 218343412Snewton aiov.iov_base = dat.buf; 218443412Snewton aiov.iov_len = dat.maxlen; 218543412Snewton msg.msg_flags = 0; 218643412Snewton 2187107849Salfred error = svr4_recvit(td, uap->fd, &msg, (caddr_t) flen); 218843412Snewton 218943412Snewton if (error) { 219043412Snewton DPRINTF(("getmsg: recvit failed %d\n", error)); 219143412Snewton return error; 219243412Snewton } 219343412Snewton 219443412Snewton if ((error = copyin(msg.msg_name, skp, sasize)) != 0) 219543412Snewton return error; 219643412Snewton 219743412Snewton sc.cmd = SVR4_TI_RECVFROM_IND; 219843412Snewton 219943412Snewton switch (st->s_family) { 220043412Snewton case AF_INET: 220143412Snewton sc.len = sasize; 220243412Snewton sockaddr_to_netaddr_in(&sc, &sain); 220343412Snewton break; 220443412Snewton 220543412Snewton case AF_LOCAL: 220643412Snewton sc.len = sasize + 4; 220743412Snewton sockaddr_to_netaddr_un(&sc, &saun); 220843412Snewton break; 220943412Snewton 221043412Snewton default: 221143412Snewton return ENOSYS; 221243412Snewton } 221343412Snewton 221443412Snewton dat.len = *retval; 221543412Snewton fl = 0; 221643412Snewton st->s_cmd = sc.cmd; 221743412Snewton break; 221843412Snewton 221943412Snewton default: 222043412Snewton st->s_cmd = sc.cmd; 222143412Snewton if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) { 222243412Snewton struct read_args ra; 222343412Snewton 222472082Sasmodai /* More weirdness: Again, I can't find documentation 222543412Snewton * to back this up, but when a process does a generic 222643412Snewton * "getmsg()" call it seems that the command field is 222743412Snewton * zero and the length of the data area is zero. I 222843412Snewton * think processes expect getmsg() to fill in dat.len 222943412Snewton * after reading at most dat.maxlen octets from the 223043412Snewton * stream. Since we're using sockets I can let 223143412Snewton * read() look after it and frob return values 223243412Snewton * appropriately (or inappropriately :-) 223343412Snewton * -- newton@atdot.dotat.org XXX 223443412Snewton */ 2235107849Salfred ra.fd = uap->fd; 2236107849Salfred ra.buf = dat.buf; 2237107849Salfred ra.nbyte = dat.maxlen; 223883366Sjulian if ((error = read(td, &ra)) != 0) { 223943412Snewton return error; 224043412Snewton } 224143412Snewton dat.len = *retval; 224243412Snewton *retval = 0; 224343412Snewton st->s_cmd = SVR4_TI_SENDTO_REQUEST; 224443412Snewton break; 224543412Snewton } 224643412Snewton DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd)); 224743412Snewton return EINVAL; 224843412Snewton } 224943412Snewton 2250107849Salfred if (uap->ctl) { 225143412Snewton if (ctl.len != -1) 225243412Snewton if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0) 225343412Snewton return error; 225443412Snewton 2255107849Salfred if ((error = copyout(&ctl, uap->ctl, sizeof(ctl))) != 0) 225643412Snewton return error; 225743412Snewton } 225843412Snewton 2259107849Salfred if (uap->dat) { 2260107849Salfred if ((error = copyout(&dat, uap->dat, sizeof(dat))) != 0) 226143412Snewton return error; 226243412Snewton } 226343412Snewton 2264107849Salfred if (uap->flags) { /* XXX: Need translation */ 2265107849Salfred if ((error = copyout(&fl, uap->flags, sizeof(fl))) != 0) 226643412Snewton return error; 226743412Snewton } 226843412Snewton 226943412Snewton *retval = 0; 227043412Snewton 227143412Snewton#ifdef DEBUG_SVR4 2272107849Salfred show_msg("<getmsg", uap->fd, uap->ctl, 2273107849Salfred uap->dat, fl); 227443412Snewton#endif /* DEBUG_SVR4 */ 227543412Snewton return error; 227643412Snewton} 227743412Snewton 227883366Sjulianint svr4_sys_send(td, uap) 227983366Sjulian struct thread *td; 228043412Snewton struct svr4_sys_send_args *uap; 228143412Snewton{ 2282103886Smini struct osend_args osa; 2283107849Salfred osa.s = uap->s; 2284107849Salfred osa.buf = uap->buf; 2285107849Salfred osa.len = uap->len; 2286107849Salfred osa.flags = uap->flags; 2287103886Smini return osend(td, &osa); 228843412Snewton} 228943412Snewton 229083366Sjulianint svr4_sys_recv(td, uap) 229183366Sjulian struct thread *td; 229243412Snewton struct svr4_sys_recv_args *uap; 229343412Snewton{ 2294103886Smini struct orecv_args ora; 2295107849Salfred ora.s = uap->s; 2296107849Salfred ora.buf = uap->buf; 2297107849Salfred ora.len = uap->len; 2298107849Salfred ora.flags = uap->flags; 2299103886Smini return orecv(td, &ora); 230043412Snewton} 230143412Snewton 230243412Snewton/* 230343412Snewton * XXX This isn't necessary, but it's handy for inserting debug code into 230443412Snewton * sendto(). Let's leave it here for now... 230543412Snewton */ 230643412Snewtonint 230783366Sjuliansvr4_sys_sendto(td, uap) 230883366Sjulian struct thread *td; 230943412Snewton struct svr4_sys_sendto_args *uap; 231043412Snewton{ 231143412Snewton struct sendto_args sa; 231243412Snewton 2313107849Salfred sa.s = uap->s; 2314107849Salfred sa.buf = uap->buf; 2315107849Salfred sa.len = uap->len; 2316107849Salfred sa.flags = uap->flags; 2317107849Salfred sa.to = (caddr_t)uap->to; 2318107849Salfred sa.tolen = uap->tolen; 231943412Snewton 232043412Snewton DPRINTF(("calling sendto()\n")); 232183366Sjulian return sendto(td, &sa); 232243412Snewton} 232343412Snewton 2324