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: releng/10.3/sys/compat/svr4/svr4_stream.c 280258 2015-03-19 13:37:36Z rwatson $"); 40116174Sobrien 41147965Sjhb#include "opt_compat.h" 42147965Sjhb#include "opt_ktrace.h" 43104571Srwatson 4443412Snewton#include <sys/param.h> 4543412Snewton#include <sys/systm.h> 46280258Srwatson#include <sys/capsicum.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 */ 5343412Snewton#include <sys/mbuf.h> 5476166Smarkm#include <sys/mutex.h> 5576166Smarkm#include <sys/proc.h> 5643412Snewton#include <sys/protosw.h> 5743412Snewton#include <sys/signal.h> 5843412Snewton#include <sys/signalvar.h> 5976166Smarkm#include <sys/socket.h> 6076166Smarkm#include <sys/socketvar.h> 6143412Snewton#include <sys/stat.h> 62134266Sjhb#include <sys/syscallsubr.h> 6343412Snewton#include <sys/sysproto.h> 6476166Smarkm#include <sys/uio.h> 6576166Smarkm#include <sys/ktrace.h> /* Must come after sys/uio.h */ 6676166Smarkm#include <sys/un.h> 6743412Snewton 6876166Smarkm#include <netinet/in.h> 6976166Smarkm 7065302Sobrien#include <compat/svr4/svr4.h> 7165302Sobrien#include <compat/svr4/svr4_types.h> 7265302Sobrien#include <compat/svr4/svr4_util.h> 7365302Sobrien#include <compat/svr4/svr4_signal.h> 7465302Sobrien#include <compat/svr4/svr4_proto.h> 7565302Sobrien#include <compat/svr4/svr4_stropts.h> 7665302Sobrien#include <compat/svr4/svr4_timod.h> 7765302Sobrien#include <compat/svr4/svr4_sockmod.h> 7865302Sobrien#include <compat/svr4/svr4_ioctl.h> 7965302Sobrien#include <compat/svr4/svr4_socket.h> 8043412Snewton 8143412Snewton/* Utils */ 82141486Sjhbstatic int clean_pipe(struct thread *, char *); 8392761Salfredstatic void getparm(struct file *, struct svr4_si_sockparms *); 8492761Salfredstatic int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *, 8592761Salfred struct file *); 8692761Salfredstatic int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *, 8792761Salfred struct file *); 8843412Snewton 8943412Snewton/* Address Conversions */ 9092761Salfredstatic void sockaddr_to_netaddr_in(struct svr4_strmcmd *, 9192761Salfred const struct sockaddr_in *); 9292761Salfredstatic void sockaddr_to_netaddr_un(struct svr4_strmcmd *, 9392761Salfred const struct sockaddr_un *); 9492761Salfredstatic void netaddr_to_sockaddr_in(struct sockaddr_in *, 9592761Salfred const struct svr4_strmcmd *); 9692761Salfredstatic void netaddr_to_sockaddr_un(struct sockaddr_un *, 9792761Salfred const struct svr4_strmcmd *); 9843412Snewton 9943412Snewton/* stream ioctls */ 10092761Salfredstatic int i_nread(struct file *, struct thread *, register_t *, int, 10192761Salfred u_long, caddr_t); 10292761Salfredstatic int i_fdinsert(struct file *, struct thread *, register_t *, int, 10392761Salfred u_long, caddr_t); 10492761Salfredstatic int i_str(struct file *, struct thread *, register_t *, int, 10592761Salfred u_long, caddr_t); 10692761Salfredstatic int i_setsig(struct file *, struct thread *, register_t *, int, 10792761Salfred u_long, caddr_t); 10892761Salfredstatic int i_getsig(struct file *, struct thread *, register_t *, int, 10992761Salfred u_long, caddr_t); 11092761Salfredstatic int _i_bind_rsvd(struct file *, struct thread *, register_t *, int, 11192761Salfred u_long, caddr_t); 11292761Salfredstatic int _i_rele_rsvd(struct file *, struct thread *, register_t *, int, 11392761Salfred u_long, caddr_t); 11443412Snewton 11543412Snewton/* i_str sockmod calls */ 11692761Salfredstatic int sockmod(struct file *, int, struct svr4_strioctl *, 11792761Salfred struct thread *); 11892761Salfredstatic int si_listen(struct file *, int, struct svr4_strioctl *, 11992761Salfred struct thread *); 12092761Salfredstatic int si_ogetudata(struct file *, int, struct svr4_strioctl *, 12192761Salfred struct thread *); 12292761Salfredstatic int si_sockparams(struct file *, int, struct svr4_strioctl *, 12392761Salfred struct thread *); 12492761Salfredstatic int si_shutdown (struct file *, int, struct svr4_strioctl *, 12592761Salfred struct thread *); 12692761Salfredstatic int si_getudata(struct file *, int, struct svr4_strioctl *, 12792761Salfred struct thread *); 12843412Snewton 12943412Snewton/* i_str timod calls */ 13092761Salfredstatic int timod(struct file *, int, struct svr4_strioctl *, struct thread *); 13192761Salfredstatic int ti_getinfo(struct file *, int, struct svr4_strioctl *, 13292761Salfred struct thread *); 13392761Salfredstatic int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *); 13443412Snewton 13543412Snewton#ifdef DEBUG_SVR4 13692761Salfredstatic void bufprint(u_char *, size_t); 13792761Salfredstatic int show_ioc(const char *, struct svr4_strioctl *); 13892761Salfredstatic int show_strbuf(struct svr4_strbuf *); 13992761Salfredstatic void show_msg(const char *, int, struct svr4_strbuf *, 14092761Salfred struct svr4_strbuf *, int); 14143412Snewton 14243412Snewtonstatic void 14343412Snewtonbufprint(buf, len) 14443412Snewton u_char *buf; 14543412Snewton size_t len; 14643412Snewton{ 14743412Snewton size_t i; 14843412Snewton 14943412Snewton uprintf("\n\t"); 15043412Snewton for (i = 0; i < len; i++) { 15143412Snewton uprintf("%x ", buf[i]); 15243412Snewton if (i && (i % 16) == 0) 15343412Snewton uprintf("\n\t"); 15443412Snewton } 15543412Snewton} 15643412Snewton 15743412Snewtonstatic int 15843412Snewtonshow_ioc(str, ioc) 15943412Snewton const char *str; 16043412Snewton struct svr4_strioctl *ioc; 16143412Snewton{ 162121275Stjr u_char *ptr = NULL; 163121275Stjr int len; 16443412Snewton int error; 16543412Snewton 166121275Stjr len = ioc->len; 167121275Stjr if (len > 1024) 168121275Stjr len = 1024; 169121275Stjr 170121275Stjr if (len > 0) { 171121275Stjr ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK); 172121275Stjr if ((error = copyin(ioc->buf, ptr, len)) != 0) { 173121275Stjr free((char *) ptr, M_TEMP); 174121275Stjr return error; 175121275Stjr } 176121275Stjr } 177121275Stjr 17843412Snewton uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ", 17943412Snewton str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf); 18043412Snewton 181121275Stjr if (ptr != NULL) 182121275Stjr bufprint(ptr, len); 18343412Snewton 18443412Snewton uprintf("}\n"); 18543412Snewton 186121275Stjr if (ptr != NULL) 187121275Stjr free((char *) ptr, M_TEMP); 18843412Snewton return 0; 18943412Snewton} 19043412Snewton 19143412Snewton 19243412Snewtonstatic int 19343412Snewtonshow_strbuf(str) 19443412Snewton struct svr4_strbuf *str; 19543412Snewton{ 19643412Snewton int error; 19743412Snewton u_char *ptr = NULL; 19843412Snewton int maxlen = str->maxlen; 19943412Snewton int len = str->len; 20043412Snewton 201121275Stjr if (maxlen > 8192) 202121275Stjr maxlen = 8192; 203121275Stjr 20443412Snewton if (maxlen < 0) 20543412Snewton maxlen = 0; 20643412Snewton 20743412Snewton if (len >= maxlen) 20843412Snewton len = maxlen; 20943412Snewton 21043412Snewton if (len > 0) { 211111119Simp ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK); 21243412Snewton 21343412Snewton if ((error = copyin(str->buf, ptr, len)) != 0) { 21443412Snewton free((char *) ptr, M_TEMP); 21543412Snewton return error; 21643412Snewton } 21743412Snewton } 21843412Snewton 21943412Snewton uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf); 22043412Snewton 22143412Snewton if (ptr) 22243412Snewton bufprint(ptr, len); 22343412Snewton 22443412Snewton uprintf("]}"); 22543412Snewton 22643412Snewton if (ptr) 22743412Snewton free((char *) ptr, M_TEMP); 22843412Snewton 22943412Snewton return 0; 23043412Snewton} 23143412Snewton 23243412Snewton 23343412Snewtonstatic void 23443412Snewtonshow_msg(str, fd, ctl, dat, flags) 23543412Snewton const char *str; 23643412Snewton int fd; 23743412Snewton struct svr4_strbuf *ctl; 23843412Snewton struct svr4_strbuf *dat; 23943412Snewton int flags; 24043412Snewton{ 24143412Snewton struct svr4_strbuf buf; 24243412Snewton int error; 24343412Snewton 24443412Snewton uprintf("%s(%d", str, fd); 24543412Snewton if (ctl != NULL) { 24643412Snewton if ((error = copyin(ctl, &buf, sizeof(buf))) != 0) 24743412Snewton return; 24843412Snewton show_strbuf(&buf); 24943412Snewton } 25043412Snewton else 25143412Snewton uprintf(", NULL"); 25243412Snewton 25343412Snewton if (dat != NULL) { 25443412Snewton if ((error = copyin(dat, &buf, sizeof(buf))) != 0) 25543412Snewton return; 25643412Snewton show_strbuf(&buf); 25743412Snewton } 25843412Snewton else 25943412Snewton uprintf(", NULL"); 26043412Snewton 26143412Snewton uprintf(", %x);\n", flags); 26243412Snewton} 26343412Snewton 26443412Snewton#endif /* DEBUG_SVR4 */ 26543412Snewton 26643412Snewton/* 26743412Snewton * We are faced with an interesting situation. On svr4 unix sockets 26843412Snewton * are really pipes. But we really have sockets, and we might as 26943412Snewton * well use them. At the point where svr4 calls TI_BIND, it has 27043412Snewton * already created a named pipe for the socket using mknod(2). 27143412Snewton * We need to create a socket with the same name when we bind, 27243412Snewton * so we need to remove the pipe before, otherwise we'll get address 27343412Snewton * already in use. So we *carefully* remove the pipe, to avoid 27443412Snewton * using this as a random file removal tool. We use system calls 27543412Snewton * to avoid code duplication. 27643412Snewton */ 27743412Snewtonstatic int 27883366Sjulianclean_pipe(td, path) 27983366Sjulian struct thread *td; 280141486Sjhb char *path; 28143412Snewton{ 28243412Snewton struct stat st; 28343412Snewton int error; 28443412Snewton 285141486Sjhb error = kern_lstat(td, path, UIO_SYSSPACE, &st); 28643412Snewton 28743412Snewton /* 28843412Snewton * Make sure we are dealing with a mode 0 named pipe. 28943412Snewton */ 29043412Snewton if ((st.st_mode & S_IFMT) != S_IFIFO) 291141486Sjhb return (0); 29243412Snewton 29343412Snewton if ((st.st_mode & ALLPERMS) != 0) 294141486Sjhb return (0); 29543412Snewton 296141486Sjhb error = kern_unlink(td, path, UIO_SYSSPACE); 297141486Sjhb if (error) 29843412Snewton DPRINTF(("clean_pipe: unlink failed %d\n", error)); 299141486Sjhb return (error); 30043412Snewton} 30143412Snewton 30243412Snewton 30343412Snewtonstatic void 30443412Snewtonsockaddr_to_netaddr_in(sc, sain) 30543412Snewton struct svr4_strmcmd *sc; 30643412Snewton const struct sockaddr_in *sain; 30743412Snewton{ 30843412Snewton struct svr4_netaddr_in *na; 30943412Snewton na = SVR4_ADDROF(sc); 31043412Snewton 31143412Snewton na->family = sain->sin_family; 31243412Snewton na->port = sain->sin_port; 31343412Snewton na->addr = sain->sin_addr.s_addr; 31443412Snewton DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port, 31543412Snewton na->addr)); 31643412Snewton} 31743412Snewton 31843412Snewton 31943412Snewtonstatic void 32043412Snewtonsockaddr_to_netaddr_un(sc, saun) 32143412Snewton struct svr4_strmcmd *sc; 32243412Snewton const struct sockaddr_un *saun; 32343412Snewton{ 32443412Snewton struct svr4_netaddr_un *na; 32543412Snewton char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 - 32643412Snewton sizeof(*sc); 32743412Snewton const char *src; 32843412Snewton 32943412Snewton na = SVR4_ADDROF(sc); 33043412Snewton na->family = saun->sun_family; 33143412Snewton for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; ) 33243412Snewton if (dst == edst) 33343412Snewton break; 33443412Snewton DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path)); 33543412Snewton} 33643412Snewton 33743412Snewton 33843412Snewtonstatic void 33943412Snewtonnetaddr_to_sockaddr_in(sain, sc) 34043412Snewton struct sockaddr_in *sain; 34143412Snewton const struct svr4_strmcmd *sc; 34243412Snewton{ 34343412Snewton const struct svr4_netaddr_in *na; 34443412Snewton 34543412Snewton 34643412Snewton na = SVR4_C_ADDROF(sc); 34743412Snewton memset(sain, 0, sizeof(*sain)); 34843412Snewton sain->sin_len = sizeof(*sain); 34943412Snewton sain->sin_family = na->family; 35043412Snewton sain->sin_port = na->port; 35143412Snewton sain->sin_addr.s_addr = na->addr; 35243412Snewton DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family, 35343412Snewton sain->sin_port, sain->sin_addr.s_addr)); 35443412Snewton} 35543412Snewton 35643412Snewton 35743412Snewtonstatic void 35843412Snewtonnetaddr_to_sockaddr_un(saun, sc) 35943412Snewton struct sockaddr_un *saun; 36043412Snewton const struct svr4_strmcmd *sc; 36143412Snewton{ 36243412Snewton const struct svr4_netaddr_un *na; 36343412Snewton char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1]; 36443412Snewton const char *src; 36543412Snewton 36643412Snewton na = SVR4_C_ADDROF(sc); 36743412Snewton memset(saun, 0, sizeof(*saun)); 36843412Snewton saun->sun_family = na->family; 36943412Snewton for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; ) 37043412Snewton if (dst == edst) 37143412Snewton break; 37243412Snewton saun->sun_len = dst - saun->sun_path; 37343412Snewton DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family, 37443412Snewton saun->sun_path)); 37543412Snewton} 37643412Snewton 37743412Snewton 37843412Snewtonstatic void 37943412Snewtongetparm(fp, pa) 38043412Snewton struct file *fp; 38143412Snewton struct svr4_si_sockparms *pa; 38243412Snewton{ 38389306Salfred struct svr4_strm *st; 38489306Salfred struct socket *so; 38543412Snewton 38689306Salfred st = svr4_stream_get(fp); 38743412Snewton if (st == NULL) 38843412Snewton return; 38943412Snewton 390109153Sdillon so = fp->f_data; 39189306Salfred 39243412Snewton pa->family = st->s_family; 39343412Snewton 39443412Snewton switch (so->so_type) { 39543412Snewton case SOCK_DGRAM: 39643412Snewton pa->type = SVR4_T_CLTS; 39743412Snewton pa->protocol = IPPROTO_UDP; 39843412Snewton DPRINTF(("getparm(dgram)\n")); 39943412Snewton return; 40043412Snewton 40143412Snewton case SOCK_STREAM: 40243412Snewton pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */ 40343412Snewton pa->protocol = IPPROTO_IP; 40443412Snewton DPRINTF(("getparm(stream)\n")); 40543412Snewton return; 40643412Snewton 40743412Snewton case SOCK_RAW: 40843412Snewton pa->type = SVR4_T_CLTS; 40943412Snewton pa->protocol = IPPROTO_RAW; 41043412Snewton DPRINTF(("getparm(raw)\n")); 41143412Snewton return; 41243412Snewton 41343412Snewton default: 41443412Snewton pa->type = 0; 41543412Snewton pa->protocol = 0; 41643412Snewton DPRINTF(("getparm(type %d?)\n", so->so_type)); 41743412Snewton return; 41843412Snewton } 41943412Snewton} 42043412Snewton 42143412Snewton 42243412Snewtonstatic int 42383366Sjuliansi_ogetudata(fp, fd, ioc, td) 42443412Snewton struct file *fp; 42543412Snewton int fd; 42643412Snewton struct svr4_strioctl *ioc; 42783366Sjulian struct thread *td; 42843412Snewton{ 42943412Snewton int error; 43043412Snewton struct svr4_si_oudata ud; 43143412Snewton struct svr4_si_sockparms pa; 43243412Snewton 43343412Snewton if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) { 43443412Snewton DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n", 43543412Snewton sizeof(ud), ioc->len)); 43643412Snewton return EINVAL; 43743412Snewton } 43843412Snewton 43943412Snewton if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 44043412Snewton return error; 44143412Snewton 44243412Snewton getparm(fp, &pa); 44343412Snewton 44443412Snewton switch (pa.family) { 44543412Snewton case AF_INET: 44643412Snewton ud.tidusize = 16384; 44743412Snewton ud.addrsize = sizeof(struct svr4_sockaddr_in); 44843412Snewton if (pa.type == SVR4_SOCK_STREAM) 44943412Snewton ud.etsdusize = 1; 45043412Snewton else 45143412Snewton ud.etsdusize = 0; 45243412Snewton break; 45343412Snewton 45443412Snewton case AF_LOCAL: 45543412Snewton ud.tidusize = 65536; 45643412Snewton ud.addrsize = 128; 45743412Snewton ud.etsdusize = 128; 45843412Snewton break; 45943412Snewton 46043412Snewton default: 46143412Snewton DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n", 46243412Snewton pa.family)); 46343412Snewton return ENOSYS; 46443412Snewton } 46543412Snewton 46643412Snewton /* I have no idea what these should be! */ 46743412Snewton ud.optsize = 128; 46843412Snewton ud.tsdusize = 128; 46943412Snewton 47043412Snewton ud.servtype = pa.type; 47143412Snewton 47243412Snewton /* XXX: Fixme */ 47343412Snewton ud.so_state = 0; 47443412Snewton ud.so_options = 0; 47543412Snewton return copyout(&ud, ioc->buf, ioc->len); 47643412Snewton} 47743412Snewton 47843412Snewton 47943412Snewtonstatic int 48083366Sjuliansi_sockparams(fp, fd, ioc, td) 48143412Snewton struct file *fp; 48243412Snewton int fd; 48343412Snewton struct svr4_strioctl *ioc; 48483366Sjulian struct thread *td; 48543412Snewton{ 48643412Snewton struct svr4_si_sockparms pa; 48743412Snewton 48843412Snewton getparm(fp, &pa); 48943412Snewton return copyout(&pa, ioc->buf, sizeof(pa)); 49043412Snewton} 49143412Snewton 49243412Snewton 49343412Snewtonstatic int 49483366Sjuliansi_listen(fp, fd, ioc, td) 49543412Snewton struct file *fp; 49643412Snewton int fd; 49743412Snewton struct svr4_strioctl *ioc; 49883366Sjulian struct thread *td; 49943412Snewton{ 50043412Snewton int error; 50143412Snewton struct svr4_strm *st = svr4_stream_get(fp); 50243412Snewton struct svr4_strmcmd lst; 50343412Snewton struct listen_args la; 50443412Snewton 50543412Snewton if (st == NULL) 50643412Snewton return EINVAL; 50743412Snewton 508121275Stjr if (ioc->len < 0 || ioc->len > sizeof(lst)) 509121275Stjr return EINVAL; 510121275Stjr 51143412Snewton if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0) 51243412Snewton return error; 51343412Snewton 51443412Snewton if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) { 51543412Snewton DPRINTF(("si_listen: bad request %ld\n", lst.cmd)); 51643412Snewton return EINVAL; 51743412Snewton } 51843412Snewton 51943412Snewton /* 52043412Snewton * We are making assumptions again... 52143412Snewton */ 522107849Salfred la.s = fd; 52343412Snewton DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5)); 524107849Salfred la.backlog = 5; 52543412Snewton 526225617Skmacy if ((error = sys_listen(td, &la)) != 0) { 52743412Snewton DPRINTF(("SI_LISTEN: listen failed %d\n", error)); 52843412Snewton return error; 52943412Snewton } 53043412Snewton 53143412Snewton st->s_cmd = SVR4_TI__ACCEPT_WAIT; 53243412Snewton lst.cmd = SVR4_TI_BIND_REPLY; 53343412Snewton 53443412Snewton switch (st->s_family) { 53543412Snewton case AF_INET: 53643412Snewton /* XXX: Fill the length here */ 53743412Snewton break; 53843412Snewton 53943412Snewton case AF_LOCAL: 54043412Snewton lst.len = 140; 54143412Snewton lst.pad[28] = 0x00000000; /* magic again */ 54243412Snewton lst.pad[29] = 0x00000800; /* magic again */ 54343412Snewton lst.pad[30] = 0x80001400; /* magic again */ 54443412Snewton break; 54543412Snewton 54643412Snewton default: 54743412Snewton DPRINTF(("SI_LISTEN: Unsupported address family %d\n", 54843412Snewton st->s_family)); 54943412Snewton return ENOSYS; 55043412Snewton } 55143412Snewton 55243412Snewton 55343412Snewton if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0) 55443412Snewton return error; 55543412Snewton 55643412Snewton return 0; 55743412Snewton} 55843412Snewton 55943412Snewton 56043412Snewtonstatic int 56183366Sjuliansi_getudata(fp, fd, ioc, td) 56243412Snewton struct file *fp; 56343412Snewton int fd; 56443412Snewton struct svr4_strioctl *ioc; 56583366Sjulian struct thread *td; 56643412Snewton{ 56743412Snewton int error; 56843412Snewton struct svr4_si_udata ud; 56943412Snewton 57043412Snewton if (sizeof(ud) != ioc->len) { 57143412Snewton DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n", 57243412Snewton sizeof(ud), ioc->len)); 57343412Snewton return EINVAL; 57443412Snewton } 57543412Snewton 57643412Snewton if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 57743412Snewton return error; 57843412Snewton 57943412Snewton getparm(fp, &ud.sockparms); 58043412Snewton 58143412Snewton switch (ud.sockparms.family) { 58243412Snewton case AF_INET: 58343412Snewton DPRINTF(("getudata_inet\n")); 58443412Snewton ud.tidusize = 16384; 58543412Snewton ud.tsdusize = 16384; 58643412Snewton ud.addrsize = sizeof(struct svr4_sockaddr_in); 58743412Snewton if (ud.sockparms.type == SVR4_SOCK_STREAM) 58843412Snewton ud.etsdusize = 1; 58943412Snewton else 59043412Snewton ud.etsdusize = 0; 59143412Snewton ud.optsize = 0; 59243412Snewton break; 59343412Snewton 59443412Snewton case AF_LOCAL: 59543412Snewton DPRINTF(("getudata_local\n")); 59643412Snewton ud.tidusize = 65536; 59743412Snewton ud.tsdusize = 128; 59843412Snewton ud.addrsize = 128; 59943412Snewton ud.etsdusize = 128; 60043412Snewton ud.optsize = 128; 60143412Snewton break; 60243412Snewton 60343412Snewton default: 60443412Snewton DPRINTF(("SI_GETUDATA: Unsupported address family %d\n", 60543412Snewton ud.sockparms.family)); 60643412Snewton return ENOSYS; 60743412Snewton } 60843412Snewton 60943412Snewton 61043412Snewton ud.servtype = ud.sockparms.type; 61143412Snewton DPRINTF(("ud.servtype = %d\n", ud.servtype)); 61243412Snewton /* XXX: Fixme */ 61343412Snewton ud.so_state = 0; 61443412Snewton ud.so_options = 0; 61543412Snewton return copyout(&ud, ioc->buf, sizeof(ud)); 61643412Snewton} 61743412Snewton 61843412Snewton 61943412Snewtonstatic int 62083366Sjuliansi_shutdown(fp, fd, ioc, td) 62143412Snewton struct file *fp; 62243412Snewton int fd; 62343412Snewton struct svr4_strioctl *ioc; 62483366Sjulian struct thread *td; 62543412Snewton{ 62643412Snewton int error; 62743412Snewton struct shutdown_args ap; 62843412Snewton 629107849Salfred if (ioc->len != sizeof(ap.how)) { 63043412Snewton DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n", 631107849Salfred sizeof(ap.how), ioc->len)); 63243412Snewton return EINVAL; 63343412Snewton } 63443412Snewton 635107849Salfred if ((error = copyin(ioc->buf, &ap.how, ioc->len)) != 0) 63643412Snewton return error; 63743412Snewton 638107849Salfred ap.s = fd; 63943412Snewton 640225617Skmacy return sys_shutdown(td, &ap); 64143412Snewton} 64243412Snewton 64343412Snewton 64443412Snewtonstatic int 64583366Sjuliansockmod(fp, fd, ioc, td) 64643412Snewton struct file *fp; 64743412Snewton int fd; 64843412Snewton struct svr4_strioctl *ioc; 64983366Sjulian struct thread *td; 65043412Snewton{ 65143412Snewton switch (ioc->cmd) { 65243412Snewton case SVR4_SI_OGETUDATA: 65343412Snewton DPRINTF(("SI_OGETUDATA\n")); 65483366Sjulian return si_ogetudata(fp, fd, ioc, td); 65543412Snewton 65643412Snewton case SVR4_SI_SHUTDOWN: 65743412Snewton DPRINTF(("SI_SHUTDOWN\n")); 65883366Sjulian return si_shutdown(fp, fd, ioc, td); 65943412Snewton 66043412Snewton case SVR4_SI_LISTEN: 66143412Snewton DPRINTF(("SI_LISTEN\n")); 66283366Sjulian return si_listen(fp, fd, ioc, td); 66343412Snewton 66443412Snewton case SVR4_SI_SETMYNAME: 66543412Snewton DPRINTF(("SI_SETMYNAME\n")); 66643412Snewton return 0; 66743412Snewton 66843412Snewton case SVR4_SI_SETPEERNAME: 66943412Snewton DPRINTF(("SI_SETPEERNAME\n")); 67043412Snewton return 0; 67143412Snewton 67243412Snewton case SVR4_SI_GETINTRANSIT: 67343412Snewton DPRINTF(("SI_GETINTRANSIT\n")); 67443412Snewton return 0; 67543412Snewton 67643412Snewton case SVR4_SI_TCL_LINK: 67743412Snewton DPRINTF(("SI_TCL_LINK\n")); 67843412Snewton return 0; 67943412Snewton 68043412Snewton case SVR4_SI_TCL_UNLINK: 68143412Snewton DPRINTF(("SI_TCL_UNLINK\n")); 68243412Snewton return 0; 68343412Snewton 68443412Snewton case SVR4_SI_SOCKPARAMS: 68543412Snewton DPRINTF(("SI_SOCKPARAMS\n")); 68683366Sjulian return si_sockparams(fp, fd, ioc, td); 68743412Snewton 68843412Snewton case SVR4_SI_GETUDATA: 68943412Snewton DPRINTF(("SI_GETUDATA\n")); 69083366Sjulian return si_getudata(fp, fd, ioc, td); 69143412Snewton 69243412Snewton default: 69343412Snewton DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd)); 69443412Snewton return 0; 69543412Snewton 69643412Snewton } 69743412Snewton} 69843412Snewton 69943412Snewton 70043412Snewtonstatic int 70183366Sjulianti_getinfo(fp, fd, ioc, td) 70243412Snewton struct file *fp; 70343412Snewton int fd; 70443412Snewton struct svr4_strioctl *ioc; 70583366Sjulian struct thread *td; 70643412Snewton{ 70743412Snewton int error; 70843412Snewton struct svr4_infocmd info; 70943412Snewton 71043412Snewton memset(&info, 0, sizeof(info)); 71143412Snewton 712121275Stjr if (ioc->len < 0 || ioc->len > sizeof(info)) 713121275Stjr return EINVAL; 714121275Stjr 71543412Snewton if ((error = copyin(ioc->buf, &info, ioc->len)) != 0) 71643412Snewton return error; 71743412Snewton 71843412Snewton if (info.cmd != SVR4_TI_INFO_REQUEST) 71943412Snewton return EINVAL; 72043412Snewton 72143412Snewton info.cmd = SVR4_TI_INFO_REPLY; 72243412Snewton info.tsdu = 0; 72343412Snewton info.etsdu = 1; 72443412Snewton info.cdata = -2; 72543412Snewton info.ddata = -2; 72643412Snewton info.addr = 16; 72743412Snewton info.opt = -1; 72843412Snewton info.tidu = 16384; 72943412Snewton info.serv = 2; 73043412Snewton info.current = 0; 73143412Snewton info.provider = 2; 73243412Snewton 73343412Snewton ioc->len = sizeof(info); 73443412Snewton if ((error = copyout(&info, ioc->buf, ioc->len)) != 0) 73543412Snewton return error; 73643412Snewton 73743412Snewton return 0; 73843412Snewton} 73943412Snewton 74043412Snewton 74143412Snewtonstatic int 74283366Sjulianti_bind(fp, fd, ioc, td) 74343412Snewton struct file *fp; 74443412Snewton int fd; 74543412Snewton struct svr4_strioctl *ioc; 74683366Sjulian struct thread *td; 74743412Snewton{ 74843412Snewton int error; 74943412Snewton struct svr4_strm *st = svr4_stream_get(fp); 75043412Snewton struct sockaddr_in sain; 75143412Snewton struct sockaddr_un saun; 752160249Sjhb struct sockaddr *skp; 75343412Snewton int sasize; 75443412Snewton struct svr4_strmcmd bnd; 75543412Snewton 75643412Snewton if (st == NULL) { 75743412Snewton DPRINTF(("ti_bind: bad file descriptor\n")); 75843412Snewton return EINVAL; 75943412Snewton } 76043412Snewton 761121275Stjr if (ioc->len < 0 || ioc->len > sizeof(bnd)) 762121275Stjr return EINVAL; 763121275Stjr 76443412Snewton if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0) 76543412Snewton return error; 76643412Snewton 76743412Snewton if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) { 76843412Snewton DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd)); 76943412Snewton return EINVAL; 77043412Snewton } 77143412Snewton 77243412Snewton switch (st->s_family) { 77343412Snewton case AF_INET: 774160249Sjhb skp = (struct sockaddr *)&sain; 77543412Snewton sasize = sizeof(sain); 77643412Snewton 77743412Snewton if (bnd.offs == 0) 778160249Sjhb goto error; 77943412Snewton 78043412Snewton netaddr_to_sockaddr_in(&sain, &bnd); 78143412Snewton 78243412Snewton DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n", 78343412Snewton sain.sin_family, sain.sin_port, 78443412Snewton sain.sin_addr.s_addr)); 78543412Snewton break; 78643412Snewton 78743412Snewton case AF_LOCAL: 788160249Sjhb skp = (struct sockaddr *)&saun; 78943412Snewton sasize = sizeof(saun); 79043412Snewton if (bnd.offs == 0) 791160249Sjhb goto error; 79243412Snewton 79343412Snewton netaddr_to_sockaddr_un(&saun, &bnd); 79443412Snewton 79543412Snewton if (saun.sun_path[0] == '\0') 796160249Sjhb goto error; 79743412Snewton 79843412Snewton DPRINTF(("TI_BIND: fam %d, path %s\n", 79943412Snewton saun.sun_family, saun.sun_path)); 80043412Snewton 80183366Sjulian if ((error = clean_pipe(td, saun.sun_path)) != 0) 80243412Snewton return error; 80343412Snewton 80443412Snewton bnd.pad[28] = 0x00001000; /* magic again */ 80543412Snewton break; 80643412Snewton 80743412Snewton default: 80843412Snewton DPRINTF(("TI_BIND: Unsupported address family %d\n", 80943412Snewton st->s_family)); 81043412Snewton return ENOSYS; 81143412Snewton } 81243412Snewton 81343412Snewton DPRINTF(("TI_BIND: fileno %d\n", fd)); 81443412Snewton 815160249Sjhb if ((error = kern_bind(td, fd, skp)) != 0) { 81643412Snewton DPRINTF(("TI_BIND: bind failed %d\n", error)); 81743412Snewton return error; 81843412Snewton } 819160249Sjhb goto reply; 82043412Snewton 821160249Sjhberror: 822160249Sjhb memset(&bnd, 0, sizeof(bnd)); 823160249Sjhb bnd.len = sasize + 4; 824160249Sjhb bnd.offs = 0x10; /* XXX */ 825160249Sjhb 82643412Snewtonreply: 82743412Snewton bnd.cmd = SVR4_TI_BIND_REPLY; 82843412Snewton 82943412Snewton if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0) 83043412Snewton return error; 83143412Snewton 83243412Snewton return 0; 83343412Snewton} 83443412Snewton 83543412Snewton 83643412Snewtonstatic int 83783366Sjuliantimod(fp, fd, ioc, td) 83843412Snewton struct file *fp; 83943412Snewton int fd; 84043412Snewton struct svr4_strioctl *ioc; 84183366Sjulian struct thread *td; 84243412Snewton{ 84343412Snewton switch (ioc->cmd) { 84443412Snewton case SVR4_TI_GETINFO: 84543412Snewton DPRINTF(("TI_GETINFO\n")); 84683366Sjulian return ti_getinfo(fp, fd, ioc, td); 84743412Snewton 84843412Snewton case SVR4_TI_OPTMGMT: 84943412Snewton DPRINTF(("TI_OPTMGMT\n")); 85043412Snewton return 0; 85143412Snewton 85243412Snewton case SVR4_TI_BIND: 85343412Snewton DPRINTF(("TI_BIND\n")); 85483366Sjulian return ti_bind(fp, fd, ioc, td); 85543412Snewton 85643412Snewton case SVR4_TI_UNBIND: 85743412Snewton DPRINTF(("TI_UNBIND\n")); 85843412Snewton return 0; 85943412Snewton 86043412Snewton default: 86143412Snewton DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd)); 86243412Snewton return 0; 86343412Snewton } 86443412Snewton} 86543412Snewton 86643412Snewton 86743412Snewtonint 86883366Sjuliansvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat) 86943412Snewton struct file *fp; 87083366Sjulian struct thread *td; 87143412Snewton register_t *retval; 87243412Snewton int fd; 87343412Snewton u_long cmd; 87443412Snewton caddr_t dat; 87543412Snewton{ 87643412Snewton struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat; 87743412Snewton struct svr4_strm *st = svr4_stream_get(fp); 87843412Snewton int error; 879160249Sjhb struct sockaddr *sa; 880160249Sjhb socklen_t sasize, oldsasize; 88143412Snewton struct svr4_strmcmd sc; 88243412Snewton 88343412Snewton DPRINTF(("svr4_stream_ti_ioctl\n")); 88443412Snewton 88543412Snewton if (st == NULL) 88643412Snewton return EINVAL; 88743412Snewton 88843412Snewton sc.offs = 0x10; 88943412Snewton 89043412Snewton if ((error = copyin(sub, &skb, sizeof(skb))) != 0) { 89143412Snewton DPRINTF(("ti_ioctl: error copying in strbuf\n")); 89243412Snewton return error; 89343412Snewton } 89443412Snewton 89543412Snewton switch (st->s_family) { 89643412Snewton case AF_INET: 897160249Sjhb sasize = sizeof(struct sockaddr_in); 89843412Snewton break; 89943412Snewton 90043412Snewton case AF_LOCAL: 901160249Sjhb sasize = sizeof(struct sockaddr_un); 90243412Snewton break; 90343412Snewton 90443412Snewton default: 90543412Snewton DPRINTF(("ti_ioctl: Unsupported address family %d\n", 90643412Snewton st->s_family)); 90743412Snewton return ENOSYS; 90843412Snewton } 909160249Sjhb oldsasize = sasize; 91043412Snewton 91143412Snewton switch (cmd) { 91243412Snewton case SVR4_TI_GETMYNAME: 91343412Snewton DPRINTF(("TI_GETMYNAME\n")); 91443412Snewton { 915160249Sjhb error = kern_getsockname(td, fd, &sa, &sasize); 916160249Sjhb if (error) { 91743412Snewton DPRINTF(("ti_ioctl: getsockname error\n")); 91843412Snewton return error; 91943412Snewton } 92043412Snewton } 92143412Snewton break; 92243412Snewton 92343412Snewton case SVR4_TI_GETPEERNAME: 92443412Snewton DPRINTF(("TI_GETPEERNAME\n")); 92543412Snewton { 926160249Sjhb error = kern_getpeername(td, fd, &sa, &sasize); 927160249Sjhb if (error) { 92843412Snewton DPRINTF(("ti_ioctl: getpeername error\n")); 92943412Snewton return error; 93043412Snewton } 93143412Snewton } 93243412Snewton break; 93343412Snewton 93443412Snewton case SVR4_TI_SETMYNAME: 93543412Snewton DPRINTF(("TI_SETMYNAME\n")); 93643412Snewton return 0; 93743412Snewton 93843412Snewton case SVR4_TI_SETPEERNAME: 93943412Snewton DPRINTF(("TI_SETPEERNAME\n")); 94043412Snewton return 0; 94143412Snewton default: 94243412Snewton DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd)); 94343412Snewton return ENOSYS; 94443412Snewton } 94543412Snewton 946160249Sjhb if (sasize < 0 || sasize > oldsasize) { 947160249Sjhb free(sa, M_SONAME); 948160249Sjhb return EINVAL; 94943412Snewton } 95043412Snewton 95143412Snewton switch (st->s_family) { 95243412Snewton case AF_INET: 953160249Sjhb sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa); 95443412Snewton skb.len = sasize; 95543412Snewton break; 95643412Snewton 95743412Snewton case AF_LOCAL: 958160249Sjhb sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa); 95943412Snewton skb.len = sasize + 4; 96043412Snewton break; 96143412Snewton 96243412Snewton default: 963160249Sjhb free(sa, M_SONAME); 96443412Snewton return ENOSYS; 96543412Snewton } 966160249Sjhb free(sa, M_SONAME); 96743412Snewton 96843412Snewton if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) { 96943412Snewton DPRINTF(("ti_ioctl: error copying out socket data\n")); 97043412Snewton return error; 97143412Snewton } 97243412Snewton 97343412Snewton 97443412Snewton if ((error = copyout(&skb, sub, sizeof(skb))) != 0) { 97543412Snewton DPRINTF(("ti_ioctl: error copying out strbuf\n")); 97643412Snewton return error; 97743412Snewton } 97843412Snewton 97943412Snewton return error; 98043412Snewton} 98143412Snewton 98243412Snewton 98343412Snewton 98443412Snewton 98543412Snewtonstatic int 98683366Sjuliani_nread(fp, td, retval, fd, cmd, dat) 98743412Snewton struct file *fp; 98883366Sjulian struct thread *td; 98943412Snewton register_t *retval; 99043412Snewton int fd; 99143412Snewton u_long cmd; 99243412Snewton caddr_t dat; 99343412Snewton{ 99443412Snewton int error; 99543412Snewton int nread = 0; 99643412Snewton 99743412Snewton /* 99843412Snewton * We are supposed to return the message length in nread, and the 99943412Snewton * number of messages in retval. We don't have the notion of number 100043412Snewton * of stream messages, so we just find out if we have any bytes waiting 100143412Snewton * for us, and if we do, then we assume that we have at least one 100243412Snewton * message waiting for us. 100343412Snewton */ 1004102003Srwatson if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td->td_ucred, 1005102003Srwatson td)) != 0) 100643412Snewton return error; 100743412Snewton 100843412Snewton if (nread != 0) 100943412Snewton *retval = 1; 101043412Snewton else 101143412Snewton *retval = 0; 101243412Snewton 101343412Snewton return copyout(&nread, dat, sizeof(nread)); 101443412Snewton} 101543412Snewton 101643412Snewtonstatic int 101783366Sjuliani_fdinsert(fp, td, retval, fd, cmd, dat) 101843412Snewton struct file *fp; 101983366Sjulian struct thread *td; 102043412Snewton register_t *retval; 102143412Snewton int fd; 102243412Snewton u_long cmd; 102343412Snewton caddr_t dat; 102443412Snewton{ 102543412Snewton /* 102643412Snewton * Major hack again here. We assume that we are using this to 102743412Snewton * implement accept(2). If that is the case, we have already 102843412Snewton * called accept, and we have stored the file descriptor in 102943412Snewton * afd. We find the file descriptor that the code wants to use 103043412Snewton * in fd insert, and then we dup2() our accepted file descriptor 103143412Snewton * to it. 103243412Snewton */ 103343412Snewton int error; 103443412Snewton struct svr4_strm *st = svr4_stream_get(fp); 103543412Snewton struct svr4_strfdinsert fdi; 103643412Snewton struct dup2_args d2p; 103743412Snewton 103843412Snewton if (st == NULL) { 103943412Snewton DPRINTF(("fdinsert: bad file type\n")); 104043412Snewton return EINVAL; 104143412Snewton } 104243412Snewton 1043160794Sjhb mtx_lock(&Giant); 104443412Snewton if (st->s_afd == -1) { 104543412Snewton DPRINTF(("fdinsert: accept fd not found\n")); 1046160794Sjhb mtx_unlock(&Giant); 104743412Snewton return ENOENT; 104843412Snewton } 104943412Snewton 105043412Snewton if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) { 105143412Snewton DPRINTF(("fdinsert: copyin failed %d\n", error)); 1052160794Sjhb mtx_unlock(&Giant); 105343412Snewton return error; 105443412Snewton } 105543412Snewton 1056107849Salfred d2p.from = st->s_afd; 1057107849Salfred d2p.to = fdi.fd; 105843412Snewton 1059225617Skmacy if ((error = sys_dup2(td, &d2p)) != 0) { 106043412Snewton DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n", 106143412Snewton st->s_afd, fdi.fd, error)); 1062160794Sjhb mtx_unlock(&Giant); 106343412Snewton return error; 106443412Snewton } 106543412Snewton 1066160249Sjhb if ((error = kern_close(td, st->s_afd)) != 0) { 106743412Snewton DPRINTF(("fdinsert: close(%d) failed %d\n", 106843412Snewton st->s_afd, error)); 1069160794Sjhb mtx_unlock(&Giant); 107043412Snewton return error; 107143412Snewton } 107243412Snewton 107343412Snewton st->s_afd = -1; 1074160794Sjhb mtx_unlock(&Giant); 107543412Snewton 107643412Snewton *retval = 0; 107743412Snewton return 0; 107843412Snewton} 107943412Snewton 108043412Snewton 108143412Snewtonstatic int 108283366Sjulian_i_bind_rsvd(fp, td, retval, fd, cmd, dat) 108343412Snewton struct file *fp; 108483366Sjulian struct thread *td; 108543412Snewton register_t *retval; 108643412Snewton int fd; 108743412Snewton u_long cmd; 108843412Snewton caddr_t dat; 108943412Snewton{ 109043412Snewton struct mkfifo_args ap; 109143412Snewton 109243412Snewton /* 109343412Snewton * This is a supposed to be a kernel and library only ioctl. 109443412Snewton * It gets called before ti_bind, when we have a unix 109543412Snewton * socket, to physically create the socket transport and 109643412Snewton * ``reserve'' it. I don't know how this get reserved inside 109743412Snewton * the kernel, but we are going to create it nevertheless. 109843412Snewton */ 1099107849Salfred ap.path = dat; 1100107849Salfred ap.mode = S_IFIFO; 110143412Snewton 1102225617Skmacy return sys_mkfifo(td, &ap); 110343412Snewton} 110443412Snewton 110543412Snewtonstatic int 110683366Sjulian_i_rele_rsvd(fp, td, retval, fd, cmd, dat) 110743412Snewton struct file *fp; 110883366Sjulian struct thread *td; 110943412Snewton register_t *retval; 111043412Snewton int fd; 111143412Snewton u_long cmd; 111243412Snewton caddr_t dat; 111343412Snewton{ 111443412Snewton struct unlink_args ap; 111543412Snewton 111643412Snewton /* 111743412Snewton * This is a supposed to be a kernel and library only ioctl. 111843412Snewton * I guess it is supposed to release the socket. 111943412Snewton */ 1120107849Salfred ap.path = dat; 112143412Snewton 1122225617Skmacy return sys_unlink(td, &ap); 112343412Snewton} 112443412Snewton 112543412Snewtonstatic int 112683366Sjuliani_str(fp, td, retval, fd, cmd, dat) 112743412Snewton struct file *fp; 112883366Sjulian struct thread *td; 112943412Snewton register_t *retval; 113043412Snewton int fd; 113143412Snewton u_long cmd; 113243412Snewton caddr_t dat; 113343412Snewton{ 113443412Snewton int error; 113543412Snewton struct svr4_strioctl ioc; 113643412Snewton 113743412Snewton if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0) 113843412Snewton return error; 113943412Snewton 114043412Snewton#ifdef DEBUG_SVR4 1141150663Srwatson if ((error = show_ioc(">", &ioc)) != 0) 114243412Snewton return error; 114343412Snewton#endif /* DEBUG_SVR4 */ 114443412Snewton 114543412Snewton switch (ioc.cmd & 0xff00) { 114643412Snewton case SVR4_SIMOD: 114783366Sjulian if ((error = sockmod(fp, fd, &ioc, td)) != 0) 114843412Snewton return error; 114943412Snewton break; 115043412Snewton 115143412Snewton case SVR4_TIMOD: 115283366Sjulian if ((error = timod(fp, fd, &ioc, td)) != 0) 115343412Snewton return error; 115443412Snewton break; 115543412Snewton 115643412Snewton default: 115743412Snewton DPRINTF(("Unimplemented module %c %ld\n", 115843412Snewton (char) (cmd >> 8), cmd & 0xff)); 115943412Snewton return 0; 116043412Snewton } 116143412Snewton 116243412Snewton#ifdef DEBUG_SVR4 1163150663Srwatson if ((error = show_ioc("<", &ioc)) != 0) 116443412Snewton return error; 116543412Snewton#endif /* DEBUG_SVR4 */ 116643412Snewton return copyout(&ioc, dat, sizeof(ioc)); 116743412Snewton} 116843412Snewton 116943412Snewtonstatic int 117083366Sjuliani_setsig(fp, td, retval, fd, cmd, dat) 117143412Snewton struct file *fp; 117283366Sjulian struct thread *td; 117343412Snewton register_t *retval; 117443412Snewton int fd; 117543412Snewton u_long cmd; 117643412Snewton caddr_t dat; 117743412Snewton{ 117843412Snewton /* 117943412Snewton * This is the best we can do for now; we cannot generate 118043412Snewton * signals only for specific events so the signal mask gets 118143412Snewton * ignored; we save it just to pass it to a possible I_GETSIG... 118243412Snewton * 118343412Snewton * We alse have to fix the O_ASYNC fcntl bit, so the 118443412Snewton * process will get SIGPOLLs. 118543412Snewton */ 118643412Snewton int error; 118743412Snewton register_t oflags, flags; 118843412Snewton struct svr4_strm *st = svr4_stream_get(fp); 118943412Snewton 119043412Snewton if (st == NULL) { 119143412Snewton DPRINTF(("i_setsig: bad file descriptor\n")); 119243412Snewton return EINVAL; 119343412Snewton } 119443412Snewton /* get old status flags */ 1195134266Sjhb error = kern_fcntl(td, fd, F_GETFL, 0); 1196134266Sjhb if (error) 1197134266Sjhb return (error); 119843412Snewton 119983366Sjulian oflags = td->td_retval[0]; 120043412Snewton 120143412Snewton /* update the flags */ 1202160794Sjhb mtx_lock(&Giant); 120343412Snewton if (dat != NULL) { 120443412Snewton int mask; 120543412Snewton 120643412Snewton flags = oflags | O_ASYNC; 120743412Snewton if ((error = copyin(dat, &mask, sizeof(mask))) != 0) { 120843412Snewton DPRINTF(("i_setsig: bad eventmask pointer\n")); 120943412Snewton return error; 121043412Snewton } 121143412Snewton if (mask & SVR4_S_ALLMASK) { 121243412Snewton DPRINTF(("i_setsig: bad eventmask data %x\n", mask)); 121343412Snewton return EINVAL; 121443412Snewton } 121543412Snewton st->s_eventmask = mask; 121643412Snewton } 121743412Snewton else { 121843412Snewton flags = oflags & ~O_ASYNC; 121943412Snewton st->s_eventmask = 0; 122043412Snewton } 1221160794Sjhb mtx_unlock(&Giant); 122243412Snewton 122343412Snewton /* set the new flags, if changed */ 122443412Snewton if (flags != oflags) { 1225134266Sjhb error = kern_fcntl(td, fd, F_SETFL, flags); 1226134266Sjhb if (error) 1227134266Sjhb return (error); 122883366Sjulian flags = td->td_retval[0]; 122943412Snewton } 123043412Snewton 123143412Snewton /* set up SIGIO receiver if needed */ 1232134266Sjhb if (dat != NULL) 1233134266Sjhb return (kern_fcntl(td, fd, F_SETOWN, td->td_proc->p_pid)); 123443412Snewton return 0; 123543412Snewton} 123643412Snewton 123743412Snewtonstatic int 123883366Sjuliani_getsig(fp, td, retval, fd, cmd, dat) 123943412Snewton struct file *fp; 124083366Sjulian struct thread *td; 124143412Snewton register_t *retval; 124243412Snewton int fd; 124343412Snewton u_long cmd; 124443412Snewton caddr_t dat; 124543412Snewton{ 1246160794Sjhb int error, eventmask; 124743412Snewton 124843412Snewton if (dat != NULL) { 124943412Snewton struct svr4_strm *st = svr4_stream_get(fp); 125043412Snewton 125143412Snewton if (st == NULL) { 125243412Snewton DPRINTF(("i_getsig: bad file descriptor\n")); 125343412Snewton return EINVAL; 125443412Snewton } 1255160794Sjhb mtx_lock(&Giant); 1256160794Sjhb eventmask = st->s_eventmask; 1257160794Sjhb mtx_unlock(&Giant); 1258160794Sjhb if ((error = copyout(&eventmask, dat, 1259160794Sjhb sizeof(eventmask))) != 0) { 126043412Snewton DPRINTF(("i_getsig: bad eventmask pointer\n")); 126143412Snewton return error; 126243412Snewton } 126343412Snewton } 126443412Snewton return 0; 126543412Snewton} 126643412Snewton 126743412Snewtonint 126883366Sjuliansvr4_stream_ioctl(fp, td, retval, fd, cmd, dat) 126943412Snewton struct file *fp; 127083366Sjulian struct thread *td; 127143412Snewton register_t *retval; 127243412Snewton int fd; 127343412Snewton u_long cmd; 127443412Snewton caddr_t dat; 127543412Snewton{ 127643412Snewton *retval = 0; 127743412Snewton 127843412Snewton /* 127943412Snewton * All the following stuff assumes "sockmod" is pushed... 128043412Snewton */ 128143412Snewton switch (cmd) { 128243412Snewton case SVR4_I_NREAD: 128343412Snewton DPRINTF(("I_NREAD\n")); 128483366Sjulian return i_nread(fp, td, retval, fd, cmd, dat); 128543412Snewton 128643412Snewton case SVR4_I_PUSH: 128780114Sassar DPRINTF(("I_PUSH %p\n", dat)); 128843412Snewton#if defined(DEBUG_SVR4) 128980114Sassar show_strbuf((struct svr4_strbuf *)dat); 129043412Snewton#endif 129143412Snewton return 0; 129243412Snewton 129343412Snewton case SVR4_I_POP: 129443412Snewton DPRINTF(("I_POP\n")); 129543412Snewton return 0; 129643412Snewton 129743412Snewton case SVR4_I_LOOK: 129843412Snewton DPRINTF(("I_LOOK\n")); 129943412Snewton return 0; 130043412Snewton 130143412Snewton case SVR4_I_FLUSH: 130243412Snewton DPRINTF(("I_FLUSH\n")); 130343412Snewton return 0; 130443412Snewton 130543412Snewton case SVR4_I_SRDOPT: 130643412Snewton DPRINTF(("I_SRDOPT\n")); 130743412Snewton return 0; 130843412Snewton 130943412Snewton case SVR4_I_GRDOPT: 131043412Snewton DPRINTF(("I_GRDOPT\n")); 131143412Snewton return 0; 131243412Snewton 131343412Snewton case SVR4_I_STR: 131443412Snewton DPRINTF(("I_STR\n")); 131583366Sjulian return i_str(fp, td, retval, fd, cmd, dat); 131643412Snewton 131743412Snewton case SVR4_I_SETSIG: 131843412Snewton DPRINTF(("I_SETSIG\n")); 131983366Sjulian return i_setsig(fp, td, retval, fd, cmd, dat); 132043412Snewton 132143412Snewton case SVR4_I_GETSIG: 132243412Snewton DPRINTF(("I_GETSIG\n")); 132383366Sjulian return i_getsig(fp, td, retval, fd, cmd, dat); 132443412Snewton 132543412Snewton case SVR4_I_FIND: 132643412Snewton DPRINTF(("I_FIND\n")); 132743412Snewton /* 132843412Snewton * Here we are not pushing modules really, we just 132943412Snewton * pretend all are present 133043412Snewton */ 133143412Snewton *retval = 0; 133243412Snewton return 0; 133343412Snewton 133443412Snewton case SVR4_I_LINK: 133543412Snewton DPRINTF(("I_LINK\n")); 133643412Snewton return 0; 133743412Snewton 133843412Snewton case SVR4_I_UNLINK: 133943412Snewton DPRINTF(("I_UNLINK\n")); 134043412Snewton return 0; 134143412Snewton 134243412Snewton case SVR4_I_ERECVFD: 134343412Snewton DPRINTF(("I_ERECVFD\n")); 134443412Snewton return 0; 134543412Snewton 134643412Snewton case SVR4_I_PEEK: 134743412Snewton DPRINTF(("I_PEEK\n")); 134843412Snewton return 0; 134943412Snewton 135043412Snewton case SVR4_I_FDINSERT: 135143412Snewton DPRINTF(("I_FDINSERT\n")); 135283366Sjulian return i_fdinsert(fp, td, retval, fd, cmd, dat); 135343412Snewton 135443412Snewton case SVR4_I_SENDFD: 135543412Snewton DPRINTF(("I_SENDFD\n")); 135643412Snewton return 0; 135743412Snewton 135843412Snewton case SVR4_I_RECVFD: 135943412Snewton DPRINTF(("I_RECVFD\n")); 136043412Snewton return 0; 136143412Snewton 136243412Snewton case SVR4_I_SWROPT: 136343412Snewton DPRINTF(("I_SWROPT\n")); 136443412Snewton return 0; 136543412Snewton 136643412Snewton case SVR4_I_GWROPT: 136743412Snewton DPRINTF(("I_GWROPT\n")); 136843412Snewton return 0; 136943412Snewton 137043412Snewton case SVR4_I_LIST: 137143412Snewton DPRINTF(("I_LIST\n")); 137243412Snewton return 0; 137343412Snewton 137443412Snewton case SVR4_I_PLINK: 137543412Snewton DPRINTF(("I_PLINK\n")); 137643412Snewton return 0; 137743412Snewton 137843412Snewton case SVR4_I_PUNLINK: 137943412Snewton DPRINTF(("I_PUNLINK\n")); 138043412Snewton return 0; 138143412Snewton 138243412Snewton case SVR4_I_SETEV: 138343412Snewton DPRINTF(("I_SETEV\n")); 138443412Snewton return 0; 138543412Snewton 138643412Snewton case SVR4_I_GETEV: 138743412Snewton DPRINTF(("I_GETEV\n")); 138843412Snewton return 0; 138943412Snewton 139043412Snewton case SVR4_I_STREV: 139143412Snewton DPRINTF(("I_STREV\n")); 139243412Snewton return 0; 139343412Snewton 139443412Snewton case SVR4_I_UNSTREV: 139543412Snewton DPRINTF(("I_UNSTREV\n")); 139643412Snewton return 0; 139743412Snewton 139843412Snewton case SVR4_I_FLUSHBAND: 139943412Snewton DPRINTF(("I_FLUSHBAND\n")); 140043412Snewton return 0; 140143412Snewton 140243412Snewton case SVR4_I_CKBAND: 140343412Snewton DPRINTF(("I_CKBAND\n")); 140443412Snewton return 0; 140543412Snewton 140643412Snewton case SVR4_I_GETBAND: 140743412Snewton DPRINTF(("I_GETBANK\n")); 140843412Snewton return 0; 140943412Snewton 141043412Snewton case SVR4_I_ATMARK: 141143412Snewton DPRINTF(("I_ATMARK\n")); 141243412Snewton return 0; 141343412Snewton 141443412Snewton case SVR4_I_SETCLTIME: 141543412Snewton DPRINTF(("I_SETCLTIME\n")); 141643412Snewton return 0; 141743412Snewton 141843412Snewton case SVR4_I_GETCLTIME: 141943412Snewton DPRINTF(("I_GETCLTIME\n")); 142043412Snewton return 0; 142143412Snewton 142243412Snewton case SVR4_I_CANPUT: 142343412Snewton DPRINTF(("I_CANPUT\n")); 142443412Snewton return 0; 142543412Snewton 142643412Snewton case SVR4__I_BIND_RSVD: 142743412Snewton DPRINTF(("_I_BIND_RSVD\n")); 142883366Sjulian return _i_bind_rsvd(fp, td, retval, fd, cmd, dat); 142943412Snewton 143043412Snewton case SVR4__I_RELE_RSVD: 143143412Snewton DPRINTF(("_I_RELE_RSVD\n")); 143283366Sjulian return _i_rele_rsvd(fp, td, retval, fd, cmd, dat); 143343412Snewton 143443412Snewton default: 143543412Snewton DPRINTF(("unimpl cmd = %lx\n", cmd)); 143643412Snewton break; 143743412Snewton } 143843412Snewton 143943412Snewton return 0; 144043412Snewton} 144143412Snewton 144243412Snewton 144343412Snewton 144443412Snewtonint 144583366Sjuliansvr4_sys_putmsg(td, uap) 1446193014Sdelphij struct thread *td; 144743412Snewton struct svr4_sys_putmsg_args *uap; 144843412Snewton{ 1449255219Spjd cap_rights_t rights; 1450255219Spjd struct file *fp; 145189306Salfred int error; 145289306Salfred 1453255219Spjd error = fget(td, uap->fd, cap_rights_init(&rights, CAP_SEND), &fp); 1454255219Spjd if (error != 0) { 145589306Salfred#ifdef DEBUG_SVR4 145689306Salfred uprintf("putmsg: bad fp\n"); 145789306Salfred#endif 145889306Salfred return EBADF; 145989306Salfred } 146089306Salfred error = svr4_do_putmsg(td, uap, fp); 146189306Salfred fdrop(fp, td); 146289306Salfred return (error); 146389306Salfred} 146489306Salfred 146589306Salfredstatic int 146689306Salfredsvr4_do_putmsg(td, uap, fp) 146789306Salfred struct thread *td; 146889306Salfred struct svr4_sys_putmsg_args *uap; 146943412Snewton struct file *fp; 147089306Salfred{ 147143412Snewton struct svr4_strbuf dat, ctl; 147243412Snewton struct svr4_strmcmd sc; 147343412Snewton struct sockaddr_in sain; 147443412Snewton struct sockaddr_un saun; 1475160249Sjhb struct sockaddr *sa; 147643412Snewton int sasize, *retval; 147743412Snewton struct svr4_strm *st; 147843412Snewton int error; 147943412Snewton 148083366Sjulian retval = td->td_retval; 148154493Snewton 148243412Snewton#ifdef DEBUG_SVR4 1483107849Salfred show_msg(">putmsg", uap->fd, uap->ctl, 1484107849Salfred uap->dat, uap->flags); 148543412Snewton#endif /* DEBUG_SVR4 */ 148643412Snewton 1487107849Salfred if (uap->ctl != NULL) { 1488107849Salfred if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) { 148943412Snewton#ifdef DEBUG_SVR4 149043412Snewton uprintf("putmsg: copyin(): %d\n", error); 149143412Snewton#endif 149243412Snewton return error; 149343412Snewton } 149443412Snewton } 149543412Snewton else 149643412Snewton ctl.len = -1; 149743412Snewton 1498107849Salfred if (uap->dat != NULL) { 1499107849Salfred if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) { 150043412Snewton#ifdef DEBUG_SVR4 150143412Snewton uprintf("putmsg: copyin(): %d (2)\n", error); 150243412Snewton#endif 150343412Snewton return error; 150443412Snewton } 150543412Snewton } 150643412Snewton else 150743412Snewton dat.len = -1; 150843412Snewton 150943412Snewton /* 151043412Snewton * Only for sockets for now. 151143412Snewton */ 151243412Snewton if ((st = svr4_stream_get(fp)) == NULL) { 151343412Snewton DPRINTF(("putmsg: bad file type\n")); 151443412Snewton return EINVAL; 151543412Snewton } 151643412Snewton 1517121275Stjr if (ctl.len < 0 || ctl.len > sizeof(sc)) { 151843412Snewton DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len, 151943412Snewton sizeof(struct svr4_strmcmd))); 152043412Snewton return EINVAL; 152143412Snewton } 152243412Snewton 152343412Snewton if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 152443412Snewton return error; 152543412Snewton 152643412Snewton switch (st->s_family) { 152743412Snewton case AF_INET: 152843412Snewton if (sc.len != sizeof(sain)) { 152943412Snewton if (sc.cmd == SVR4_TI_DATA_REQUEST) { 153043412Snewton struct write_args wa; 153143412Snewton 153243412Snewton /* Solaris seems to use sc.cmd = 3 to 153343412Snewton * send "expedited" data. telnet uses 153443412Snewton * this for options processing, sending EOF, 153543412Snewton * etc. I'm sure other things use it too. 153643412Snewton * I don't have any documentation 153743412Snewton * on it, so I'm making a guess that this 153843412Snewton * is how it works. newton@atdot.dotat.org XXX 153943412Snewton */ 154051844Speter DPRINTF(("sending expedited data ??\n")); 1541107849Salfred wa.fd = uap->fd; 1542107849Salfred wa.buf = dat.buf; 1543107849Salfred wa.nbyte = dat.len; 1544225617Skmacy return sys_write(td, &wa); 154543412Snewton } 154643412Snewton DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len)); 154743412Snewton return EINVAL; 154843412Snewton } 154943412Snewton netaddr_to_sockaddr_in(&sain, &sc); 1550160249Sjhb sa = (struct sockaddr *)&sain; 155143412Snewton sasize = sizeof(sain); 1552160249Sjhb if (sain.sin_family != st->s_family) 1553160249Sjhb error = EINVAL; 155443412Snewton break; 155543412Snewton 155643412Snewton case AF_LOCAL: 155743412Snewton if (ctl.len == 8) { 155843412Snewton /* We are doing an accept; succeed */ 155943412Snewton DPRINTF(("putmsg: Do nothing\n")); 156043412Snewton *retval = 0; 156143412Snewton return 0; 156243412Snewton } 156343412Snewton else { 156443412Snewton /* Maybe we've been given a device/inode pair */ 1565130640Sphk dev_t *dev = SVR4_ADDROF(&sc); 156643412Snewton ino_t *ino = (ino_t *) &dev[1]; 1567160558Sjhb if (svr4_find_socket(td, fp, *dev, *ino, &saun) != 0) { 156843412Snewton /* I guess we have it by name */ 1569160249Sjhb netaddr_to_sockaddr_un(&saun, &sc); 157043412Snewton } 1571160558Sjhb sa = (struct sockaddr *)&saun; 157243412Snewton sasize = sizeof(saun); 157343412Snewton } 157443412Snewton break; 157543412Snewton 157643412Snewton default: 157743412Snewton DPRINTF(("putmsg: Unsupported address family %d\n", 157843412Snewton st->s_family)); 157943412Snewton return ENOSYS; 158043412Snewton } 158143412Snewton 1582160794Sjhb mtx_lock(&Giant); 1583160794Sjhb st->s_cmd = sc.cmd; 1584160794Sjhb mtx_unlock(&Giant); 1585160794Sjhb switch (sc.cmd) { 158643412Snewton case SVR4_TI_CONNECT_REQUEST: /* connect */ 158743412Snewton { 158843412Snewton 1589160249Sjhb return (kern_connect(td, uap->fd, sa)); 159043412Snewton } 159143412Snewton 159243412Snewton case SVR4_TI_SENDTO_REQUEST: /* sendto */ 159343412Snewton { 159443412Snewton struct msghdr msg; 159543412Snewton struct iovec aiov; 159643412Snewton 1597160249Sjhb msg.msg_name = sa; 159843412Snewton msg.msg_namelen = sasize; 159943412Snewton msg.msg_iov = &aiov; 160043412Snewton msg.msg_iovlen = 1; 160143412Snewton msg.msg_control = 0; 160243412Snewton msg.msg_flags = 0; 160343412Snewton aiov.iov_base = dat.buf; 160443412Snewton aiov.iov_len = dat.len; 1605160249Sjhb error = kern_sendit(td, uap->fd, &msg, uap->flags, 1606160249Sjhb NULL, UIO_USERSPACE); 160743412Snewton DPRINTF(("sendto_request error: %d\n", error)); 160843412Snewton *retval = 0; 160943412Snewton return error; 161043412Snewton } 161143412Snewton 161243412Snewton default: 161343412Snewton DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd)); 161443412Snewton return ENOSYS; 161543412Snewton } 161643412Snewton} 161743412Snewton 161843412Snewtonint 161989308Salfredsvr4_sys_getmsg(td, uap) 162089308Salfred struct thread *td; 162189306Salfred struct svr4_sys_getmsg_args *uap; 162289306Salfred{ 1623255219Spjd cap_rights_t rights; 1624255219Spjd struct file *fp; 162589306Salfred int error; 162689306Salfred 1627255219Spjd error = fget(td, uap->fd, cap_rights_init(&rights, CAP_RECV), &fp); 1628255219Spjd if (error != 0) { 162989306Salfred#ifdef DEBUG_SVR4 163089306Salfred uprintf("getmsg: bad fp\n"); 163189306Salfred#endif 163289306Salfred return EBADF; 163389306Salfred } 163489308Salfred error = svr4_do_getmsg(td, uap, fp); 163589306Salfred fdrop(fp, td); 163689306Salfred return (error); 163789306Salfred} 163889306Salfred 163989306Salfredint 164089536Salfredsvr4_do_getmsg(td, uap, fp) 1641193014Sdelphij struct thread *td; 164243412Snewton struct svr4_sys_getmsg_args *uap; 164389306Salfred struct file *fp; 164443412Snewton{ 164543412Snewton struct svr4_strbuf dat, ctl; 164643412Snewton struct svr4_strmcmd sc; 164743412Snewton int error, *retval; 164843412Snewton struct msghdr msg; 164943412Snewton struct iovec aiov; 165043412Snewton struct sockaddr_in sain; 165143412Snewton struct sockaddr_un saun; 1652160249Sjhb struct sockaddr *sa; 1653160249Sjhb socklen_t sasize; 165443412Snewton struct svr4_strm *st; 1655160765Sjhb struct file *afp; 165643412Snewton int fl; 165743412Snewton 165883366Sjulian retval = td->td_retval; 1659160249Sjhb error = 0; 1660160765Sjhb afp = NULL; 166154493Snewton 166243412Snewton memset(&sc, 0, sizeof(sc)); 166343412Snewton 166443412Snewton#ifdef DEBUG_SVR4 1665107849Salfred show_msg(">getmsg", uap->fd, uap->ctl, 1666107849Salfred uap->dat, 0); 166743412Snewton#endif /* DEBUG_SVR4 */ 166843412Snewton 1669107849Salfred if (uap->ctl != NULL) { 1670107849Salfred if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) 167143412Snewton return error; 1672121275Stjr if (ctl.len < 0) 1673121275Stjr return EINVAL; 167443412Snewton } 167543412Snewton else { 167643412Snewton ctl.len = -1; 167743412Snewton ctl.maxlen = 0; 167843412Snewton } 167943412Snewton 1680107849Salfred if (uap->dat != NULL) { 1681107849Salfred if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) 168243412Snewton return error; 168343412Snewton } 168443412Snewton else { 168543412Snewton dat.len = -1; 168643412Snewton dat.maxlen = 0; 168743412Snewton } 168843412Snewton 168943412Snewton /* 169043412Snewton * Only for sockets for now. 169143412Snewton */ 169243412Snewton if ((st = svr4_stream_get(fp)) == NULL) { 169343412Snewton DPRINTF(("getmsg: bad file type\n")); 169443412Snewton return EINVAL; 169543412Snewton } 169643412Snewton 169743412Snewton if (ctl.maxlen == -1 || dat.maxlen == -1) { 169843412Snewton DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n")); 169943412Snewton return ENOSYS; 170043412Snewton } 170143412Snewton 170243412Snewton switch (st->s_family) { 170343412Snewton case AF_INET: 170443412Snewton sasize = sizeof(sain); 170543412Snewton break; 170643412Snewton 170743412Snewton case AF_LOCAL: 170843412Snewton sasize = sizeof(saun); 170943412Snewton break; 171043412Snewton 171143412Snewton default: 171243412Snewton DPRINTF(("getmsg: Unsupported address family %d\n", 171343412Snewton st->s_family)); 171443412Snewton return ENOSYS; 171543412Snewton } 171643412Snewton 1717160794Sjhb mtx_lock(&Giant); 171843412Snewton switch (st->s_cmd) { 171943412Snewton case SVR4_TI_CONNECT_REQUEST: 172043412Snewton DPRINTF(("getmsg: TI_CONNECT_REQUEST\n")); 172143412Snewton /* 172243412Snewton * We do the connect in one step, so the putmsg should 172343412Snewton * have gotten the error. 172443412Snewton */ 172543412Snewton sc.cmd = SVR4_TI_OK_REPLY; 172643412Snewton sc.len = 0; 172743412Snewton 172843412Snewton ctl.len = 8; 172943412Snewton dat.len = -1; 173043412Snewton fl = 1; 173143412Snewton st->s_cmd = sc.cmd; 173243412Snewton break; 173343412Snewton 173443412Snewton case SVR4_TI_OK_REPLY: 173543412Snewton DPRINTF(("getmsg: TI_OK_REPLY\n")); 173643412Snewton /* 173743412Snewton * We are immediately after a connect reply, so we send 173843412Snewton * a connect verification. 173943412Snewton */ 174043412Snewton 1741160249Sjhb error = kern_getpeername(td, uap->fd, &sa, &sasize); 1742160249Sjhb if (error) { 1743160794Sjhb mtx_unlock(&Giant); 174443412Snewton DPRINTF(("getmsg: getpeername failed %d\n", error)); 174543412Snewton return error; 174643412Snewton } 174743412Snewton 174843412Snewton sc.cmd = SVR4_TI_CONNECT_REPLY; 174943412Snewton sc.pad[0] = 0x4; 175043412Snewton sc.offs = 0x18; 175143412Snewton sc.pad[1] = 0x14; 175243412Snewton sc.pad[2] = 0x04000402; 175343412Snewton 175443412Snewton switch (st->s_family) { 175543412Snewton case AF_INET: 175643412Snewton sc.len = sasize; 1757160249Sjhb sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa); 175843412Snewton break; 175943412Snewton 176043412Snewton case AF_LOCAL: 176143412Snewton sc.len = sasize + 4; 1762160249Sjhb sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa); 176343412Snewton break; 176443412Snewton 176543412Snewton default: 1766160794Sjhb mtx_unlock(&Giant); 1767160249Sjhb free(sa, M_SONAME); 176843412Snewton return ENOSYS; 176943412Snewton } 1770160249Sjhb free(sa, M_SONAME); 177143412Snewton 177243412Snewton ctl.len = 40; 177343412Snewton dat.len = -1; 177443412Snewton fl = 0; 177543412Snewton st->s_cmd = sc.cmd; 177643412Snewton break; 177743412Snewton 177843412Snewton case SVR4_TI__ACCEPT_OK: 177943412Snewton DPRINTF(("getmsg: TI__ACCEPT_OK\n")); 178043412Snewton /* 178143412Snewton * We do the connect in one step, so the putmsg should 178243412Snewton * have gotten the error. 178343412Snewton */ 178443412Snewton sc.cmd = SVR4_TI_OK_REPLY; 178543412Snewton sc.len = 1; 178643412Snewton 178743412Snewton ctl.len = 8; 178843412Snewton dat.len = -1; 178943412Snewton fl = 1; 179043412Snewton st->s_cmd = SVR4_TI__ACCEPT_WAIT; 179143412Snewton break; 179243412Snewton 179343412Snewton case SVR4_TI__ACCEPT_WAIT: 179443412Snewton DPRINTF(("getmsg: TI__ACCEPT_WAIT\n")); 179543412Snewton /* 179643412Snewton * We are after a listen, so we try to accept... 179743412Snewton */ 1798160249Sjhb 1799160765Sjhb error = kern_accept(td, uap->fd, &sa, &sasize, &afp); 1800160249Sjhb if (error) { 1801160794Sjhb mtx_unlock(&Giant); 180243412Snewton DPRINTF(("getmsg: accept failed %d\n", error)); 180343412Snewton return error; 180443412Snewton } 180543412Snewton 180643412Snewton st->s_afd = *retval; 180743412Snewton 180843412Snewton DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd)); 180943412Snewton 181043412Snewton sc.cmd = SVR4_TI_ACCEPT_REPLY; 181143412Snewton sc.offs = 0x18; 181243412Snewton sc.pad[0] = 0x0; 181343412Snewton 181443412Snewton switch (st->s_family) { 181543412Snewton case AF_INET: 181643412Snewton sc.pad[1] = 0x28; 1817160249Sjhb sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)&sa); 181843412Snewton ctl.len = 40; 181943412Snewton sc.len = sasize; 182043412Snewton break; 182143412Snewton 182243412Snewton case AF_LOCAL: 182343412Snewton sc.pad[1] = 0x00010000; 182443412Snewton sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */ 182543412Snewton sc.pad[3] = 0x00010000; 182643412Snewton ctl.len = 134; 182743412Snewton sc.len = sasize + 4; 182843412Snewton break; 182943412Snewton 183043412Snewton default: 1831160765Sjhb fdclose(td->td_proc->p_fd, afp, st->s_afd, td); 1832160765Sjhb fdrop(afp, td); 1833160765Sjhb st->s_afd = -1; 1834160794Sjhb mtx_unlock(&Giant); 1835160249Sjhb free(sa, M_SONAME); 183643412Snewton return ENOSYS; 183743412Snewton } 1838160249Sjhb free(sa, M_SONAME); 183943412Snewton 184043412Snewton dat.len = -1; 184143412Snewton fl = 0; 184243412Snewton st->s_cmd = SVR4_TI__ACCEPT_OK; 184343412Snewton break; 184443412Snewton 184543412Snewton case SVR4_TI_SENDTO_REQUEST: 184643412Snewton DPRINTF(("getmsg: TI_SENDTO_REQUEST\n")); 184743412Snewton if (ctl.maxlen > 36 && ctl.len < 36) 184843412Snewton ctl.len = 36; 184943412Snewton 1850121275Stjr if (ctl.len > sizeof(sc)) 1851121275Stjr ctl.len = sizeof(sc); 1852121275Stjr 1853160794Sjhb if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) { 1854160794Sjhb mtx_unlock(&Giant); 185543412Snewton return error; 1856160794Sjhb } 185743412Snewton 185843412Snewton switch (st->s_family) { 185943412Snewton case AF_INET: 1860160249Sjhb sa = (struct sockaddr *)&sain; 186143412Snewton sockaddr_to_netaddr_in(&sc, &sain); 186243412Snewton break; 186343412Snewton 186443412Snewton case AF_LOCAL: 1865160249Sjhb sa = (struct sockaddr *)&saun; 186643412Snewton sockaddr_to_netaddr_un(&sc, &saun); 186743412Snewton break; 186843412Snewton 186943412Snewton default: 1870160794Sjhb mtx_unlock(&Giant); 187143412Snewton return ENOSYS; 187243412Snewton } 187343412Snewton 1874160249Sjhb msg.msg_name = sa; 187543412Snewton msg.msg_namelen = sasize; 187643412Snewton msg.msg_iov = &aiov; 187743412Snewton msg.msg_iovlen = 1; 187843412Snewton msg.msg_control = 0; 187943412Snewton aiov.iov_base = dat.buf; 188043412Snewton aiov.iov_len = dat.maxlen; 188143412Snewton msg.msg_flags = 0; 188243412Snewton 1883160249Sjhb error = kern_recvit(td, uap->fd, &msg, UIO_SYSSPACE, NULL); 188443412Snewton 188543412Snewton if (error) { 1886160794Sjhb mtx_unlock(&Giant); 188743412Snewton DPRINTF(("getmsg: recvit failed %d\n", error)); 188843412Snewton return error; 188943412Snewton } 189043412Snewton 189143412Snewton sc.cmd = SVR4_TI_RECVFROM_IND; 189243412Snewton 189343412Snewton switch (st->s_family) { 189443412Snewton case AF_INET: 189543412Snewton sc.len = sasize; 189643412Snewton sockaddr_to_netaddr_in(&sc, &sain); 189743412Snewton break; 189843412Snewton 189943412Snewton case AF_LOCAL: 190043412Snewton sc.len = sasize + 4; 190143412Snewton sockaddr_to_netaddr_un(&sc, &saun); 190243412Snewton break; 190343412Snewton 190443412Snewton default: 1905160794Sjhb mtx_unlock(&Giant); 190643412Snewton return ENOSYS; 190743412Snewton } 190843412Snewton 190943412Snewton dat.len = *retval; 191043412Snewton fl = 0; 191143412Snewton st->s_cmd = sc.cmd; 191243412Snewton break; 191343412Snewton 191443412Snewton default: 191543412Snewton st->s_cmd = sc.cmd; 191643412Snewton if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) { 191743412Snewton struct read_args ra; 191843412Snewton 191972082Sasmodai /* More weirdness: Again, I can't find documentation 192043412Snewton * to back this up, but when a process does a generic 192143412Snewton * "getmsg()" call it seems that the command field is 192243412Snewton * zero and the length of the data area is zero. I 192343412Snewton * think processes expect getmsg() to fill in dat.len 192443412Snewton * after reading at most dat.maxlen octets from the 192543412Snewton * stream. Since we're using sockets I can let 192643412Snewton * read() look after it and frob return values 192743412Snewton * appropriately (or inappropriately :-) 192843412Snewton * -- newton@atdot.dotat.org XXX 192943412Snewton */ 1930107849Salfred ra.fd = uap->fd; 1931107849Salfred ra.buf = dat.buf; 1932107849Salfred ra.nbyte = dat.maxlen; 1933225617Skmacy if ((error = sys_read(td, &ra)) != 0) { 1934160794Sjhb mtx_unlock(&Giant); 193543412Snewton return error; 193643412Snewton } 193743412Snewton dat.len = *retval; 193843412Snewton *retval = 0; 193943412Snewton st->s_cmd = SVR4_TI_SENDTO_REQUEST; 194043412Snewton break; 194143412Snewton } 1942160794Sjhb mtx_unlock(&Giant); 194343412Snewton DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd)); 194443412Snewton return EINVAL; 194543412Snewton } 194643412Snewton 1947107849Salfred if (uap->ctl) { 1948144014Sdas if (ctl.len > sizeof(sc)) 1949144014Sdas ctl.len = sizeof(sc); 195043412Snewton if (ctl.len != -1) 1951160765Sjhb error = copyout(&sc, ctl.buf, ctl.len); 195243412Snewton 1953160765Sjhb if (error == 0) 1954160765Sjhb error = copyout(&ctl, uap->ctl, sizeof(ctl)); 195543412Snewton } 195643412Snewton 1957107849Salfred if (uap->dat) { 1958160765Sjhb if (error == 0) 1959160765Sjhb error = copyout(&dat, uap->dat, sizeof(dat)); 196043412Snewton } 196143412Snewton 1962107849Salfred if (uap->flags) { /* XXX: Need translation */ 1963160765Sjhb if (error == 0) 1964160765Sjhb error = copyout(&fl, uap->flags, sizeof(fl)); 196543412Snewton } 196643412Snewton 1967160765Sjhb if (error) { 1968160765Sjhb if (afp) { 1969160765Sjhb fdclose(td->td_proc->p_fd, afp, st->s_afd, td); 1970160765Sjhb fdrop(afp, td); 1971160765Sjhb st->s_afd = -1; 1972160765Sjhb } 1973160794Sjhb mtx_unlock(&Giant); 1974160765Sjhb return (error); 1975160765Sjhb } 1976160794Sjhb mtx_unlock(&Giant); 1977160765Sjhb if (afp) 1978160765Sjhb fdrop(afp, td); 1979160765Sjhb 198043412Snewton *retval = 0; 198143412Snewton 198243412Snewton#ifdef DEBUG_SVR4 1983107849Salfred show_msg("<getmsg", uap->fd, uap->ctl, 1984107849Salfred uap->dat, fl); 198543412Snewton#endif /* DEBUG_SVR4 */ 198643412Snewton return error; 198743412Snewton} 198843412Snewton 198983366Sjulianint svr4_sys_send(td, uap) 199083366Sjulian struct thread *td; 199143412Snewton struct svr4_sys_send_args *uap; 199243412Snewton{ 1993183040Sed struct sendto_args sta; 1994183040Sed 1995183040Sed sta.s = uap->s; 1996183040Sed sta.buf = uap->buf; 1997183040Sed sta.len = uap->len; 1998183040Sed sta.flags = uap->flags; 1999183040Sed sta.to = NULL; 2000183040Sed sta.tolen = 0; 2001183040Sed 2002225617Skmacy return (sys_sendto(td, &sta)); 200343412Snewton} 200443412Snewton 200583366Sjulianint svr4_sys_recv(td, uap) 200683366Sjulian struct thread *td; 200743412Snewton struct svr4_sys_recv_args *uap; 200843412Snewton{ 2009183040Sed struct recvfrom_args rfa; 2010183040Sed 2011183040Sed rfa.s = uap->s; 2012183040Sed rfa.buf = uap->buf; 2013183040Sed rfa.len = uap->len; 2014183040Sed rfa.flags = uap->flags; 2015183040Sed rfa.from = NULL; 2016183040Sed rfa.fromlenaddr = NULL; 2017183040Sed 2018225617Skmacy return (sys_recvfrom(td, &rfa)); 201943412Snewton} 202043412Snewton 202143412Snewton/* 202243412Snewton * XXX This isn't necessary, but it's handy for inserting debug code into 202343412Snewton * sendto(). Let's leave it here for now... 202443412Snewton */ 202543412Snewtonint 202683366Sjuliansvr4_sys_sendto(td, uap) 202783366Sjulian struct thread *td; 202843412Snewton struct svr4_sys_sendto_args *uap; 202943412Snewton{ 203043412Snewton struct sendto_args sa; 203143412Snewton 2032107849Salfred sa.s = uap->s; 2033107849Salfred sa.buf = uap->buf; 2034107849Salfred sa.len = uap->len; 2035107849Salfred sa.flags = uap->flags; 2036107849Salfred sa.to = (caddr_t)uap->to; 2037107849Salfred sa.tolen = uap->tolen; 203843412Snewton 203943412Snewton DPRINTF(("calling sendto()\n")); 2040225617Skmacy return sys_sendto(td, &sa); 204143412Snewton} 204243412Snewton 2043