svr4_stream.c revision 89536
1191665Sbms/* 2191665Sbms * Copyright (c) 1998 Mark Newton. All rights reserved. 3191665Sbms * Copyright (c) 1994, 1996 Christos Zoulas. All rights reserved. 4191665Sbms * 5191665Sbms * Redistribution and use in source and binary forms, with or without 6191665Sbms * modification, are permitted provided that the following conditions 7191665Sbms * are met: 8191665Sbms * 1. Redistributions of source code must retain the above copyright 9191665Sbms * notice, this list of conditions and the following disclaimer. 10191665Sbms * 2. Redistributions in binary form must reproduce the above copyright 11191665Sbms * notice, this list of conditions and the following disclaimer in the 12191665Sbms * documentation and/or other materials provided with the distribution. 13191665Sbms * 3. All advertising materials mentioning features or use of this software 14191665Sbms * must display the following acknowledgement: 15191665Sbms * This product includes software developed by Christos Zoulas. 16191665Sbms * 4. The name of the author may not be used to endorse or promote products 17191665Sbms * derived from this software without specific prior written permission. 18191665Sbms * 19191665Sbms * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20191665Sbms * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21191665Sbms * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22191665Sbms * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23191665Sbms * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24191665Sbms * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25191665Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26191665Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27191665Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28191665Sbms * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29191665Sbms * 30191665Sbms * $FreeBSD: head/sys/compat/svr4/svr4_stream.c 89536 2002-01-19 03:52:17Z alfred $ 31191665Sbms */ 32191672Sbms 33191665Sbms/* 34191665Sbms * Pretend that we have streams... 35191665Sbms * Yes, this is gross. 36191665Sbms * 37191665Sbms * ToDo: The state machine for getmsg needs re-thinking 38191665Sbms */ 39191665Sbms 40191665Sbms#define COMPAT_43 1 41191665Sbms 42191665Sbms#include <sys/param.h> 43191665Sbms#include <sys/systm.h> 44191665Sbms#include <sys/fcntl.h> 45191665Sbms#include <sys/filedesc.h> 46191665Sbms#include <sys/filio.h> 47191665Sbms#include <sys/lock.h> 48191665Sbms#include <sys/malloc.h> 49191665Sbms#include <sys/file.h> /* Must come after sys/malloc.h */ 50191665Sbms#include <sys/mbuf.h> 51191665Sbms#include <sys/mutex.h> 52191665Sbms#include <sys/proc.h> 53191665Sbms#include <sys/protosw.h> 54191665Sbms#include <sys/signal.h> 55257176Sglebius#include <sys/signalvar.h> 56191665Sbms#include <sys/socket.h> 57191665Sbms#include <sys/socketvar.h> 58191665Sbms#include <sys/stat.h> 59191665Sbms#include <sys/sysproto.h> 60191665Sbms#include <sys/uio.h> 61191665Sbms#include <sys/ktrace.h> /* Must come after sys/uio.h */ 62292015Smelifaro#include <sys/un.h> 63191665Sbms 64191665Sbms#include <netinet/in.h> 65191665Sbms 66191665Sbms#include <compat/svr4/svr4.h> 67191665Sbms#include <compat/svr4/svr4_types.h> 68191665Sbms#include <compat/svr4/svr4_util.h> 69191665Sbms#include <compat/svr4/svr4_signal.h> 70191665Sbms#include <compat/svr4/svr4_proto.h> 71195699Srwatson#include <compat/svr4/svr4_stropts.h> 72191665Sbms#include <compat/svr4/svr4_timod.h> 73191665Sbms#include <compat/svr4/svr4_sockmod.h> 74191665Sbms#include <compat/svr4/svr4_ioctl.h> 75191665Sbms#include <compat/svr4/svr4_socket.h> 76191665Sbms 77191665Sbms/* Utils */ 78191665Sbmsstatic int clean_pipe __P((struct thread *, const char *)); 79191665Sbmsstatic void getparm __P((struct file *, struct svr4_si_sockparms *)); 80191665Sbmsstatic int svr4_do_putmsg __P((struct thread *, struct svr4_sys_putmsg_args *, 81191665Sbms struct file *)); 82191665Sbmsstatic int svr4_do_getmsg __P((struct thread *, struct svr4_sys_getmsg_args *, 83191665Sbms struct file *)); 84191665Sbms 85191665Sbms/* Address Conversions */ 86191665Sbmsstatic void sockaddr_to_netaddr_in __P((struct svr4_strmcmd *, 87191665Sbms const struct sockaddr_in *)); 88191665Sbmsstatic void sockaddr_to_netaddr_un __P((struct svr4_strmcmd *, 89191665Sbms const struct sockaddr_un *)); 90191665Sbmsstatic void netaddr_to_sockaddr_in __P((struct sockaddr_in *, 91191665Sbms const struct svr4_strmcmd *)); 92191665Sbmsstatic void netaddr_to_sockaddr_un __P((struct sockaddr_un *, 93191665Sbms const struct svr4_strmcmd *)); 94191665Sbms 95191665Sbms/* stream ioctls */ 96191665Sbmsstatic int i_nread __P((struct file *, struct thread *, register_t *, int, 97191665Sbms u_long, caddr_t)); 98191665Sbmsstatic int i_fdinsert __P((struct file *, struct thread *, register_t *, int, 99191665Sbms u_long, caddr_t)); 100191665Sbmsstatic int i_str __P((struct file *, struct thread *, register_t *, int, 101191665Sbms u_long, caddr_t)); 102191665Sbmsstatic int i_setsig __P((struct file *, struct thread *, register_t *, int, 103191665Sbms u_long, caddr_t)); 104191665Sbmsstatic int i_getsig __P((struct file *, struct thread *, register_t *, int, 105191665Sbms u_long, caddr_t)); 106191665Sbmsstatic int _i_bind_rsvd __P((struct file *, struct thread *, register_t *, int, 107191665Sbms u_long, caddr_t)); 108191665Sbmsstatic int _i_rele_rsvd __P((struct file *, struct thread *, register_t *, int, 109191665Sbms u_long, caddr_t)); 110191665Sbms 111191665Sbms/* i_str sockmod calls */ 112191665Sbmsstatic int sockmod __P((struct file *, int, struct svr4_strioctl *, 113191665Sbms struct thread *)); 114191665Sbmsstatic int si_listen __P((struct file *, int, struct svr4_strioctl *, 115191665Sbms struct thread *)); 116191665Sbmsstatic int si_ogetudata __P((struct file *, int, struct svr4_strioctl *, 117191665Sbms struct thread *)); 118191665Sbmsstatic int si_sockparams __P((struct file *, int, struct svr4_strioctl *, 119191665Sbms struct thread *)); 120191665Sbmsstatic int si_shutdown __P((struct file *, int, struct svr4_strioctl *, 121191665Sbms struct thread *)); 122191665Sbmsstatic int si_getudata __P((struct file *, int, struct svr4_strioctl *, 123191665Sbms struct thread *)); 124191665Sbms 125191665Sbms/* i_str timod calls */ 126191665Sbmsstatic int timod __P((struct file *, int, struct svr4_strioctl *, 127191665Sbms struct thread *)); 128191665Sbmsstatic int ti_getinfo __P((struct file *, int, struct svr4_strioctl *, 129191665Sbms struct thread *)); 130191665Sbmsstatic int ti_bind __P((struct file *, int, struct svr4_strioctl *, 131191665Sbms struct thread *)); 132191665Sbms 133191665Sbms/* infrastructure */ 134191665Sbmsstatic int svr4_sendit __P((struct thread *td, int s, struct msghdr *mp, 135191665Sbms int flags)); 136259840Sdim 137191665Sbmsstatic int svr4_recvit __P((struct thread *td, int s, struct msghdr *mp, 138259840Sdim caddr_t namelenp)); 139191665Sbms 140191665Sbms/* <sigh> Ok, so we shouldn't use sendit() in uipc_syscalls.c because 141191665Sbms * it isn't part of a "public" interface; We're supposed to use 142191665Sbms * pru_sosend instead. Same goes for recvit()/pru_soreceive() for 143191665Sbms * that matter. Solution: Suck sendit()/recvit() into here where we 144191665Sbms * can do what we like. 145191665Sbms * 146191665Sbms * I hate code duplication. 147191672Sbms * 148191672Sbms * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though. 149191672Sbms */ 150191665Sbmsstatic int 151191665Sbmssvr4_sendit(td, s, mp, flags) 152191665Sbms register struct thread *td; 153191665Sbms int s; 154191665Sbms register struct msghdr *mp; 155191665Sbms int flags; 156191665Sbms{ 157227309Sed struct uio auio; 158227309Sed register struct iovec *iov; 159191665Sbms register int i; 160191665Sbms struct mbuf *control; 161191665Sbms struct sockaddr *to; 162267992Shselasky int len, error; 163191665Sbms struct socket *so; 164191665Sbms#ifdef KTRACE 165191665Sbms struct iovec *ktriov = NULL; 166191665Sbms struct uio ktruio; 167267992Shselasky#endif 168191665Sbms 169191665Sbms if ((error = fgetsock(td, s, &so, NULL)) != 0) 170191665Sbms return (error); 171191665Sbms auio.uio_iov = mp->msg_iov; 172267992Shselasky auio.uio_iovcnt = mp->msg_iovlen; 173191665Sbms auio.uio_segflg = UIO_USERSPACE; 174191665Sbms auio.uio_rw = UIO_WRITE; 175227309Sed auio.uio_td = td; 176191665Sbms auio.uio_offset = 0; /* XXX */ 177191665Sbms auio.uio_resid = 0; 178191665Sbms iov = mp->msg_iov; 179259840Sdim for (i = 0; i < mp->msg_iovlen; i++, iov++) { 180191665Sbms if ((auio.uio_resid += iov->iov_len) < 0) { 181191665Sbms error = EINVAL; 182191665Sbms goto done1; 183191665Sbms } 184191665Sbms } 185191665Sbms if (mp->msg_name) { 186191665Sbms error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); 187191665Sbms if (error) 188191665Sbms goto done1; 189191665Sbms } else { 190191665Sbms to = 0; 191191665Sbms } 192191665Sbms if (mp->msg_control) { 193191665Sbms if (mp->msg_controllen < sizeof(struct cmsghdr)) { 194191665Sbms error = EINVAL; 195191665Sbms goto bad; 196191665Sbms } 197191665Sbms error = sockargs(&control, mp->msg_control, 198191665Sbms mp->msg_controllen, MT_CONTROL); 199191665Sbms if (error) 200191665Sbms goto bad; 201191665Sbms } else { 202259840Sdim control = 0; 203191665Sbms } 204191665Sbms#ifdef KTRACE 205191665Sbms if (KTRPOINT(td->td_proc, KTR_GENIO)) { 206191665Sbms int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 207191665Sbms 208191665Sbms MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 209191665Sbms bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 210191665Sbms ktruio = auio; 211191665Sbms } 212191665Sbms#endif 213191665Sbms len = auio.uio_resid; 214191665Sbms error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control, 215191665Sbms flags, td); 216191665Sbms if (error) { 217191665Sbms if (auio.uio_resid != len && (error == ERESTART || 218191665Sbms error == EINTR || error == EWOULDBLOCK)) 219191665Sbms error = 0; 220191665Sbms if (error == EPIPE) { 221191665Sbms PROC_LOCK(td->td_proc); 222191665Sbms psignal(td->td_proc, SIGPIPE); 223191665Sbms PROC_UNLOCK(td->td_proc); 224191665Sbms } 225191665Sbms } 226191665Sbms if (error == 0) 227191665Sbms td->td_retval[0] = len - auio.uio_resid; 228191665Sbms#ifdef KTRACE 229191665Sbms if (ktriov != NULL) { 230191665Sbms if (error == 0) { 231191665Sbms ktruio.uio_iov = ktriov; 232191665Sbms ktruio.uio_resid = td->td_retval[0]; 233191665Sbms ktrgenio(td->td_proc->p_tracep, s, UIO_WRITE, &ktruio, error); 234191665Sbms } 235191665Sbms FREE(ktriov, M_TEMP); 236191665Sbms } 237191665Sbms#endif 238191665Sbmsbad: 239191665Sbms if (to) 240191665Sbms FREE(to, M_SONAME); 241191665Sbmsdone1: 242191665Sbms fputsock(so); 243191665Sbms return (error); 244191665Sbms} 245191665Sbms 246191665Sbmsstatic int 247191665Sbmssvr4_recvit(td, s, mp, namelenp) 248191665Sbms register struct thread *td; 249191665Sbms int s; 250191665Sbms register struct msghdr *mp; 251191665Sbms caddr_t namelenp; 252191665Sbms{ 253191665Sbms struct uio auio; 254191665Sbms register struct iovec *iov; 255191665Sbms register int i; 256191665Sbms int len, error; 257191665Sbms struct mbuf *m, *control = 0; 258191665Sbms caddr_t ctlbuf; 259191665Sbms struct socket *so; 260191665Sbms struct sockaddr *fromsa = 0; 261191665Sbms#ifdef KTRACE 262191665Sbms struct iovec *ktriov = NULL; 263191665Sbms struct uio ktruio; 264191665Sbms#endif 265191665Sbms 266191665Sbms if ((error = fgetsock(td, s, &so, NULL)) != 0) 267191665Sbms return (error); 268191665Sbms auio.uio_iov = mp->msg_iov; 269191665Sbms auio.uio_iovcnt = mp->msg_iovlen; 270191665Sbms auio.uio_segflg = UIO_USERSPACE; 271191665Sbms auio.uio_rw = UIO_READ; 272191665Sbms auio.uio_td = td; 273191665Sbms auio.uio_offset = 0; /* XXX */ 274191665Sbms auio.uio_resid = 0; 275191665Sbms iov = mp->msg_iov; 276191665Sbms for (i = 0; i < mp->msg_iovlen; i++, iov++) { 277191665Sbms if ((auio.uio_resid += iov->iov_len) < 0) { 278191665Sbms error = EINVAL; 279191665Sbms goto done1; 280191665Sbms } 281191665Sbms } 282191665Sbms#ifdef KTRACE 283191665Sbms if (KTRPOINT(td->td_proc, KTR_GENIO)) { 284191665Sbms int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 285191665Sbms 286191665Sbms MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 287191665Sbms bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 288191665Sbms ktruio = auio; 289191665Sbms } 290191665Sbms#endif 291191665Sbms len = auio.uio_resid; 292191665Sbms error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, 293191665Sbms (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 294191665Sbms &mp->msg_flags); 295191665Sbms if (error) { 296191665Sbms if (auio.uio_resid != len && (error == ERESTART || 297191665Sbms error == EINTR || error == EWOULDBLOCK)) 298191665Sbms error = 0; 299191665Sbms } 300191665Sbms#ifdef KTRACE 301191665Sbms if (ktriov != NULL) { 302191665Sbms if (error == 0) { 303191665Sbms ktruio.uio_iov = ktriov; 304191665Sbms ktruio.uio_resid = len - auio.uio_resid; 305191665Sbms ktrgenio(td->td_proc->p_tracep, s, UIO_READ, &ktruio, error); 306191665Sbms } 307191665Sbms FREE(ktriov, M_TEMP); 308191665Sbms } 309192923Sbms#endif 310192923Sbms if (error) 311192923Sbms goto out; 312192923Sbms td->td_retval[0] = len - auio.uio_resid; 313191665Sbms if (mp->msg_name) { 314191665Sbms len = mp->msg_namelen; 315191665Sbms if (len <= 0 || fromsa == 0) 316191665Sbms len = 0; 317191665Sbms else { 318191665Sbms#ifndef MIN 319191665Sbms#define MIN(a,b) ((a)>(b)?(b):(a)) 320191665Sbms#endif 321191665Sbms /* save sa_len before it is destroyed by MSG_COMPAT */ 322191665Sbms len = MIN(len, fromsa->sa_len); 323191665Sbms error = copyout(fromsa, 324191665Sbms (caddr_t)mp->msg_name, (unsigned)len); 325191665Sbms if (error) 326191665Sbms goto out; 327191665Sbms } 328191665Sbms mp->msg_namelen = len; 329191665Sbms if (namelenp && 330191665Sbms (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 331191665Sbms goto out; 332191665Sbms } 333191665Sbms } 334191665Sbms if (mp->msg_control) { 335191665Sbms len = mp->msg_controllen; 336192923Sbms m = control; 337191665Sbms mp->msg_controllen = 0; 338191665Sbms ctlbuf = (caddr_t) mp->msg_control; 339191665Sbms 340191665Sbms while (m && len > 0) { 341191665Sbms unsigned int tocopy; 342191665Sbms 343191665Sbms if (len >= m->m_len) 344191665Sbms tocopy = m->m_len; 345191665Sbms else { 346191665Sbms mp->msg_flags |= MSG_CTRUNC; 347191665Sbms tocopy = len; 348191665Sbms } 349191665Sbms 350191665Sbms if ((error = copyout((caddr_t)mtod(m, caddr_t), 351191665Sbms ctlbuf, tocopy)) != 0) 352191665Sbms goto out; 353191665Sbms 354191665Sbms ctlbuf += tocopy; 355191665Sbms len -= tocopy; 356191665Sbms m = m->m_next; 357191665Sbms } 358191665Sbms mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control; 359191665Sbms } 360191665Sbmsout: 361191665Sbms if (fromsa) 362191665Sbms FREE(fromsa, M_SONAME); 363191665Sbms if (control) 364191665Sbms m_freem(control); 365191665Sbmsdone1: 366191665Sbms fputsock(so); 367191665Sbms return (error); 368191665Sbms} 369191665Sbms 370191665Sbms#ifdef DEBUG_SVR4 371191665Sbmsstatic void bufprint __P((u_char *, size_t)); 372191665Sbmsstatic int show_ioc __P((const char *, struct svr4_strioctl *)); 373191665Sbmsstatic int show_strbuf __P((struct svr4_strbuf *)); 374191665Sbmsstatic void show_msg __P((const char *, int, struct svr4_strbuf *, 375191665Sbms struct svr4_strbuf *, int)); 376191665Sbms 377191665Sbmsstatic void 378191665Sbmsbufprint(buf, len) 379191665Sbms u_char *buf; 380191665Sbms size_t len; 381191665Sbms{ 382191665Sbms size_t i; 383191665Sbms 384191665Sbms uprintf("\n\t"); 385191665Sbms for (i = 0; i < len; i++) { 386191665Sbms uprintf("%x ", buf[i]); 387191665Sbms if (i && (i % 16) == 0) 388191665Sbms uprintf("\n\t"); 389191665Sbms } 390191665Sbms} 391191665Sbms 392191665Sbmsstatic int 393191665Sbmsshow_ioc(str, ioc) 394191665Sbms const char *str; 395191665Sbms struct svr4_strioctl *ioc; 396191665Sbms{ 397191665Sbms u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK); 398191665Sbms int error; 399191665Sbms 400191665Sbms uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ", 401191665Sbms str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf); 402191665Sbms 403191665Sbms if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) { 404191665Sbms free((char *) ptr, M_TEMP); 405191665Sbms return error; 406229621Sjhb } 407191665Sbms 408191665Sbms bufprint(ptr, ioc->len); 409191665Sbms 410191665Sbms uprintf("}\n"); 411191665Sbms 412191665Sbms free((char *) ptr, M_TEMP); 413191665Sbms return 0; 414191665Sbms} 415191665Sbms 416191665Sbms 417191665Sbmsstatic int 418191665Sbmsshow_strbuf(str) 419191665Sbms struct svr4_strbuf *str; 420191665Sbms{ 421191665Sbms int error; 422191665Sbms u_char *ptr = NULL; 423191665Sbms int maxlen = str->maxlen; 424191665Sbms int len = str->len; 425191665Sbms 426191665Sbms if (maxlen < 0) 427191665Sbms maxlen = 0; 428191665Sbms 429191665Sbms if (len >= maxlen) 430229621Sjhb len = maxlen; 431191665Sbms 432191665Sbms if (len > 0) { 433191665Sbms ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK); 434229621Sjhb 435191665Sbms if ((error = copyin(str->buf, ptr, len)) != 0) { 436191665Sbms free((char *) ptr, M_TEMP); 437191665Sbms return error; 438191665Sbms } 439191665Sbms } 440191665Sbms 441191665Sbms uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf); 442191665Sbms 443191665Sbms if (ptr) 444191665Sbms bufprint(ptr, len); 445191665Sbms 446191665Sbms uprintf("]}"); 447191665Sbms 448191665Sbms if (ptr) 449191665Sbms free((char *) ptr, M_TEMP); 450191665Sbms 451191665Sbms return 0; 452191665Sbms} 453191665Sbms 454191665Sbms 455191665Sbmsstatic void 456191665Sbmsshow_msg(str, fd, ctl, dat, flags) 457191665Sbms const char *str; 458191665Sbms int fd; 459191665Sbms struct svr4_strbuf *ctl; 460191665Sbms struct svr4_strbuf *dat; 461229621Sjhb int flags; 462191665Sbms{ 463191665Sbms struct svr4_strbuf buf; 464191665Sbms int error; 465191665Sbms 466191665Sbms uprintf("%s(%d", str, fd); 467191665Sbms if (ctl != NULL) { 468191665Sbms if ((error = copyin(ctl, &buf, sizeof(buf))) != 0) 469191665Sbms return; 470191665Sbms show_strbuf(&buf); 471191665Sbms } 472191665Sbms else 473291045Scem uprintf(", NULL"); 474191665Sbms 475291045Scem if (dat != NULL) { 476191665Sbms if ((error = copyin(dat, &buf, sizeof(buf))) != 0) 477191665Sbms return; 478191665Sbms show_strbuf(&buf); 479191665Sbms } 480191665Sbms else 481191665Sbms uprintf(", NULL"); 482191665Sbms 483278979Sglebius uprintf(", %x);\n", flags); 484191665Sbms} 485191665Sbms 486191665Sbms#endif /* DEBUG_SVR4 */ 487191665Sbms 488191665Sbms/* 489191665Sbms * We are faced with an interesting situation. On svr4 unix sockets 490191665Sbms * are really pipes. But we really have sockets, and we might as 491191665Sbms * well use them. At the point where svr4 calls TI_BIND, it has 492191665Sbms * already created a named pipe for the socket using mknod(2). 493229621Sjhb * We need to create a socket with the same name when we bind, 494191665Sbms * so we need to remove the pipe before, otherwise we'll get address 495191665Sbms * already in use. So we *carefully* remove the pipe, to avoid 496191665Sbms * using this as a random file removal tool. We use system calls 497191665Sbms * to avoid code duplication. 498191665Sbms */ 499191665Sbmsstatic int 500191665Sbmsclean_pipe(td, path) 501191665Sbms struct thread *td; 502191665Sbms const char *path; 503191665Sbms{ 504191665Sbms struct lstat_args la; 505191665Sbms struct unlink_args ua; 506191665Sbms struct stat st; 507191665Sbms int error; 508191665Sbms caddr_t sg = stackgap_init(); 509191665Sbms size_t l = strlen(path) + 1; 510191665Sbms void *tpath; 511191665Sbms 512191665Sbms tpath = stackgap_alloc(&sg, l); 513191665Sbms SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat)); 514191665Sbms 515191665Sbms if ((error = copyout(path, tpath, l)) != 0) 516191665Sbms return error; 517191665Sbms 518191665Sbms SCARG(&la, path) = tpath; 519191665Sbms 520191665Sbms if ((error = lstat(td, &la)) != 0) 521191665Sbms return 0; 522191665Sbms 523191665Sbms if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0) 524191665Sbms return 0; 525191665Sbms 526191665Sbms /* 527191665Sbms * Make sure we are dealing with a mode 0 named pipe. 528191665Sbms */ 529191665Sbms if ((st.st_mode & S_IFMT) != S_IFIFO) 530191665Sbms return 0; 531191665Sbms 532191665Sbms if ((st.st_mode & ALLPERMS) != 0) 533191665Sbms return 0; 534191665Sbms 535191665Sbms SCARG(&ua, path) = SCARG(&la, path); 536191665Sbms 537191665Sbms if ((error = unlink(td, &ua)) != 0) { 538191665Sbms DPRINTF(("clean_pipe: unlink failed %d\n", error)); 539191665Sbms return error; 540191665Sbms } 541191665Sbms 542191665Sbms return 0; 543191665Sbms} 544191665Sbms 545191665Sbms 546191665Sbmsstatic void 547191665Sbmssockaddr_to_netaddr_in(sc, sain) 548191665Sbms struct svr4_strmcmd *sc; 549191665Sbms const struct sockaddr_in *sain; 550191665Sbms{ 551191665Sbms struct svr4_netaddr_in *na; 552191665Sbms na = SVR4_ADDROF(sc); 553191665Sbms 554191665Sbms na->family = sain->sin_family; 555191665Sbms na->port = sain->sin_port; 556191665Sbms na->addr = sain->sin_addr.s_addr; 557191665Sbms DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port, 558191665Sbms na->addr)); 559191665Sbms} 560191665Sbms 561191665Sbms 562191665Sbmsstatic void 563191665Sbmssockaddr_to_netaddr_un(sc, saun) 564191665Sbms struct svr4_strmcmd *sc; 565191665Sbms const struct sockaddr_un *saun; 566191665Sbms{ 567191665Sbms struct svr4_netaddr_un *na; 568191665Sbms char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 - 569191665Sbms sizeof(*sc); 570191665Sbms const char *src; 571191665Sbms 572191665Sbms na = SVR4_ADDROF(sc); 573191665Sbms na->family = saun->sun_family; 574191665Sbms for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; ) 575191665Sbms if (dst == edst) 576191665Sbms break; 577298995Spfg DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path)); 578191665Sbms} 579191665Sbms 580191665Sbms 581191665Sbmsstatic void 582191665Sbmsnetaddr_to_sockaddr_in(sain, sc) 583191665Sbms struct sockaddr_in *sain; 584191665Sbms const struct svr4_strmcmd *sc; 585191665Sbms{ 586191665Sbms const struct svr4_netaddr_in *na; 587191665Sbms 588191665Sbms 589191665Sbms na = SVR4_C_ADDROF(sc); 590191665Sbms memset(sain, 0, sizeof(*sain)); 591191665Sbms sain->sin_len = sizeof(*sain); 592191665Sbms sain->sin_family = na->family; 593191665Sbms sain->sin_port = na->port; 594191665Sbms sain->sin_addr.s_addr = na->addr; 595191665Sbms DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family, 596191665Sbms sain->sin_port, sain->sin_addr.s_addr)); 597191665Sbms} 598191665Sbms 599191665Sbms 600191665Sbmsstatic void 601191665Sbmsnetaddr_to_sockaddr_un(saun, sc) 602191665Sbms struct sockaddr_un *saun; 603191665Sbms const struct svr4_strmcmd *sc; 604191665Sbms{ 605191665Sbms const struct svr4_netaddr_un *na; 606191665Sbms char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1]; 607191665Sbms const char *src; 608191665Sbms 609191665Sbms na = SVR4_C_ADDROF(sc); 610191665Sbms memset(saun, 0, sizeof(*saun)); 611191665Sbms saun->sun_family = na->family; 612191665Sbms for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; ) 613191665Sbms if (dst == edst) 614191665Sbms break; 615191665Sbms saun->sun_len = dst - saun->sun_path; 616191665Sbms DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family, 617191665Sbms saun->sun_path)); 618191665Sbms} 619191665Sbms 620191665Sbms 621191665Sbmsstatic void 622191665Sbmsgetparm(fp, pa) 623191665Sbms struct file *fp; 624191665Sbms struct svr4_si_sockparms *pa; 625191665Sbms{ 626191665Sbms struct svr4_strm *st; 627191665Sbms struct socket *so; 628191665Sbms 629191665Sbms st = svr4_stream_get(fp); 630191665Sbms if (st == NULL) 631191665Sbms return; 632191665Sbms 633191665Sbms so = (struct socket *) fp->f_data; 634191665Sbms 635191665Sbms pa->family = st->s_family; 636191665Sbms 637191665Sbms switch (so->so_type) { 638191665Sbms case SOCK_DGRAM: 639191665Sbms pa->type = SVR4_T_CLTS; 640191665Sbms pa->protocol = IPPROTO_UDP; 641191665Sbms DPRINTF(("getparm(dgram)\n")); 642191665Sbms return; 643191665Sbms 644191665Sbms case SOCK_STREAM: 645191665Sbms pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */ 646191665Sbms pa->protocol = IPPROTO_IP; 647191665Sbms DPRINTF(("getparm(stream)\n")); 648191665Sbms return; 649191665Sbms 650191665Sbms case SOCK_RAW: 651191665Sbms pa->type = SVR4_T_CLTS; 652191665Sbms pa->protocol = IPPROTO_RAW; 653191665Sbms DPRINTF(("getparm(raw)\n")); 654191665Sbms return; 655191665Sbms 656191665Sbms default: 657191665Sbms pa->type = 0; 658191665Sbms pa->protocol = 0; 659191665Sbms DPRINTF(("getparm(type %d?)\n", so->so_type)); 660191665Sbms return; 661191665Sbms } 662191665Sbms} 663191665Sbms 664191665Sbms 665191665Sbmsstatic int 666191665Sbmssi_ogetudata(fp, fd, ioc, td) 667191665Sbms struct file *fp; 668191665Sbms int fd; 669191665Sbms struct svr4_strioctl *ioc; 670191665Sbms struct thread *td; 671191665Sbms{ 672191665Sbms int error; 673191665Sbms struct svr4_si_oudata ud; 674191665Sbms struct svr4_si_sockparms pa; 675191665Sbms 676191665Sbms if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) { 677191665Sbms DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n", 678191665Sbms sizeof(ud), ioc->len)); 679191665Sbms return EINVAL; 680191665Sbms } 681191665Sbms 682191665Sbms if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 683191665Sbms return error; 684191665Sbms 685191665Sbms getparm(fp, &pa); 686191665Sbms 687191665Sbms switch (pa.family) { 688191665Sbms case AF_INET: 689191665Sbms ud.tidusize = 16384; 690191665Sbms ud.addrsize = sizeof(struct svr4_sockaddr_in); 691191665Sbms if (pa.type == SVR4_SOCK_STREAM) 692191665Sbms ud.etsdusize = 1; 693191665Sbms else 694191665Sbms ud.etsdusize = 0; 695191665Sbms break; 696191665Sbms 697191665Sbms case AF_LOCAL: 698191665Sbms ud.tidusize = 65536; 699191665Sbms ud.addrsize = 128; 700191665Sbms ud.etsdusize = 128; 701191665Sbms break; 702191665Sbms 703191665Sbms default: 704191665Sbms DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n", 705191665Sbms pa.family)); 706191665Sbms return ENOSYS; 707191665Sbms } 708191665Sbms 709191665Sbms /* I have no idea what these should be! */ 710191665Sbms ud.optsize = 128; 711191665Sbms ud.tsdusize = 128; 712191665Sbms 713191665Sbms ud.servtype = pa.type; 714191665Sbms 715191665Sbms /* XXX: Fixme */ 716191665Sbms ud.so_state = 0; 717191665Sbms ud.so_options = 0; 718191665Sbms return copyout(&ud, ioc->buf, ioc->len); 719191665Sbms} 720191665Sbms 721191665Sbms 722191665Sbmsstatic int 723191665Sbmssi_sockparams(fp, fd, ioc, td) 724191665Sbms struct file *fp; 725191665Sbms int fd; 726191665Sbms struct svr4_strioctl *ioc; 727191665Sbms struct thread *td; 728191665Sbms{ 729191665Sbms struct svr4_si_sockparms pa; 730191665Sbms 731191665Sbms getparm(fp, &pa); 732191665Sbms return copyout(&pa, ioc->buf, sizeof(pa)); 733191665Sbms} 734191665Sbms 735191665Sbms 736191665Sbmsstatic int 737191665Sbmssi_listen(fp, fd, ioc, td) 738191665Sbms struct file *fp; 739191665Sbms int fd; 740191665Sbms struct svr4_strioctl *ioc; 741191665Sbms struct thread *td; 742191665Sbms{ 743191665Sbms int error; 744191665Sbms struct svr4_strm *st = svr4_stream_get(fp); 745191665Sbms struct svr4_strmcmd lst; 746191665Sbms struct listen_args la; 747191665Sbms 748191665Sbms if (st == NULL) 749191665Sbms return EINVAL; 750191665Sbms 751191665Sbms if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0) 752191665Sbms return error; 753191665Sbms 754191665Sbms if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) { 755191665Sbms DPRINTF(("si_listen: bad request %ld\n", lst.cmd)); 756191665Sbms return EINVAL; 757191665Sbms } 758191665Sbms 759191665Sbms /* 760191665Sbms * We are making assumptions again... 761191665Sbms */ 762191665Sbms SCARG(&la, s) = fd; 763191665Sbms DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5)); 764191665Sbms SCARG(&la, backlog) = 5; 765191665Sbms 766191665Sbms if ((error = listen(td, &la)) != 0) { 767191665Sbms DPRINTF(("SI_LISTEN: listen failed %d\n", error)); 768191665Sbms return error; 769191665Sbms } 770191665Sbms 771191665Sbms st->s_cmd = SVR4_TI__ACCEPT_WAIT; 772191665Sbms lst.cmd = SVR4_TI_BIND_REPLY; 773191665Sbms 774191665Sbms switch (st->s_family) { 775191665Sbms case AF_INET: 776191665Sbms /* XXX: Fill the length here */ 777191665Sbms break; 778191665Sbms 779191665Sbms case AF_LOCAL: 780191665Sbms lst.len = 140; 781191665Sbms lst.pad[28] = 0x00000000; /* magic again */ 782191665Sbms lst.pad[29] = 0x00000800; /* magic again */ 783191665Sbms lst.pad[30] = 0x80001400; /* magic again */ 784191665Sbms break; 785191665Sbms 786191665Sbms default: 787191665Sbms DPRINTF(("SI_LISTEN: Unsupported address family %d\n", 788191665Sbms st->s_family)); 789191665Sbms return ENOSYS; 790191665Sbms } 791191665Sbms 792191665Sbms 793191665Sbms if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0) 794191665Sbms return error; 795191665Sbms 796191665Sbms return 0; 797191665Sbms} 798191665Sbms 799191665Sbms 800191665Sbmsstatic int 801191665Sbmssi_getudata(fp, fd, ioc, td) 802191665Sbms struct file *fp; 803191665Sbms int fd; 804191665Sbms struct svr4_strioctl *ioc; 805191665Sbms struct thread *td; 806191665Sbms{ 807191665Sbms int error; 808191665Sbms struct svr4_si_udata ud; 809191665Sbms 810191665Sbms if (sizeof(ud) != ioc->len) { 811191665Sbms DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n", 812191665Sbms sizeof(ud), ioc->len)); 813191665Sbms return EINVAL; 814191665Sbms } 815191665Sbms 816191665Sbms if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) 817191665Sbms return error; 818191665Sbms 819191665Sbms getparm(fp, &ud.sockparms); 820191665Sbms 821191665Sbms switch (ud.sockparms.family) { 822191665Sbms case AF_INET: 823191665Sbms DPRINTF(("getudata_inet\n")); 824191665Sbms ud.tidusize = 16384; 825191665Sbms ud.tsdusize = 16384; 826191665Sbms ud.addrsize = sizeof(struct svr4_sockaddr_in); 827191665Sbms if (ud.sockparms.type == SVR4_SOCK_STREAM) 828191665Sbms ud.etsdusize = 1; 829191665Sbms else 830191665Sbms ud.etsdusize = 0; 831191665Sbms ud.optsize = 0; 832191665Sbms break; 833191665Sbms 834191665Sbms case AF_LOCAL: 835191665Sbms DPRINTF(("getudata_local\n")); 836191665Sbms ud.tidusize = 65536; 837191665Sbms ud.tsdusize = 128; 838191665Sbms ud.addrsize = 128; 839191665Sbms ud.etsdusize = 128; 840191665Sbms ud.optsize = 128; 841191665Sbms break; 842191665Sbms 843191665Sbms default: 844191665Sbms DPRINTF(("SI_GETUDATA: Unsupported address family %d\n", 845191665Sbms ud.sockparms.family)); 846191665Sbms return ENOSYS; 847191665Sbms } 848191665Sbms 849191665Sbms 850191665Sbms ud.servtype = ud.sockparms.type; 851191665Sbms DPRINTF(("ud.servtype = %d\n", ud.servtype)); 852191665Sbms /* XXX: Fixme */ 853191665Sbms ud.so_state = 0; 854191665Sbms ud.so_options = 0; 855191665Sbms return copyout(&ud, ioc->buf, sizeof(ud)); 856191665Sbms} 857191665Sbms 858191665Sbms 859191665Sbmsstatic int 860191665Sbmssi_shutdown(fp, fd, ioc, td) 861191665Sbms struct file *fp; 862191665Sbms int fd; 863191665Sbms struct svr4_strioctl *ioc; 864191665Sbms struct thread *td; 865191665Sbms{ 866191665Sbms int error; 867191665Sbms struct shutdown_args ap; 868191665Sbms 869191665Sbms if (ioc->len != sizeof(SCARG(&ap, how))) { 870191665Sbms DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n", 871191665Sbms sizeof(SCARG(&ap, how)), ioc->len)); 872191665Sbms return EINVAL; 873191665Sbms } 874191665Sbms 875191665Sbms if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0) 876191665Sbms return error; 877191665Sbms 878191665Sbms SCARG(&ap, s) = fd; 879191665Sbms 880191665Sbms return shutdown(td, &ap); 881191665Sbms} 882191665Sbms 883191665Sbms 884191665Sbmsstatic int 885191665Sbmssockmod(fp, fd, ioc, td) 886191665Sbms struct file *fp; 887191665Sbms int fd; 888191665Sbms struct svr4_strioctl *ioc; 889191665Sbms struct thread *td; 890191665Sbms{ 891191665Sbms switch (ioc->cmd) { 892191665Sbms case SVR4_SI_OGETUDATA: 893191665Sbms DPRINTF(("SI_OGETUDATA\n")); 894191665Sbms return si_ogetudata(fp, fd, ioc, td); 895191665Sbms 896191665Sbms case SVR4_SI_SHUTDOWN: 897191665Sbms DPRINTF(("SI_SHUTDOWN\n")); 898191665Sbms return si_shutdown(fp, fd, ioc, td); 899191665Sbms 900191665Sbms case SVR4_SI_LISTEN: 901191665Sbms DPRINTF(("SI_LISTEN\n")); 902191665Sbms return si_listen(fp, fd, ioc, td); 903191665Sbms 904191665Sbms case SVR4_SI_SETMYNAME: 905191665Sbms DPRINTF(("SI_SETMYNAME\n")); 906191665Sbms return 0; 907191665Sbms 908191665Sbms case SVR4_SI_SETPEERNAME: 909191665Sbms DPRINTF(("SI_SETPEERNAME\n")); 910191665Sbms return 0; 911191665Sbms 912191665Sbms case SVR4_SI_GETINTRANSIT: 913191665Sbms DPRINTF(("SI_GETINTRANSIT\n")); 914191665Sbms return 0; 915191665Sbms 916191665Sbms case SVR4_SI_TCL_LINK: 917191665Sbms DPRINTF(("SI_TCL_LINK\n")); 918191665Sbms return 0; 919191665Sbms 920191665Sbms case SVR4_SI_TCL_UNLINK: 921191665Sbms DPRINTF(("SI_TCL_UNLINK\n")); 922191665Sbms return 0; 923191665Sbms 924191665Sbms case SVR4_SI_SOCKPARAMS: 925191665Sbms DPRINTF(("SI_SOCKPARAMS\n")); 926191665Sbms return si_sockparams(fp, fd, ioc, td); 927191665Sbms 928191665Sbms case SVR4_SI_GETUDATA: 929191665Sbms DPRINTF(("SI_GETUDATA\n")); 930191665Sbms return si_getudata(fp, fd, ioc, td); 931191665Sbms 932191665Sbms default: 933191665Sbms DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd)); 934191665Sbms return 0; 935191665Sbms 936191665Sbms } 937191665Sbms} 938191665Sbms 939191665Sbms 940191665Sbmsstatic int 941191665Sbmsti_getinfo(fp, fd, ioc, td) 942191665Sbms struct file *fp; 943191665Sbms int fd; 944191665Sbms struct svr4_strioctl *ioc; 945191665Sbms struct thread *td; 946191665Sbms{ 947191665Sbms int error; 948191665Sbms struct svr4_infocmd info; 949191665Sbms 950191665Sbms memset(&info, 0, sizeof(info)); 951191665Sbms 952191665Sbms if ((error = copyin(ioc->buf, &info, ioc->len)) != 0) 953191665Sbms return error; 954191665Sbms 955191665Sbms if (info.cmd != SVR4_TI_INFO_REQUEST) 956191665Sbms return EINVAL; 957191665Sbms 958191665Sbms info.cmd = SVR4_TI_INFO_REPLY; 959191665Sbms info.tsdu = 0; 960191665Sbms info.etsdu = 1; 961191665Sbms info.cdata = -2; 962191665Sbms info.ddata = -2; 963191665Sbms info.addr = 16; 964191665Sbms info.opt = -1; 965191665Sbms info.tidu = 16384; 966191665Sbms info.serv = 2; 967191665Sbms info.current = 0; 968191665Sbms info.provider = 2; 969191665Sbms 970191665Sbms ioc->len = sizeof(info); 971191665Sbms if ((error = copyout(&info, ioc->buf, ioc->len)) != 0) 972191665Sbms return error; 973191665Sbms 974191665Sbms return 0; 975191665Sbms} 976191665Sbms 977191665Sbms 978191665Sbmsstatic int 979191665Sbmsti_bind(fp, fd, ioc, td) 980191665Sbms struct file *fp; 981191665Sbms int fd; 982191665Sbms struct svr4_strioctl *ioc; 983191665Sbms struct thread *td; 984191665Sbms{ 985191665Sbms int error; 986191665Sbms struct svr4_strm *st = svr4_stream_get(fp); 987191665Sbms struct sockaddr_in sain; 988191665Sbms struct sockaddr_un saun; 989191665Sbms caddr_t sg; 990191665Sbms void *skp, *sup = NULL; 991191665Sbms int sasize; 992191665Sbms struct svr4_strmcmd bnd; 993191665Sbms struct bind_args ba; 994191665Sbms 995191665Sbms if (st == NULL) { 996191665Sbms DPRINTF(("ti_bind: bad file descriptor\n")); 997191665Sbms return EINVAL; 998191665Sbms } 999191665Sbms 1000191665Sbms if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0) 1001191665Sbms return error; 1002191665Sbms 1003191665Sbms if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) { 1004191665Sbms DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd)); 1005191665Sbms return EINVAL; 1006191665Sbms } 1007191665Sbms 1008191665Sbms switch (st->s_family) { 1009191665Sbms case AF_INET: 1010191665Sbms skp = &sain; 1011191665Sbms sasize = sizeof(sain); 1012191665Sbms 1013191665Sbms if (bnd.offs == 0) 1014191665Sbms goto reply; 1015191665Sbms 1016191665Sbms netaddr_to_sockaddr_in(&sain, &bnd); 1017191665Sbms 1018191665Sbms DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n", 1019191665Sbms sain.sin_family, sain.sin_port, 1020191665Sbms sain.sin_addr.s_addr)); 1021191665Sbms break; 1022191665Sbms 1023191665Sbms case AF_LOCAL: 1024191665Sbms skp = &saun; 1025191665Sbms sasize = sizeof(saun); 1026191665Sbms if (bnd.offs == 0) 1027191665Sbms goto reply; 1028191665Sbms 1029191665Sbms netaddr_to_sockaddr_un(&saun, &bnd); 1030191665Sbms 1031191665Sbms if (saun.sun_path[0] == '\0') 1032191665Sbms goto reply; 1033191665Sbms 1034191665Sbms DPRINTF(("TI_BIND: fam %d, path %s\n", 1035191665Sbms saun.sun_family, saun.sun_path)); 1036191665Sbms 1037191665Sbms if ((error = clean_pipe(td, saun.sun_path)) != 0) 1038191665Sbms return error; 1039191665Sbms 1040191665Sbms bnd.pad[28] = 0x00001000; /* magic again */ 1041191665Sbms break; 1042191665Sbms 1043191665Sbms default: 1044191665Sbms DPRINTF(("TI_BIND: Unsupported address family %d\n", 1045191665Sbms st->s_family)); 1046191665Sbms return ENOSYS; 1047191665Sbms } 1048191665Sbms 1049191665Sbms sg = stackgap_init(); 1050191665Sbms sup = stackgap_alloc(&sg, sasize); 1051191665Sbms 1052191665Sbms if ((error = copyout(skp, sup, sasize)) != 0) 1053191665Sbms return error; 1054191665Sbms 1055191665Sbms SCARG(&ba, s) = fd; 1056191665Sbms DPRINTF(("TI_BIND: fileno %d\n", fd)); 1057191665Sbms SCARG(&ba, name) = (void *) sup; 1058191665Sbms SCARG(&ba, namelen) = sasize; 1059191665Sbms 1060191665Sbms if ((error = bind(td, &ba)) != 0) { 1061191665Sbms DPRINTF(("TI_BIND: bind failed %d\n", error)); 1062191665Sbms return error; 1063191665Sbms } 1064191665Sbms 1065191665Sbmsreply: 1066191665Sbms if (sup == NULL) { 1067191665Sbms memset(&bnd, 0, sizeof(bnd)); 1068191665Sbms bnd.len = sasize + 4; 1069191665Sbms bnd.offs = 0x10; /* XXX */ 1070191665Sbms } 1071191665Sbms 1072191665Sbms bnd.cmd = SVR4_TI_BIND_REPLY; 1073191665Sbms 1074191665Sbms if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0) 1075191665Sbms return error; 1076191665Sbms 1077273857Sae return 0; 1078278979Sglebius} 1079191665Sbms 1080191665Sbms 1081191665Sbmsstatic int 1082191665Sbmstimod(fp, fd, ioc, td) 1083191665Sbms struct file *fp; 1084191665Sbms int fd; 1085191665Sbms struct svr4_strioctl *ioc; 1086191665Sbms struct thread *td; 1087191665Sbms{ 1088191665Sbms switch (ioc->cmd) { 1089191665Sbms case SVR4_TI_GETINFO: 1090191665Sbms DPRINTF(("TI_GETINFO\n")); 1091191665Sbms return ti_getinfo(fp, fd, ioc, td); 1092191665Sbms 1093191665Sbms case SVR4_TI_OPTMGMT: 1094191665Sbms DPRINTF(("TI_OPTMGMT\n")); 1095191665Sbms return 0; 1096191665Sbms 1097191665Sbms case SVR4_TI_BIND: 1098191665Sbms DPRINTF(("TI_BIND\n")); 1099191665Sbms return ti_bind(fp, fd, ioc, td); 1100191665Sbms 1101191665Sbms case SVR4_TI_UNBIND: 1102191665Sbms DPRINTF(("TI_UNBIND\n")); 1103191665Sbms return 0; 1104191665Sbms 1105191665Sbms default: 1106191665Sbms DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd)); 1107191665Sbms return 0; 1108191665Sbms } 1109191665Sbms} 1110191665Sbms 1111191665Sbms 1112191665Sbmsint 1113191665Sbmssvr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat) 1114191665Sbms struct file *fp; 1115191665Sbms struct thread *td; 1116191665Sbms register_t *retval; 1117191665Sbms int fd; 1118191665Sbms u_long cmd; 1119191665Sbms caddr_t dat; 1120191665Sbms{ 1121191665Sbms struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat; 1122191665Sbms struct svr4_strm *st = svr4_stream_get(fp); 1123191665Sbms int error; 1124191665Sbms void *skp, *sup; 1125191665Sbms struct sockaddr_in sain; 1126191665Sbms struct sockaddr_un saun; 1127191665Sbms struct svr4_strmcmd sc; 1128191665Sbms int sasize; 1129191665Sbms caddr_t sg; 1130191665Sbms int *lenp; 1131191665Sbms 1132191665Sbms DPRINTF(("svr4_stream_ti_ioctl\n")); 1133191665Sbms 1134191665Sbms if (st == NULL) 1135191665Sbms return EINVAL; 1136191665Sbms 1137191665Sbms sc.offs = 0x10; 1138191665Sbms 1139191665Sbms if ((error = copyin(sub, &skb, sizeof(skb))) != 0) { 1140191665Sbms DPRINTF(("ti_ioctl: error copying in strbuf\n")); 1141191665Sbms return error; 1142191665Sbms } 1143191665Sbms 1144191665Sbms switch (st->s_family) { 1145191665Sbms case AF_INET: 1146191665Sbms skp = &sain; 1147191665Sbms sasize = sizeof(sain); 1148191665Sbms break; 1149191665Sbms 1150191665Sbms case AF_LOCAL: 1151191665Sbms skp = &saun; 1152191665Sbms sasize = sizeof(saun); 1153191665Sbms break; 1154191665Sbms 1155191665Sbms default: 1156191665Sbms DPRINTF(("ti_ioctl: Unsupported address family %d\n", 1157191665Sbms st->s_family)); 1158191665Sbms return ENOSYS; 1159191665Sbms } 1160191665Sbms 1161191665Sbms sg = stackgap_init(); 1162191665Sbms sup = stackgap_alloc(&sg, sasize); 1163191665Sbms lenp = stackgap_alloc(&sg, sizeof(*lenp)); 1164191665Sbms 1165191665Sbms if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) { 1166191665Sbms DPRINTF(("ti_ioctl: error copying out lenp\n")); 1167191665Sbms return error; 1168191665Sbms } 1169191665Sbms 1170192923Sbms switch (cmd) { 1171192923Sbms case SVR4_TI_GETMYNAME: 1172192923Sbms DPRINTF(("TI_GETMYNAME\n")); 1173192923Sbms { 1174192923Sbms struct getsockname_args ap; 1175192923Sbms SCARG(&ap, fdes) = fd; 1176192923Sbms SCARG(&ap, asa) = sup; 1177192923Sbms SCARG(&ap, alen) = lenp; 1178192923Sbms if ((error = getsockname(td, &ap)) != 0) { 1179192923Sbms DPRINTF(("ti_ioctl: getsockname error\n")); 1180192923Sbms return error; 1181192923Sbms } 1182192923Sbms } 1183192923Sbms break; 1184191665Sbms 1185191665Sbms case SVR4_TI_GETPEERNAME: 1186191665Sbms DPRINTF(("TI_GETPEERNAME\n")); 1187260511Sae { 1188191665Sbms struct getpeername_args ap; 1189191665Sbms SCARG(&ap, fdes) = fd; 1190191665Sbms SCARG(&ap, asa) = sup; 1191191665Sbms SCARG(&ap, alen) = lenp; 1192191665Sbms if ((error = getpeername(td, &ap)) != 0) { 1193191665Sbms DPRINTF(("ti_ioctl: getpeername error\n")); 1194191665Sbms return error; 1195191665Sbms } 1196191665Sbms } 1197191665Sbms break; 1198191665Sbms 1199191665Sbms case SVR4_TI_SETMYNAME: 1200191665Sbms DPRINTF(("TI_SETMYNAME\n")); 1201191665Sbms return 0; 1202191665Sbms 1203191665Sbms case SVR4_TI_SETPEERNAME: 1204191665Sbms DPRINTF(("TI_SETPEERNAME\n")); 1205191665Sbms return 0; 1206191665Sbms default: 1207191665Sbms DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd)); 1208191665Sbms return ENOSYS; 1209191665Sbms } 1210191665Sbms 1211191665Sbms if ((error = copyin(sup, skp, sasize)) != 0) { 1212191665Sbms DPRINTF(("ti_ioctl: error copying in socket data\n")); 1213191665Sbms return error; 1214191665Sbms } 1215191665Sbms 1216191665Sbms if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) { 1217191665Sbms DPRINTF(("ti_ioctl: error copying in socket size\n")); 1218191665Sbms return error; 1219191665Sbms } 1220191665Sbms 1221191665Sbms switch (st->s_family) { 1222191665Sbms case AF_INET: 1223191665Sbms sockaddr_to_netaddr_in(&sc, &sain); 1224191665Sbms skb.len = sasize; 1225191665Sbms break; 1226191665Sbms 1227191665Sbms case AF_LOCAL: 1228191665Sbms sockaddr_to_netaddr_un(&sc, &saun); 1229191665Sbms skb.len = sasize + 4; 1230191665Sbms break; 1231191665Sbms 1232191665Sbms default: 1233191665Sbms return ENOSYS; 1234191665Sbms } 1235191665Sbms 1236191665Sbms 1237191665Sbms if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) { 1238191665Sbms DPRINTF(("ti_ioctl: error copying out socket data\n")); 1239191665Sbms return error; 1240191665Sbms } 1241191665Sbms 1242191665Sbms 1243191665Sbms if ((error = copyout(&skb, sub, sizeof(skb))) != 0) { 1244191665Sbms DPRINTF(("ti_ioctl: error copying out strbuf\n")); 1245191665Sbms return error; 1246191665Sbms } 1247191665Sbms 1248191665Sbms return error; 1249191665Sbms} 1250191665Sbms 1251191665Sbms 1252191665Sbms 1253191665Sbms 1254191665Sbmsstatic int 1255191665Sbmsi_nread(fp, td, retval, fd, cmd, dat) 1256191665Sbms struct file *fp; 1257191665Sbms struct thread *td; 1258191665Sbms register_t *retval; 1259191665Sbms int fd; 1260191665Sbms u_long cmd; 1261191665Sbms caddr_t dat; 1262191665Sbms{ 1263191665Sbms int error; 1264191665Sbms int nread = 0; 1265191665Sbms 1266191665Sbms /* 1267191665Sbms * We are supposed to return the message length in nread, and the 1268191665Sbms * number of messages in retval. We don't have the notion of number 1269191665Sbms * of stream messages, so we just find out if we have any bytes waiting 1270191665Sbms * for us, and if we do, then we assume that we have at least one 1271191665Sbms * message waiting for us. 1272191665Sbms */ 1273191665Sbms if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td)) != 0) 1274191665Sbms return error; 1275191665Sbms 1276191665Sbms if (nread != 0) 1277191665Sbms *retval = 1; 1278260511Sae else 1279191665Sbms *retval = 0; 1280191665Sbms 1281191665Sbms return copyout(&nread, dat, sizeof(nread)); 1282191665Sbms} 1283191665Sbms 1284191665Sbmsstatic int 1285191665Sbmsi_fdinsert(fp, td, retval, fd, cmd, dat) 1286191665Sbms struct file *fp; 1287191665Sbms struct thread *td; 1288191665Sbms register_t *retval; 1289191665Sbms int fd; 1290191665Sbms u_long cmd; 1291191665Sbms caddr_t dat; 1292191665Sbms{ 1293191665Sbms /* 1294191665Sbms * Major hack again here. We assume that we are using this to 1295191665Sbms * implement accept(2). If that is the case, we have already 1296191665Sbms * called accept, and we have stored the file descriptor in 1297191665Sbms * afd. We find the file descriptor that the code wants to use 1298191665Sbms * in fd insert, and then we dup2() our accepted file descriptor 1299191665Sbms * to it. 1300191665Sbms */ 1301191665Sbms int error; 1302191665Sbms struct svr4_strm *st = svr4_stream_get(fp); 1303191665Sbms struct svr4_strfdinsert fdi; 1304191665Sbms struct dup2_args d2p; 1305191665Sbms struct close_args clp; 1306191665Sbms 1307191665Sbms if (st == NULL) { 1308191665Sbms DPRINTF(("fdinsert: bad file type\n")); 1309191665Sbms return EINVAL; 1310191665Sbms } 1311191665Sbms 1312191665Sbms if (st->s_afd == -1) { 1313191665Sbms DPRINTF(("fdinsert: accept fd not found\n")); 1314191665Sbms return ENOENT; 1315191665Sbms } 1316191665Sbms 1317191665Sbms if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) { 1318191665Sbms DPRINTF(("fdinsert: copyin failed %d\n", error)); 1319191665Sbms return error; 1320191665Sbms } 1321191665Sbms 1322191665Sbms SCARG(&d2p, from) = st->s_afd; 1323191665Sbms SCARG(&d2p, to) = fdi.fd; 1324191665Sbms 1325191665Sbms if ((error = dup2(td, &d2p)) != 0) { 1326191665Sbms DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n", 1327191665Sbms st->s_afd, fdi.fd, error)); 1328191665Sbms return error; 1329191665Sbms } 1330191665Sbms 1331191665Sbms SCARG(&clp, fd) = st->s_afd; 1332191665Sbms 1333191665Sbms if ((error = close(td, &clp)) != 0) { 1334191665Sbms DPRINTF(("fdinsert: close(%d) failed %d\n", 1335191665Sbms st->s_afd, error)); 1336191665Sbms return error; 1337191665Sbms } 1338191665Sbms 1339191665Sbms st->s_afd = -1; 1340191665Sbms 1341191665Sbms *retval = 0; 1342191665Sbms return 0; 1343191665Sbms} 1344191665Sbms 1345191665Sbms 1346191665Sbmsstatic int 1347191665Sbms_i_bind_rsvd(fp, td, retval, fd, cmd, dat) 1348191665Sbms struct file *fp; 1349191665Sbms struct thread *td; 1350191665Sbms register_t *retval; 1351191665Sbms int fd; 1352191665Sbms u_long cmd; 1353191665Sbms caddr_t dat; 1354191665Sbms{ 1355191665Sbms struct mkfifo_args ap; 1356191665Sbms 1357191665Sbms /* 1358191665Sbms * This is a supposed to be a kernel and library only ioctl. 1359191665Sbms * It gets called before ti_bind, when we have a unix 1360191665Sbms * socket, to physically create the socket transport and 1361191665Sbms * ``reserve'' it. I don't know how this get reserved inside 1362191665Sbms * the kernel, but we are going to create it nevertheless. 1363191665Sbms */ 1364191665Sbms SCARG(&ap, path) = dat; 1365191665Sbms SCARG(&ap, mode) = S_IFIFO; 1366191665Sbms 1367191665Sbms return mkfifo(td, &ap); 1368191665Sbms} 1369191665Sbms 1370191665Sbmsstatic int 1371191665Sbms_i_rele_rsvd(fp, td, retval, fd, cmd, dat) 1372191665Sbms struct file *fp; 1373191665Sbms struct thread *td; 1374191665Sbms register_t *retval; 1375191665Sbms int fd; 1376191665Sbms u_long cmd; 1377191665Sbms caddr_t dat; 1378191665Sbms{ 1379191665Sbms struct unlink_args ap; 1380191665Sbms 1381191665Sbms /* 1382191665Sbms * This is a supposed to be a kernel and library only ioctl. 1383191665Sbms * I guess it is supposed to release the socket. 1384192923Sbms */ 1385192923Sbms SCARG(&ap, path) = dat; 1386191665Sbms 1387191665Sbms return unlink(td, &ap); 1388191665Sbms} 1389191665Sbms 1390191665Sbmsstatic int 1391191665Sbmsi_str(fp, td, retval, fd, cmd, dat) 1392191665Sbms struct file *fp; 1393191665Sbms struct thread *td; 1394191665Sbms register_t *retval; 1395191665Sbms int fd; 1396191665Sbms u_long cmd; 1397191665Sbms caddr_t dat; 1398191665Sbms{ 1399191665Sbms int error; 1400191665Sbms struct svr4_strioctl ioc; 1401191665Sbms 1402191665Sbms if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0) 1403191665Sbms return error; 1404191665Sbms 1405191665Sbms#ifdef DEBUG_SVR4 1406191665Sbms if ((error = show_ioc(">", &ioc)) != 0) 1407191665Sbms return error; 1408191665Sbms#endif /* DEBUG_SVR4 */ 1409191665Sbms 1410191665Sbms switch (ioc.cmd & 0xff00) { 1411191665Sbms case SVR4_SIMOD: 1412191665Sbms if ((error = sockmod(fp, fd, &ioc, td)) != 0) 1413191665Sbms return error; 1414191665Sbms break; 1415191665Sbms 1416191665Sbms case SVR4_TIMOD: 1417191665Sbms if ((error = timod(fp, fd, &ioc, td)) != 0) 1418191665Sbms return error; 1419191665Sbms break; 1420191665Sbms 1421191665Sbms default: 1422191665Sbms DPRINTF(("Unimplemented module %c %ld\n", 1423191665Sbms (char) (cmd >> 8), cmd & 0xff)); 1424191665Sbms return 0; 1425191665Sbms } 1426191665Sbms 1427191665Sbms#ifdef DEBUG_SVR4 1428191665Sbms if ((error = show_ioc("<", &ioc)) != 0) 1429191665Sbms return error; 1430191665Sbms#endif /* DEBUG_SVR4 */ 1431191665Sbms return copyout(&ioc, dat, sizeof(ioc)); 1432191665Sbms} 1433191665Sbms 1434191665Sbmsstatic int 1435191665Sbmsi_setsig(fp, td, retval, fd, cmd, dat) 1436191665Sbms struct file *fp; 1437191665Sbms struct thread *td; 1438191665Sbms register_t *retval; 1439191665Sbms int fd; 1440191665Sbms u_long cmd; 1441191665Sbms caddr_t dat; 1442191665Sbms{ 1443191665Sbms /* 1444191665Sbms * This is the best we can do for now; we cannot generate 1445191665Sbms * signals only for specific events so the signal mask gets 1446191665Sbms * ignored; we save it just to pass it to a possible I_GETSIG... 1447191665Sbms * 1448191665Sbms * We alse have to fix the O_ASYNC fcntl bit, so the 1449191665Sbms * process will get SIGPOLLs. 1450191665Sbms */ 1451191665Sbms struct fcntl_args fa; 1452191665Sbms int error; 1453264364Sae register_t oflags, flags; 1454191665Sbms struct svr4_strm *st = svr4_stream_get(fp); 1455264364Sae 1456264364Sae if (st == NULL) { 1457264364Sae DPRINTF(("i_setsig: bad file descriptor\n")); 1458264364Sae return EINVAL; 1459264364Sae } 1460191665Sbms /* get old status flags */ 1461191665Sbms SCARG(&fa, fd) = fd; 1462191665Sbms SCARG(&fa, cmd) = F_GETFL; 1463191665Sbms if ((error = fcntl(td, &fa)) != 0) 1464191665Sbms return error; 1465191665Sbms 1466191665Sbms oflags = td->td_retval[0]; 1467191665Sbms 1468191665Sbms /* update the flags */ 1469191665Sbms if (dat != NULL) { 1470191665Sbms int mask; 1471191665Sbms 1472191665Sbms flags = oflags | O_ASYNC; 1473191665Sbms if ((error = copyin(dat, &mask, sizeof(mask))) != 0) { 1474191665Sbms DPRINTF(("i_setsig: bad eventmask pointer\n")); 1475191665Sbms return error; 1476191665Sbms } 1477191665Sbms if (mask & SVR4_S_ALLMASK) { 1478191665Sbms DPRINTF(("i_setsig: bad eventmask data %x\n", mask)); 1479191665Sbms return EINVAL; 1480191665Sbms } 1481191665Sbms st->s_eventmask = mask; 1482191665Sbms } 1483191665Sbms else { 1484191665Sbms flags = oflags & ~O_ASYNC; 1485191665Sbms st->s_eventmask = 0; 1486191665Sbms } 1487191665Sbms 1488191665Sbms /* set the new flags, if changed */ 1489191665Sbms if (flags != oflags) { 1490191665Sbms SCARG(&fa, cmd) = F_SETFL; 1491191665Sbms SCARG(&fa, arg) = (long) flags; 1492191665Sbms if ((error = fcntl(td, &fa)) != 0) 1493191665Sbms return error; 1494191665Sbms flags = td->td_retval[0]; 1495191665Sbms } 1496191665Sbms 1497191665Sbms /* set up SIGIO receiver if needed */ 1498191665Sbms if (dat != NULL) { 1499191665Sbms SCARG(&fa, cmd) = F_SETOWN; 1500191665Sbms SCARG(&fa, arg) = (long) td->td_proc->p_pid; 1501191665Sbms return fcntl(td, &fa); 1502191665Sbms } 1503191665Sbms return 0; 1504191665Sbms} 1505191665Sbms 1506191665Sbmsstatic int 1507191665Sbmsi_getsig(fp, td, retval, fd, cmd, dat) 1508191665Sbms struct file *fp; 1509191665Sbms struct thread *td; 1510191665Sbms register_t *retval; 1511191665Sbms int fd; 1512191665Sbms u_long cmd; 1513191665Sbms caddr_t dat; 1514191665Sbms{ 1515191665Sbms int error; 1516191665Sbms 1517191665Sbms if (dat != NULL) { 1518191665Sbms struct svr4_strm *st = svr4_stream_get(fp); 1519191665Sbms 1520191665Sbms if (st == NULL) { 1521191665Sbms DPRINTF(("i_getsig: bad file descriptor\n")); 1522191665Sbms return EINVAL; 1523191665Sbms } 1524191665Sbms if ((error = copyout(&st->s_eventmask, dat, 1525191665Sbms sizeof(st->s_eventmask))) != 0) { 1526191665Sbms DPRINTF(("i_getsig: bad eventmask pointer\n")); 1527191665Sbms return error; 1528191665Sbms } 1529191665Sbms } 1530191665Sbms return 0; 1531191665Sbms} 1532191665Sbms 1533191665Sbmsint 1534191665Sbmssvr4_stream_ioctl(fp, td, retval, fd, cmd, dat) 1535191665Sbms struct file *fp; 1536191665Sbms struct thread *td; 1537191665Sbms register_t *retval; 1538191665Sbms int fd; 1539191665Sbms u_long cmd; 1540191665Sbms caddr_t dat; 1541191665Sbms{ 1542191665Sbms *retval = 0; 1543191665Sbms 1544191665Sbms /* 1545191665Sbms * All the following stuff assumes "sockmod" is pushed... 1546191665Sbms */ 1547191665Sbms switch (cmd) { 1548191665Sbms case SVR4_I_NREAD: 1549191665Sbms DPRINTF(("I_NREAD\n")); 1550191665Sbms return i_nread(fp, td, retval, fd, cmd, dat); 1551191665Sbms 1552191665Sbms case SVR4_I_PUSH: 1553191665Sbms DPRINTF(("I_PUSH %p\n", dat)); 1554191665Sbms#if defined(DEBUG_SVR4) 1555191665Sbms show_strbuf((struct svr4_strbuf *)dat); 1556191665Sbms#endif 1557191665Sbms return 0; 1558191665Sbms 1559191665Sbms case SVR4_I_POP: 1560191665Sbms DPRINTF(("I_POP\n")); 1561191665Sbms return 0; 1562191665Sbms 1563191665Sbms case SVR4_I_LOOK: 1564191665Sbms DPRINTF(("I_LOOK\n")); 1565191665Sbms return 0; 1566191665Sbms 1567191665Sbms case SVR4_I_FLUSH: 1568191665Sbms DPRINTF(("I_FLUSH\n")); 1569191665Sbms return 0; 1570191665Sbms 1571191665Sbms case SVR4_I_SRDOPT: 1572191665Sbms DPRINTF(("I_SRDOPT\n")); 1573191665Sbms return 0; 1574191665Sbms 1575191665Sbms case SVR4_I_GRDOPT: 1576191665Sbms DPRINTF(("I_GRDOPT\n")); 1577191665Sbms return 0; 1578191665Sbms 1579191665Sbms case SVR4_I_STR: 1580191665Sbms DPRINTF(("I_STR\n")); 1581191665Sbms return i_str(fp, td, retval, fd, cmd, dat); 1582191665Sbms 1583191665Sbms case SVR4_I_SETSIG: 1584191665Sbms DPRINTF(("I_SETSIG\n")); 1585191665Sbms return i_setsig(fp, td, retval, fd, cmd, dat); 1586191665Sbms 1587191665Sbms case SVR4_I_GETSIG: 1588191665Sbms DPRINTF(("I_GETSIG\n")); 1589192923Sbms return i_getsig(fp, td, retval, fd, cmd, dat); 1590192923Sbms 1591191665Sbms case SVR4_I_FIND: 1592191665Sbms DPRINTF(("I_FIND\n")); 1593192923Sbms /* 1594192923Sbms * Here we are not pushing modules really, we just 1595192923Sbms * pretend all are present 1596192923Sbms */ 1597192923Sbms *retval = 0; 1598192923Sbms return 0; 1599191665Sbms 1600191665Sbms case SVR4_I_LINK: 1601192923Sbms DPRINTF(("I_LINK\n")); 1602192923Sbms return 0; 1603191665Sbms 1604191665Sbms case SVR4_I_UNLINK: 1605191665Sbms DPRINTF(("I_UNLINK\n")); 1606191665Sbms return 0; 1607191665Sbms 1608191665Sbms case SVR4_I_ERECVFD: 1609191665Sbms DPRINTF(("I_ERECVFD\n")); 1610191665Sbms return 0; 1611191665Sbms 1612191665Sbms case SVR4_I_PEEK: 1613191665Sbms DPRINTF(("I_PEEK\n")); 1614191665Sbms return 0; 1615191665Sbms 1616191665Sbms case SVR4_I_FDINSERT: 1617191665Sbms DPRINTF(("I_FDINSERT\n")); 1618191665Sbms return i_fdinsert(fp, td, retval, fd, cmd, dat); 1619191665Sbms 1620191665Sbms case SVR4_I_SENDFD: 1621191665Sbms DPRINTF(("I_SENDFD\n")); 1622191665Sbms return 0; 1623191665Sbms 1624191665Sbms case SVR4_I_RECVFD: 1625191665Sbms DPRINTF(("I_RECVFD\n")); 1626191665Sbms return 0; 1627191665Sbms 1628191665Sbms case SVR4_I_SWROPT: 1629191665Sbms DPRINTF(("I_SWROPT\n")); 1630191665Sbms return 0; 1631191665Sbms 1632254629Sdelphij case SVR4_I_GWROPT: 1633254629Sdelphij DPRINTF(("I_GWROPT\n")); 1634191665Sbms return 0; 1635191665Sbms 1636191665Sbms case SVR4_I_LIST: 1637191665Sbms DPRINTF(("I_LIST\n")); 1638191665Sbms return 0; 1639191665Sbms 1640191665Sbms case SVR4_I_PLINK: 1641191665Sbms DPRINTF(("I_PLINK\n")); 1642191665Sbms return 0; 1643191665Sbms 1644191665Sbms case SVR4_I_PUNLINK: 1645191665Sbms DPRINTF(("I_PUNLINK\n")); 1646191665Sbms return 0; 1647191665Sbms 1648191665Sbms case SVR4_I_SETEV: 1649191665Sbms DPRINTF(("I_SETEV\n")); 1650191665Sbms return 0; 1651191665Sbms 1652191665Sbms case SVR4_I_GETEV: 1653191665Sbms DPRINTF(("I_GETEV\n")); 1654191665Sbms return 0; 1655191665Sbms 1656191665Sbms case SVR4_I_STREV: 1657191665Sbms DPRINTF(("I_STREV\n")); 1658191665Sbms return 0; 1659191665Sbms 1660191665Sbms case SVR4_I_UNSTREV: 1661191665Sbms DPRINTF(("I_UNSTREV\n")); 1662191665Sbms return 0; 1663191665Sbms 1664191665Sbms case SVR4_I_FLUSHBAND: 1665191665Sbms DPRINTF(("I_FLUSHBAND\n")); 1666191665Sbms return 0; 1667191665Sbms 1668191665Sbms case SVR4_I_CKBAND: 1669191665Sbms DPRINTF(("I_CKBAND\n")); 1670191665Sbms return 0; 1671191665Sbms 1672191665Sbms case SVR4_I_GETBAND: 1673191665Sbms DPRINTF(("I_GETBANK\n")); 1674191665Sbms return 0; 1675191665Sbms 1676191665Sbms case SVR4_I_ATMARK: 1677191665Sbms DPRINTF(("I_ATMARK\n")); 1678191665Sbms return 0; 1679191665Sbms 1680191665Sbms case SVR4_I_SETCLTIME: 1681191665Sbms DPRINTF(("I_SETCLTIME\n")); 1682191665Sbms return 0; 1683191665Sbms 1684191665Sbms case SVR4_I_GETCLTIME: 1685191665Sbms DPRINTF(("I_GETCLTIME\n")); 1686191665Sbms return 0; 1687191665Sbms 1688191665Sbms case SVR4_I_CANPUT: 1689191665Sbms DPRINTF(("I_CANPUT\n")); 1690191672Sbms return 0; 1691191672Sbms 1692191672Sbms case SVR4__I_BIND_RSVD: 1693191665Sbms DPRINTF(("_I_BIND_RSVD\n")); 1694191665Sbms return _i_bind_rsvd(fp, td, retval, fd, cmd, dat); 1695191672Sbms 1696191665Sbms case SVR4__I_RELE_RSVD: 1697191665Sbms DPRINTF(("_I_RELE_RSVD\n")); 1698191665Sbms return _i_rele_rsvd(fp, td, retval, fd, cmd, dat); 1699191665Sbms 1700191665Sbms default: 1701191665Sbms DPRINTF(("unimpl cmd = %lx\n", cmd)); 1702191665Sbms break; 1703191665Sbms } 1704191665Sbms 1705191665Sbms return 0; 1706191665Sbms} 1707191665Sbms 1708191665Sbms 1709191665Sbms 1710191672Sbmsint 1711191665Sbmssvr4_sys_putmsg(td, uap) 1712191665Sbms register struct thread *td; 1713191672Sbms struct svr4_sys_putmsg_args *uap; 1714191665Sbms{ 1715191665Sbms struct file *fp; 1716191672Sbms int error; 1717191665Sbms 1718191665Sbms if ((error = fget(td, uap->fd, &fp)) != 0) { 1719191665Sbms#ifdef DEBUG_SVR4 1720191672Sbms uprintf("putmsg: bad fp\n"); 1721191672Sbms#endif 1722191665Sbms return EBADF; 1723227481Sbz } 1724191665Sbms error = svr4_do_putmsg(td, uap, fp); 1725191665Sbms fdrop(fp, td); 1726191665Sbms return (error); 1727191665Sbms} 1728191665Sbms 1729191672Sbmsstatic int 1730191672Sbmssvr4_do_putmsg(td, uap, fp) 1731191665Sbms struct thread *td; 1732191672Sbms struct svr4_sys_putmsg_args *uap; 1733191665Sbms struct file *fp; 1734191665Sbms{ 1735191665Sbms struct svr4_strbuf dat, ctl; 1736191665Sbms struct svr4_strmcmd sc; 1737191665Sbms struct sockaddr_in sain; 1738191672Sbms struct sockaddr_un saun; 1739191665Sbms void *skp, *sup; 1740191665Sbms int sasize, *retval; 1741191665Sbms struct svr4_strm *st; 1742191665Sbms int error; 1743191665Sbms caddr_t sg; 1744191665Sbms 1745191665Sbms retval = td->td_retval; 1746191665Sbms 1747191665Sbms#ifdef DEBUG_SVR4 1748191665Sbms show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl), 1749191665Sbms SCARG(uap, dat), SCARG(uap, flags)); 1750191665Sbms#endif /* DEBUG_SVR4 */ 1751191665Sbms 1752191665Sbms FILE_LOCK_ASSERT(fp, MA_NOTOWNED); 1753191665Sbms 1754191665Sbms if (SCARG(uap, ctl) != NULL) { 1755191665Sbms if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) { 1756191665Sbms#ifdef DEBUG_SVR4 1757191665Sbms uprintf("putmsg: copyin(): %d\n", error); 1758191672Sbms#endif 1759191672Sbms return error; 1760191672Sbms } 1761191672Sbms } 1762191672Sbms else 1763191672Sbms ctl.len = -1; 1764191672Sbms 1765191672Sbms if (SCARG(uap, dat) != NULL) { 1766191672Sbms if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) { 1767191672Sbms#ifdef DEBUG_SVR4 1768191672Sbms uprintf("putmsg: copyin(): %d (2)\n", error); 1769191672Sbms#endif 1770191672Sbms return error; 1771191672Sbms } 1772191672Sbms } 1773231852Sbz else 1774191672Sbms dat.len = -1; 1775191672Sbms 1776292015Smelifaro /* 1777292015Smelifaro * Only for sockets for now. 1778292015Smelifaro */ 1779292015Smelifaro if ((st = svr4_stream_get(fp)) == NULL) { 1780191672Sbms DPRINTF(("putmsg: bad file type\n")); 1781191672Sbms return EINVAL; 1782191672Sbms } 1783191672Sbms 1784191672Sbms if (ctl.len > sizeof(sc)) { 1785191672Sbms DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len, 1786292015Smelifaro sizeof(struct svr4_strmcmd))); 1787292015Smelifaro return EINVAL; 1788292015Smelifaro } 1789292015Smelifaro 1790191672Sbms if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 1791292015Smelifaro return error; 1792191672Sbms 1793191672Sbms switch (st->s_family) { 1794191672Sbms case AF_INET: 1795191665Sbms if (sc.len != sizeof(sain)) { 1796191672Sbms if (sc.cmd == SVR4_TI_DATA_REQUEST) { 1797191672Sbms struct write_args wa; 1798191672Sbms 1799191665Sbms /* Solaris seems to use sc.cmd = 3 to 1800191665Sbms * send "expedited" data. telnet uses 1801191665Sbms * this for options processing, sending EOF, 1802191665Sbms * etc. I'm sure other things use it too. 1803191665Sbms * I don't have any documentation 1804191665Sbms * on it, so I'm making a guess that this 1805191665Sbms * is how it works. newton@atdot.dotat.org XXX 1806191665Sbms */ 1807191665Sbms DPRINTF(("sending expedited data ??\n")); 1808191665Sbms SCARG(&wa, fd) = SCARG(uap, fd); 1809191665Sbms SCARG(&wa, buf) = dat.buf; 1810191665Sbms SCARG(&wa, nbyte) = dat.len; 1811191665Sbms return write(td, &wa); 1812191665Sbms } 1813191665Sbms DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len)); 1814191665Sbms return EINVAL; 1815199528Sbms } 1816191665Sbms netaddr_to_sockaddr_in(&sain, &sc); 1817191665Sbms skp = &sain; 1818191665Sbms sasize = sizeof(sain); 1819191665Sbms error = sain.sin_family != st->s_family; 1820191665Sbms break; 1821191665Sbms 1822191665Sbms case AF_LOCAL: 1823191665Sbms if (ctl.len == 8) { 1824191665Sbms /* We are doing an accept; succeed */ 1825192923Sbms DPRINTF(("putmsg: Do nothing\n")); 1826192923Sbms *retval = 0; 1827192923Sbms return 0; 1828192923Sbms } 1829192923Sbms else { 1830192923Sbms /* Maybe we've been given a device/inode pair */ 1831191665Sbms udev_t *dev = SVR4_ADDROF(&sc); 1832191665Sbms ino_t *ino = (ino_t *) &dev[1]; 1833191665Sbms skp = svr4_find_socket(td, fp, *dev, *ino); 1834191665Sbms if (skp == NULL) { 1835191665Sbms skp = &saun; 1836191665Sbms /* I guess we have it by name */ 1837191665Sbms netaddr_to_sockaddr_un(skp, &sc); 1838191665Sbms } 1839191665Sbms sasize = sizeof(saun); 1840191665Sbms } 1841191665Sbms break; 1842191665Sbms 1843191665Sbms default: 1844191672Sbms DPRINTF(("putmsg: Unsupported address family %d\n", 1845191672Sbms st->s_family)); 1846191672Sbms return ENOSYS; 1847259884Sbz } 1848191672Sbms 1849191672Sbms sg = stackgap_init(); 1850191672Sbms sup = stackgap_alloc(&sg, sasize); 1851191665Sbms 1852191665Sbms if ((error = copyout(skp, sup, sasize)) != 0) 1853191665Sbms return error; 1854191665Sbms 1855191665Sbms switch (st->s_cmd = sc.cmd) { 1856191665Sbms case SVR4_TI_CONNECT_REQUEST: /* connect */ 1857191665Sbms { 1858191665Sbms struct connect_args co; 1859191665Sbms 1860191665Sbms SCARG(&co, s) = SCARG(uap, fd); 1861191665Sbms SCARG(&co, name) = (void *) sup; 1862191665Sbms SCARG(&co, namelen) = (int) sasize; 1863191665Sbms 1864191665Sbms return connect(td, &co); 1865191665Sbms } 1866191665Sbms 1867191665Sbms case SVR4_TI_SENDTO_REQUEST: /* sendto */ 1868191665Sbms { 1869191665Sbms struct msghdr msg; 1870191665Sbms struct iovec aiov; 1871191665Sbms 1872191665Sbms msg.msg_name = (caddr_t) sup; 1873191665Sbms msg.msg_namelen = sasize; 1874191665Sbms msg.msg_iov = &aiov; 1875191665Sbms msg.msg_iovlen = 1; 1876191665Sbms msg.msg_control = 0; 1877192923Sbms msg.msg_flags = 0; 1878192923Sbms aiov.iov_base = dat.buf; 1879192923Sbms aiov.iov_len = dat.len; 1880192923Sbms#if 0 1881192923Sbms error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 1882192923Sbms uio, 0, 0, 0, uio->uio_td); 1883192923Sbms#endif 1884192923Sbms error = svr4_sendit(td, SCARG(uap, fd), &msg, 1885191665Sbms SCARG(uap, flags)); 1886192923Sbms DPRINTF(("sendto_request error: %d\n", error)); 1887191665Sbms *retval = 0; 1888191665Sbms return error; 1889191665Sbms } 1890191665Sbms 1891191665Sbms default: 1892191665Sbms DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd)); 1893191665Sbms return ENOSYS; 1894191665Sbms } 1895191665Sbms} 1896191665Sbms 1897191665Sbmsint 1898191665Sbmssvr4_sys_getmsg(td, uap) 1899191665Sbms struct thread *td; 1900191665Sbms struct svr4_sys_getmsg_args *uap; 1901191665Sbms{ 1902191665Sbms struct file *fp; 1903191665Sbms int error; 1904191665Sbms 1905191665Sbms if ((error = fget(td, uap->fd, &fp)) != 0) { 1906191665Sbms#ifdef DEBUG_SVR4 1907192923Sbms uprintf("getmsg: bad fp\n"); 1908192923Sbms#endif 1909192923Sbms return EBADF; 1910191665Sbms } 1911192923Sbms error = svr4_do_getmsg(td, uap, fp); 1912192923Sbms fdrop(fp, td); 1913192923Sbms return (error); 1914192923Sbms} 1915191672Sbms 1916192923Sbmsint 1917191672Sbmssvr4_do_getmsg(td, uap, fp) 1918191665Sbms register struct thread *td; 1919191665Sbms struct svr4_sys_getmsg_args *uap; 1920191665Sbms struct file *fp; 1921191665Sbms{ 1922191665Sbms struct getpeername_args ga; 1923191665Sbms struct accept_args aa; 1924191665Sbms struct svr4_strbuf dat, ctl; 1925199526Sbms struct svr4_strmcmd sc; 1926199526Sbms int error, *retval; 1927199526Sbms struct msghdr msg; 1928199526Sbms struct iovec aiov; 1929199526Sbms struct sockaddr_in sain; 1930199526Sbms struct sockaddr_un saun; 1931199526Sbms void *skp, *sup; 1932199526Sbms int sasize; 1933199526Sbms struct svr4_strm *st; 1934199526Sbms int *flen; 1935199528Sbms int fl; 1936199528Sbms caddr_t sg; 1937199528Sbms 1938199528Sbms retval = td->td_retval; 1939199528Sbms 1940199528Sbms FILE_LOCK_ASSERT(fp, MA_NOTOWNED); 1941199528Sbms 1942199528Sbms memset(&sc, 0, sizeof(sc)); 1943199528Sbms 1944199528Sbms#ifdef DEBUG_SVR4 1945199528Sbms show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl), 1946199528Sbms SCARG(uap, dat), 0); 1947199528Sbms#endif /* DEBUG_SVR4 */ 1948199528Sbms 1949199528Sbms if (SCARG(uap, ctl) != NULL) { 1950199528Sbms if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) 1951199526Sbms return error; 1952199528Sbms } 1953199528Sbms else { 1954199526Sbms ctl.len = -1; 1955199526Sbms ctl.maxlen = 0; 1956199526Sbms } 1957199526Sbms 1958199526Sbms if (SCARG(uap, dat) != NULL) { 1959199527Sbms if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) 1960199527Sbms return error; 1961199527Sbms } 1962199527Sbms else { 1963199527Sbms dat.len = -1; 1964199527Sbms dat.maxlen = 0; 1965199527Sbms } 1966199527Sbms 1967199527Sbms /* 1968199526Sbms * Only for sockets for now. 1969199527Sbms */ 1970199527Sbms if ((st = svr4_stream_get(fp)) == NULL) { 1971191665Sbms DPRINTF(("getmsg: bad file type\n")); 1972191665Sbms return EINVAL; 1973191665Sbms } 1974191665Sbms 1975191665Sbms if (ctl.maxlen == -1 || dat.maxlen == -1) { 1976191665Sbms DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n")); 1977191665Sbms return ENOSYS; 1978191665Sbms } 1979191665Sbms 1980191665Sbms switch (st->s_family) { 1981191665Sbms case AF_INET: 1982191665Sbms skp = &sain; 1983191665Sbms sasize = sizeof(sain); 1984191665Sbms break; 1985191665Sbms 1986191665Sbms case AF_LOCAL: 1987191665Sbms skp = &saun; 1988191665Sbms sasize = sizeof(saun); 1989191665Sbms break; 1990191665Sbms 1991191665Sbms default: 1992191665Sbms DPRINTF(("getmsg: Unsupported address family %d\n", 1993191665Sbms st->s_family)); 1994191665Sbms return ENOSYS; 1995191665Sbms } 1996191665Sbms 1997191665Sbms sg = stackgap_init(); 1998191665Sbms sup = stackgap_alloc(&sg, sasize); 1999191665Sbms flen = (int *) stackgap_alloc(&sg, sizeof(*flen)); 2000191665Sbms 2001191665Sbms fl = sasize; 2002191665Sbms if ((error = copyout(&fl, flen, sizeof(fl))) != 0) 2003199526Sbms return error; 2004199526Sbms 2005199527Sbms switch (st->s_cmd) { 2006199527Sbms case SVR4_TI_CONNECT_REQUEST: 2007199527Sbms DPRINTF(("getmsg: TI_CONNECT_REQUEST\n")); 2008199528Sbms /* 2009199528Sbms * We do the connect in one step, so the putmsg should 2010191665Sbms * have gotten the error. 2011191665Sbms */ 2012191665Sbms sc.cmd = SVR4_TI_OK_REPLY; 2013191665Sbms sc.len = 0; 2014191665Sbms 2015191665Sbms ctl.len = 8; 2016191665Sbms dat.len = -1; 2017191665Sbms fl = 1; 2018191665Sbms st->s_cmd = sc.cmd; 2019191665Sbms break; 2020191665Sbms 2021191665Sbms case SVR4_TI_OK_REPLY: 2022191665Sbms DPRINTF(("getmsg: TI_OK_REPLY\n")); 2023191665Sbms /* 2024191665Sbms * We are immediately after a connect reply, so we send 2025191665Sbms * a connect verification. 2026199526Sbms */ 2027199526Sbms 2028199526Sbms SCARG(&ga, fdes) = SCARG(uap, fd); 2029199526Sbms SCARG(&ga, asa) = (void *) sup; 2030199526Sbms SCARG(&ga, alen) = flen; 2031199526Sbms 2032191665Sbms if ((error = getpeername(td, &ga)) != 0) { 2033191665Sbms DPRINTF(("getmsg: getpeername failed %d\n", error)); 2034191665Sbms return error; 2035191665Sbms } 2036191665Sbms 2037191665Sbms if ((error = copyin(sup, skp, sasize)) != 0) 2038191665Sbms return error; 2039191665Sbms 2040191665Sbms sc.cmd = SVR4_TI_CONNECT_REPLY; 2041191665Sbms sc.pad[0] = 0x4; 2042264364Sae sc.offs = 0x18; 2043264364Sae sc.pad[1] = 0x14; 2044191665Sbms sc.pad[2] = 0x04000402; 2045264364Sae 2046191665Sbms switch (st->s_family) { 2047191665Sbms case AF_INET: 2048191665Sbms sc.len = sasize; 2049191665Sbms sockaddr_to_netaddr_in(&sc, &sain); 2050264364Sae break; 2051191665Sbms 2052191665Sbms case AF_LOCAL: 2053264364Sae sc.len = sasize + 4; 2054264364Sae sockaddr_to_netaddr_un(&sc, &saun); 2055264364Sae break; 2056264364Sae 2057264364Sae default: 2058264364Sae return ENOSYS; 2059191665Sbms } 2060191665Sbms 2061191665Sbms ctl.len = 40; 2062191665Sbms dat.len = -1; 2063191665Sbms fl = 0; 2064191665Sbms st->s_cmd = sc.cmd; 2065191665Sbms break; 2066191665Sbms 2067191665Sbms case SVR4_TI__ACCEPT_OK: 2068191665Sbms DPRINTF(("getmsg: TI__ACCEPT_OK\n")); 2069191665Sbms /* 2070191665Sbms * We do the connect in one step, so the putmsg should 2071191665Sbms * have gotten the error. 2072191665Sbms */ 2073191665Sbms sc.cmd = SVR4_TI_OK_REPLY; 2074191665Sbms sc.len = 1; 2075191665Sbms 2076191665Sbms ctl.len = 8; 2077191665Sbms dat.len = -1; 2078191665Sbms fl = 1; 2079191665Sbms st->s_cmd = SVR4_TI__ACCEPT_WAIT; 2080191665Sbms break; 2081191665Sbms 2082191665Sbms case SVR4_TI__ACCEPT_WAIT: 2083191665Sbms DPRINTF(("getmsg: TI__ACCEPT_WAIT\n")); 2084191665Sbms /* 2085191665Sbms * We are after a listen, so we try to accept... 2086191665Sbms */ 2087191665Sbms SCARG(&aa, s) = SCARG(uap, fd); 2088191665Sbms SCARG(&aa, name) = (void *) sup; 2089191665Sbms SCARG(&aa, anamelen) = flen; 2090191665Sbms 2091192923Sbms if ((error = accept(td, &aa)) != 0) { 2092191665Sbms DPRINTF(("getmsg: accept failed %d\n", error)); 2093191665Sbms return error; 2094191665Sbms } 2095191665Sbms 2096191665Sbms st->s_afd = *retval; 2097191665Sbms 2098191665Sbms DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd)); 2099192923Sbms 2100191665Sbms if ((error = copyin(sup, skp, sasize)) != 0) 2101191665Sbms return error; 2102191665Sbms 2103191665Sbms sc.cmd = SVR4_TI_ACCEPT_REPLY; 2104191665Sbms sc.offs = 0x18; 2105191665Sbms sc.pad[0] = 0x0; 2106191665Sbms 2107192923Sbms switch (st->s_family) { 2108191665Sbms case AF_INET: 2109191665Sbms sc.pad[1] = 0x28; 2110191665Sbms sockaddr_to_netaddr_in(&sc, &sain); 2111191665Sbms ctl.len = 40; 2112191665Sbms sc.len = sasize; 2113191665Sbms break; 2114191665Sbms 2115191665Sbms case AF_LOCAL: 2116191665Sbms sc.pad[1] = 0x00010000; 2117192923Sbms sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */ 2118192923Sbms sc.pad[3] = 0x00010000; 2119192923Sbms ctl.len = 134; 2120192923Sbms sc.len = sasize + 4; 2121192923Sbms break; 2122192923Sbms 2123192923Sbms default: 2124191665Sbms return ENOSYS; 2125192923Sbms } 2126191665Sbms 2127191665Sbms dat.len = -1; 2128191665Sbms fl = 0; 2129191665Sbms st->s_cmd = SVR4_TI__ACCEPT_OK; 2130191665Sbms break; 2131191665Sbms 2132191665Sbms case SVR4_TI_SENDTO_REQUEST: 2133192923Sbms DPRINTF(("getmsg: TI_SENDTO_REQUEST\n")); 2134192923Sbms if (ctl.maxlen > 36 && ctl.len < 36) 2135192923Sbms ctl.len = 36; 2136192923Sbms 2137191665Sbms if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) 2138191665Sbms return error; 2139191665Sbms 2140191665Sbms switch (st->s_family) { 2141191665Sbms case AF_INET: 2142191665Sbms sockaddr_to_netaddr_in(&sc, &sain); 2143191665Sbms break; 2144191665Sbms 2145191665Sbms case AF_LOCAL: 2146191665Sbms sockaddr_to_netaddr_un(&sc, &saun); 2147191665Sbms break; 2148191665Sbms 2149191665Sbms default: 2150191665Sbms return ENOSYS; 2151191665Sbms } 2152191665Sbms 2153191665Sbms msg.msg_name = (caddr_t) sup; 2154191665Sbms msg.msg_namelen = sasize; 2155191665Sbms msg.msg_iov = &aiov; 2156191665Sbms msg.msg_iovlen = 1; 2157191665Sbms msg.msg_control = 0; 2158191665Sbms aiov.iov_base = dat.buf; 2159192923Sbms aiov.iov_len = dat.maxlen; 2160192923Sbms msg.msg_flags = 0; 2161192923Sbms 2162192923Sbms error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen); 2163192923Sbms 2164192923Sbms if (error) { 2165192923Sbms DPRINTF(("getmsg: recvit failed %d\n", error)); 2166192923Sbms return error; 2167191665Sbms } 2168192923Sbms 2169192923Sbms if ((error = copyin(msg.msg_name, skp, sasize)) != 0) 2170192923Sbms return error; 2171191665Sbms 2172191665Sbms sc.cmd = SVR4_TI_RECVFROM_IND; 2173191665Sbms 2174191665Sbms switch (st->s_family) { 2175191665Sbms case AF_INET: 2176191665Sbms sc.len = sasize; 2177191665Sbms sockaddr_to_netaddr_in(&sc, &sain); 2178191665Sbms break; 2179191665Sbms 2180191665Sbms case AF_LOCAL: 2181191665Sbms sc.len = sasize + 4; 2182191665Sbms sockaddr_to_netaddr_un(&sc, &saun); 2183191665Sbms break; 2184192923Sbms 2185192923Sbms default: 2186192923Sbms return ENOSYS; 2187192923Sbms } 2188192923Sbms 2189191672Sbms dat.len = *retval; 2190192923Sbms fl = 0; 2191259884Sbz st->s_cmd = sc.cmd; 2192192923Sbms break; 2193192923Sbms 2194192923Sbms default: 2195192923Sbms st->s_cmd = sc.cmd; 2196192923Sbms if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) { 2197192923Sbms struct read_args ra; 2198192923Sbms 2199192923Sbms /* More weirdness: Again, I can't find documentation 2200192923Sbms * to back this up, but when a process does a generic 2201192923Sbms * "getmsg()" call it seems that the command field is 2202195755Sbms * zero and the length of the data area is zero. I 2203195755Sbms * think processes expect getmsg() to fill in dat.len 2204195755Sbms * after reading at most dat.maxlen octets from the 2205195755Sbms * stream. Since we're using sockets I can let 2206192923Sbms * read() look after it and frob return values 2207192923Sbms * appropriately (or inappropriately :-) 2208192923Sbms * -- newton@atdot.dotat.org XXX 2209192923Sbms */ 2210192923Sbms SCARG(&ra, fd) = SCARG(uap, fd); 2211192923Sbms SCARG(&ra, buf) = dat.buf; 2212195755Sbms SCARG(&ra, nbyte) = dat.maxlen; 2213195755Sbms if ((error = read(td, &ra)) != 0) { 2214195755Sbms return error; 2215195755Sbms } 2216195755Sbms dat.len = *retval; 2217195755Sbms *retval = 0; 2218195755Sbms st->s_cmd = SVR4_TI_SENDTO_REQUEST; 2219195755Sbms break; 2220192923Sbms } 2221192923Sbms DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd)); 2222192923Sbms return EINVAL; 2223191672Sbms } 2224192923Sbms 2225192923Sbms if (SCARG(uap, ctl)) { 2226192923Sbms if (ctl.len != -1) 2227191672Sbms if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0) 2228191665Sbms return error; 2229191665Sbms 2230191665Sbms if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0) 2231191665Sbms return error; 2232191665Sbms } 2233191665Sbms 2234191665Sbms if (SCARG(uap, dat)) { 2235191665Sbms if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0) 2236191665Sbms return error; 2237191665Sbms } 2238191665Sbms 2239191665Sbms if (SCARG(uap, flags)) { /* XXX: Need translation */ 2240191665Sbms if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0) 2241191665Sbms return error; 2242191665Sbms } 2243191665Sbms 2244191665Sbms *retval = 0; 2245191665Sbms 2246191665Sbms#ifdef DEBUG_SVR4 2247191665Sbms show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl), 2248191665Sbms SCARG(uap, dat), fl); 2249191665Sbms#endif /* DEBUG_SVR4 */ 2250191665Sbms return error; 2251191665Sbms} 2252191665Sbms 2253191665Sbmsint svr4_sys_send(td, uap) 2254191665Sbms struct thread *td; 2255191665Sbms struct svr4_sys_send_args *uap; 2256191665Sbms{ 2257191665Sbms struct osend_args osa; 2258191665Sbms SCARG(&osa, s) = SCARG(uap, s); 2259191665Sbms SCARG(&osa, buf) = SCARG(uap, buf); 2260191665Sbms SCARG(&osa, len) = SCARG(uap, len); 2261191665Sbms SCARG(&osa, flags) = SCARG(uap, flags); 2262191665Sbms return osend(td, &osa); 2263191665Sbms} 2264191665Sbms 2265191665Sbmsint svr4_sys_recv(td, uap) 2266191665Sbms struct thread *td; 2267191665Sbms struct svr4_sys_recv_args *uap; 2268191665Sbms{ 2269191665Sbms struct orecv_args ora; 2270191665Sbms SCARG(&ora, s) = SCARG(uap, s); 2271191665Sbms SCARG(&ora, buf) = SCARG(uap, buf); 2272191665Sbms SCARG(&ora, len) = SCARG(uap, len); 2273191665Sbms SCARG(&ora, flags) = SCARG(uap, flags); 2274191665Sbms return orecv(td, &ora); 2275191665Sbms} 2276191665Sbms 2277191665Sbms/* 2278191665Sbms * XXX This isn't necessary, but it's handy for inserting debug code into 2279191665Sbms * sendto(). Let's leave it here for now... 2280191665Sbms */ 2281191665Sbmsint 2282191665Sbmssvr4_sys_sendto(td, uap) 2283191665Sbms struct thread *td; 2284191665Sbms struct svr4_sys_sendto_args *uap; 2285191665Sbms{ 2286191665Sbms struct sendto_args sa; 2287191665Sbms 2288191665Sbms SCARG(&sa, s) = SCARG(uap, s); 2289264364Sae SCARG(&sa, buf) = SCARG(uap, buf); 2290191665Sbms SCARG(&sa, len) = SCARG(uap, len); 2291191665Sbms SCARG(&sa, flags) = SCARG(uap, flags); 2292264364Sae SCARG(&sa, to) = (caddr_t)SCARG(uap, to); 2293264364Sae SCARG(&sa, tolen) = SCARG(uap, tolen); 2294264364Sae 2295264364Sae DPRINTF(("calling sendto()\n")); 2296264364Sae return sendto(td, &sa); 2297264364Sae} 2298191665Sbms 2299191665Sbms