ibcs2_socksys.c revision 3584
118334Speter/*- 272564Sobrien * Copyright (c) 1994 Mostyn Lewis 390091Sobrien * All rights reserved. 418334Speter * 590091Sobrien * This software is based on code which is: 618334Speter * Copyright (c) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk) 790091Sobrien * 890091Sobrien * Redistribution and use in source and binary forms, with or without 990091Sobrien * modification, are permitted provided that the following conditions 1090091Sobrien * are met: 1118334Speter * 1. Redistributions of source code must retain the above copyright 1290091Sobrien * notice, this list of conditions and the following disclaimer 1390091Sobrien * in this position and unchanged. 1490091Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1590091Sobrien * notice, this list of conditions and the following disclaimer in the 1618334Speter * documentation and/or other materials provided with the distribution. 1718334Speter * 3. The name of the author may not be used to endorse or promote products 1890091Sobrien * derived from this software withough specific prior written permission 1990091Sobrien * 2090091Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2118334Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2218334Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2318334Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2418334Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2518334Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2618334Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2718334Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2818334Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2918334Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3018334Speter * 3118334Speter * $Id: ibcs2_socksys.c,v 1.2 1994/10/13 23:10:58 sos Exp $ 3218334Speter */ 3318334Speter 3418334Speter#include <sys/param.h> 3518334Speter#include <sys/systm.h> 3618334Speter#include <sys/filedesc.h> 3718334Speter#include <sys/file.h> 3818334Speter#include <sys/kernel.h> 3918334Speter#include <sys/mbuf.h> 4018334Speter#include <sys/protosw.h> 4118334Speter#include <sys/socket.h> 4252268Sobrien#include <sys/socketvar.h> 4318334Speter#include <sys/ioctl.h> 4418334Speter#include <sys/sockio.h> 4518334Speter#include <sys/proc.h> 4652268Sobrien#include <sys/exec.h> 4718334Speter#include <sys/stat.h> 4818334Speter#include <sys/syscall.h> 4990091Sobrien#include <sys/sysent.h> 5018334Speter#include <sys/malloc.h> 5118334Speter#include <sys/un.h> 5218334Speter#include <net/if.h> 5318334Speter#include <net/if_arp.h> 5418334Speter#include <net/route.h> 5518334Speter#include <netinet/in.h> 5618334Speter#include <vm/vm.h> 5752268Sobrien#include <i386/ibcs2/ibcs2.h> 5852518Sobrien#include <i386/ibcs2/ibcs2_socksys.h> 5990091Sobrien 6090091Sobrien/* Socksys pseudo driver entry points */ 6190091Sobrien 62107605Sobrienint sockopen (dev_t dev, int mode, int devtype, struct proc *p); 6318334Speterint sockioctl(dev_t dev, int cmd, caddr_t arg, int fflag, struct proc *p); 6452268Sobrienint sockclose(dev_t dev, int flag, int mode, struct proc *p); 6552268Sobrien 6652268Sobrien/* Socksys internal functions */ 6752268Sobrien 6852518Sobrienstatic void put_socket_fops(struct proc *p, int fd); 6952518Sobrienstatic int ss_fop_close(struct file *fp, struct proc *p); 7052518Sobrienstatic int ss_fop_ioctl(struct file*fp, int cmd, caddr_t arg, struct proc *p); 7152518Sobrienstatic int ss_syscall(caddr_t arg, struct proc *p); 7218334Speter 7318334Speter/* 7418334Speter * This structure is setup on first usage. Its address is planted 7552268Sobrien * into a socket's file structure fileops pointer after a successful 7618334Speter * socket creation or accept. 7718334Speter */ 7818334Speterstatic struct fileops ss_socket_fops = { 7918334Speter NULL, /* normal socket read */ 8018334Speter NULL, /* normal socket write */ 8118334Speter NULL, /* socksys ioctl */ 8218334Speter NULL, /* normal socket select */ 8318334Speter NULL, /* socksys close */ 8418334Speter}; 8518334Speter 8618334Speterstatic int (*close_s)__P((struct file *fp, struct proc *p)); 8718334Speterstatic int (*ioctl_s)__P((struct file *fp, int cmd, caddr_t data, struct proc *p)); 8818334Speter 8918334Speterint ss_debug = 1; 9018334Speter 9118334Speterstatic int 9218334Speterss_syscall(arg, p) 9318334Speter caddr_t arg; 9418334Speter struct proc *p; 9518334Speter{ 9618334Speter int cmd; 9718334Speter int error; 9818334Speter int retval[2]; 9918334Speter 10052518Sobrien retval[0] = retval[1] = 0; 10152518Sobrien cmd = ((struct ss_call *)arg)->arg[0]; 10252518Sobrien 10390091Sobrien#ifdef SS_DEBUG 10452518Sobrien if(ss_debug) { 10518334Speter static char *ss_syscall_strings[] = { 10690091Sobrien "0?", "accept", "bind", "connect", "getpeername", 10790091Sobrien "getsockname", "getsockopt", "listen", "recv(from)", 10890091Sobrien "recvfrom", "send(to)", "sendto", "setsockopt", "shutdown", 10990091Sobrien "socket", "select", "getipdomain", "setipdomain", 11090091Sobrien "adjtime", "setreuid", "setregid", "gettimeofday", 11152518Sobrien "settimeofday", "getitimer", "setitimer", 11252518Sobrien }; 11390091Sobrien 11452518Sobrien printf("ss_syscall: [%d] ",p->p_pid); 11552518Sobrien if(cmd < 0 || (cmd > CMD_SO_SETITIMER && cmd != CMD_SO_SS_DEBUG) ) 11652518Sobrien printf("? "); 11752518Sobrien else { 11852518Sobrien if(cmd == CMD_SO_SS_DEBUG) 11952518Sobrien printf("%s ","ss_debug"); 12052518Sobrien else 12190091Sobrien printf("%s ",ss_syscall_strings[cmd]); 12290091Sobrien } 12390091Sobrien printf("(%d) <0x%x,0x%x,0x%x,0x%x,0x%x,0x%x>\n", 12490091Sobrien cmd, 12590091Sobrien ((struct ss_call *)arg)->arg[1], 12652518Sobrien ((struct ss_call *)arg)->arg[2], 12796283Sobrien ((struct ss_call *)arg)->arg[3], 12896283Sobrien ((struct ss_call *)arg)->arg[4], 12996283Sobrien ((struct ss_call *)arg)->arg[5], 13090091Sobrien ((struct ss_call *)arg)->arg[6]); 13190091Sobrien } 13290091Sobrien#endif /* SS_DEBUG */ 13390091Sobrien 13490091Sobrien error = 0; 13590091Sobrien 13690091Sobrien switch (cmd) { 13790091Sobrien 13852518Sobrien case CMD_SO_SS_DEBUG: 13990091Sobrien 14090091Sobrien ss_debug = ((struct ss_call *)arg)->arg[1]; 14190091Sobrien break; 14290091Sobrien 14390091Sobrien case CMD_SO_SOCKET: { /* NO CONV */ 14490091Sobrien 14552268Sobrien#ifdef SS_DEBUG 14618334Speter if(ss_debug > 1) 14718334Speter printf("SO_SOCKET af in %d\n", 14818334Speter ((struct ss_call *)arg)->arg[1]); 14990091Sobrien#endif /* SS_DEBUG */ 15090091Sobrien ((struct ss_call *)arg)->arg[1] = ss_convert( 15118334Speter af_whatevers, 15290091Sobrien &(((struct ss_call *)arg)->arg[1]), 15390091Sobrien 0); 15490091Sobrien#ifdef SS_DEBUG 15518334Speter if(ss_debug > 1) { 15690091Sobrien printf("SO_SOCKET af out %d\n", 15718334Speter ((struct ss_call *)arg)->arg[1]); 15890091Sobrien 15918334Speter printf("SO_SOCKET type in %d\n", 16018334Speter ((struct ss_call *)arg)->arg[2]); 16118334Speter } 16218334Speter#endif /* SS_DEBUG */ 16318334Speter ((struct ss_call *)arg)->arg[2] = ss_convert( 16418334Speter type_whatevers, 16518334Speter &(((struct ss_call *)arg)->arg[2]), 16618334Speter 0); 16718334Speter#ifdef SS_DEBUG 16818334Speter if(ss_debug > 1) 16918334Speter printf("SO_SOCKET type out %d\n", 17018334Speter ((struct ss_call *)arg)->arg[2]); 17118334Speter#endif /* SS_DEBUG */ 17218334Speter 17318334Speter SYSCALL(SYS_socket, 0, 0); 17418334Speter 17518334Speter#ifdef SS_DEBUG 17618334Speter if(ss_debug) 17718334Speter printf("ss_syscall: [%d] socket fd=%d\n", 17818334Speter p->p_pid, retval[0]); 17918334Speter#endif /* SS_DEBUG */ 18018334Speter put_socket_fops(p,retval[0]); 18118334Speter 18252268Sobrien break; 18318334Speter } 18418334Speter 18518334Speter case CMD_SO_ACCEPT: { /* CONVERSION in arg 2 */ 18618334Speter 18790091Sobrien SYSCALL(SYS_accept, 2, SS_STRUCT_SOCKADDR); 18890091Sobrien 18918334Speter#ifdef SS_DEBUG 19052268Sobrien if(ss_debug) 19190091Sobrien printf("ss_syscall: [%d] accept fd=%d\n", 19290091Sobrien p->p_pid, retval[0]); 19390091Sobrien#endif /* SS_DEBUG */ 19490091Sobrien put_socket_fops(p,retval[0]); 19590091Sobrien 19618334Speter break; 19718334Speter } 19818334Speter 19918334Speter case CMD_SO_BIND: 20018334Speter SYSCALL(SYS_bind, 2, SS_STRUCT_SOCKADDR); 20118334Speter break; 20218334Speter 20318334Speter case CMD_SO_CONNECT: { 20418334Speter struct alien_sockaddr *sa; 20518334Speter unsigned short family; 20618334Speter 20718334Speter /* Remap any INADDR_ANY (0.0.0.0) to localhost */ 20852268Sobrien 20918334Speter sa = (struct alien_sockaddr *)((struct ss_call *)arg)->arg[1]; 21018334Speter if(error = copyin((caddr_t)&sa->sa_family, 21152268Sobrien (caddr_t)&family, sizeof(short))) 21218334Speter return(error); 21352268Sobrien if (family == AF_INET) { 21418334Speter unsigned long *addr; 21518334Speter unsigned long saddr; 21618334Speter 21718334Speter addr = &(((struct alien_sockaddr_in *)sa)->sin_addr.s_addr); 21818334Speter if(error = copyin((caddr_t)addr, (caddr_t)&saddr, sizeof(long))) 21918334Speter return(error); 22018334Speter if (saddr == INADDR_ANY) { 22118334Speter /* 0x0100007f is 127.0.0.1 reversed */ 22218334Speter saddr = 0x0100007f; 22318334Speter if(error = copyout((caddr_t)&saddr, 22418334Speter (caddr_t)addr, sizeof(long))) 22590091Sobrien return(error); 22690091Sobrien#ifdef SS_DEBUG 22790091Sobrien if (ss_debug) 22852518Sobrien printf("ss_syscall: remapped INADDR_ANY to localhost\n"); 22952518Sobrien#endif /* SS_DEBUG */ 23052518Sobrien } 23152518Sobrien } 23252518Sobrien SYSCALL(SYS_connect, 2, SS_STRUCT_SOCKADDR); 23352518Sobrien break; 23418334Speter } 23518334Speter 23690091Sobrien case CMD_SO_GETPEERNAME: 23790091Sobrien SYSCALL(SYS_getpeername, 2, SS_STRUCT_SOCKADDR); 23890091Sobrien break; 23990091Sobrien 24090091Sobrien case CMD_SO_GETSOCKNAME: 24190091Sobrien SYSCALL(SYS_getsockname, 2, SS_STRUCT_SOCKADDR); 24290091Sobrien break; 24390091Sobrien 24490091Sobrien case CMD_SO_GETSOCKOPT: 24590091Sobrien if(error = ss_getsockopt((caddr_t)(((int *)arg) + 1),retval,p)) 24696283Sobrien return(error); 24790091Sobrien break; 24818334Speter 24990091Sobrien case CMD_SO_LISTEN: 25090091Sobrien SYSCALL(SYS_listen, 0, 0); 25196283Sobrien break; 25290091Sobrien 25390091Sobrien case CMD_SO_RECV: 25496283Sobrien ((struct ss_call *)arg)->arg[5] = (int)((struct sockaddr *)NULL); 25590091Sobrien ((struct ss_call *)arg)->arg[6] = 0; 25696283Sobrien SYSCALL(SYS_recvfrom, 0, 0); 25790091Sobrien break; 25896283Sobrien 25996283Sobrien case CMD_SO_RECVFROM: 26096283Sobrien SYSCALL(SYS_recvfrom, 5, SS_STRUCT_SOCKADDR); 26196283Sobrien break; 26290091Sobrien 26390091Sobrien case CMD_SO_SEND: 26490091Sobrien ((struct ss_call *)arg)->arg[5] = (int)((struct sockaddr *)NULL); 26590091Sobrien ((struct ss_call *)arg)->arg[6] = 0; 26690091Sobrien SYSCALL(SYS_sendto, 0, 0); 26790091Sobrien break; 26890091Sobrien 26990091Sobrien case CMD_SO_SENDTO: 27090091Sobrien SYSCALL(SYS_sendto, 5, SS_STRUCT_SOCKADDR); 27190091Sobrien break; 27252268Sobrien 27390091Sobrien case CMD_SO_SETSOCKOPT: 27490091Sobrien if(error = ss_setsockopt((caddr_t)(((int *)arg) + 1),retval,p)) 27552268Sobrien return(error); 27690091Sobrien 27790091Sobrien case CMD_SO_SHUTDOWN: 27890091Sobrien SYSCALL(SYS_shutdown, 0, 0); 27990091Sobrien break; 28090091Sobrien 28190091Sobrien case CMD_SO_GETIPDOMAIN: 28290091Sobrien SYSCALL(SYS_getdomainname, 0, 0); 28390091Sobrien break; 28490091Sobrien 28590091Sobrien case CMD_SO_SETIPDOMAIN: /* Note check on BSD utsname no change? */ 28690091Sobrien SYSCALL(SYS_setdomainname, 0, 0); 28790091Sobrien break; 28890091Sobrien 28990091Sobrien case CMD_SO_SETREUID: 29090091Sobrien SYSCALL(126/*SYS_setreuid*/, 0, 0); 29190091Sobrien break; 29252268Sobrien 29390091Sobrien case CMD_SO_SETREGID: 29490091Sobrien SYSCALL(127/*SYS_setregid*/, 0, 0); 29590091Sobrien break; 29690091Sobrien 29790091Sobrien case CMD_SO_GETTIME: 29890091Sobrien SYSCALL(SYS_gettimeofday, 0, 0); 29990091Sobrien break; 30090091Sobrien 30190091Sobrien case CMD_SO_SETTIME: 30290091Sobrien SYSCALL(SYS_settimeofday, 0, 0); 30390091Sobrien break; 30490091Sobrien 30590091Sobrien case CMD_SO_GETITIMER: 30690091Sobrien SYSCALL(SYS_getitimer, 0, 0); 30790091Sobrien break; 30890091Sobrien 30990091Sobrien case CMD_SO_SETITIMER: 31090091Sobrien SYSCALL(SYS_setitimer, 0, 0); 31190091Sobrien break; 31290091Sobrien 31318334Speter case CMD_SO_SELECT: 31418334Speter SYSCALL(SYS_select, 0, 0); 31590091Sobrien break; 31618334Speter 31718334Speter case CMD_SO_ADJTIME: 31818334Speter SYSCALL(SYS_adjtime, 0, 0); 31918334Speter break; 32018334Speter 32118334Speter default: 32218334Speter printf("ss_syscall: default 0x%x\n",cmd); 32318334Speter return (EINVAL); 32418334Speter } 32552268Sobrien IBCS2_MAGIC_RETURN; 32690091Sobrien} 32718334Speter 32818334Speter 32952268Sobrienstatic int 33018334Speterss_fop_ioctl(fp, cmd, arg, p) 33118334Speter struct file *fp; 33218334Speter int cmd; 33318334Speter caddr_t arg; 33490091Sobrien struct proc *p; 33590091Sobrien{ 33690091Sobrien int error; 33790091Sobrien int retval[2]; 33818334Speter 33918334Speter#ifdef SS_DEBUG 34018334Speter if(ss_debug) { 34118334Speter static char **ioctl_strings; 34218334Speter int fd; 34390091Sobrien struct filedesc *fdp; 34418334Speter unsigned int ioctl_type; 34590091Sobrien unsigned int ioctl_len; 34690091Sobrien char cmd_type; 34790091Sobrien int cmd_ordinal; 34890091Sobrien 34990091Sobrien static char *ioctl_type_strings[] = { 35090091Sobrien "0?", "SS_IO", "SS_IOR", "3?", "SS_IOW", "5?", "SS_IOWR" 35190091Sobrien }; 35290091Sobrien static char *ioctl_S_strings[] = { 35390091Sobrien "0?", "SIOCSHIWAT", "SIOCGHIWAT", "SIOCSLOWAT", "SIOCGLOWAT", 35490091Sobrien "SIOCATMARK", "SIOCSPGRP", "SIOCGPGRP", "FIONREAD", 35590091Sobrien "FIONBIO", "FIOASYNC", "SIOCPROTO", "SIOCGETNAME", 35690091Sobrien "SIOCGETPEER", "IF_UNITSEL", "SIOCXPROTO" 35790091Sobrien }; 35890091Sobrien static char *ioctl_R_strings[] = { 35990091Sobrien "0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?", 36090091Sobrien "SIOCADDRT", "SIOCDELRT" 36118334Speter }; 36218334Speter static char *ioctl_I_strings[] = { 36318334Speter "0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?", 36490091Sobrien "9?", "10?", "SIOCSIFADDR", "SIOCGIFADDR", "SIOCSIFDSTADDR", 36590091Sobrien "SIOCGIFDSTADDR", "SIOCSIFFLAGS", "SIOCGIFFLAGS", 36690091Sobrien "SIOCGIFCONF", "18?", "19?", "20?", "SIOCSIFMTU", 36790091Sobrien "SIOCGIFMTU", "23?", "24?", "25?", "SIOCIFDETACH", 36818334Speter "SIOCGENPSTATS", "28?", "SIOCX25XMT", "SS_SIOCX25RCV", 36918334Speter "SS_SIOCX25TBL", "SIOCGIFBRDADDR" ,"SIOCSIFBRDADDR", 37018334Speter "SIOCGIFNETMASK", "SIOCSIFNETMASK", "SIOCGIFMETRIC", 37118334Speter "SIOCSIFMETRIC", "SIOCSARP", "SIOCGARP", "SIOCDARP", 37218334Speter "SIOCSIFNAME", "SIOCGIFONEP", "SIOCSIFONEP ", 37318334Speter "44?", "45?", "46?", "47?", "48?", "49?", "50?", "51?", 37418334Speter "52?", "53?", "54?", "55?", "56?", "57?", "58?", "59?", 37518334Speter "60?", "61?", "62?", "63?", "64?", "SIOCGENADDR", 37618334Speter "SIOCSOCKSYS" 37718334Speter }; 37818334Speter 37918334Speter cmd_type = (cmd >> 8) & 0xff; 38018334Speter cmd_ordinal = cmd & 0xff; 38190091Sobrien 38218334Speter switch (cmd_type) { 38318334Speter 38452268Sobrien case 'S': 38518334Speter ioctl_strings = ioctl_S_strings; 38690091Sobrien if (cmd_ordinal > 15) 38790091Sobrien cmd_ordinal = -1; 38818334Speter break; 38918334Speter 39018334Speter case 'R': 39118334Speter ioctl_strings = ioctl_R_strings; 39218334Speter if (cmd_ordinal > 10) 39318334Speter cmd_ordinal = -1; 39490091Sobrien break; 39590091Sobrien 39618334Speter case 'I': 39796283Sobrien ioctl_strings = ioctl_I_strings; 39896283Sobrien if (cmd_ordinal > 66) 39996283Sobrien cmd_ordinal = -1; 40096283Sobrien break; 40196283Sobrien 40296283Sobrien default: 40396283Sobrien cmd_type = '?'; 40496283Sobrien break; 40596283Sobrien } 40696283Sobrien fdp = p->p_fd; 40796283Sobrien fd = -1; 40896283Sobrien while(++fd < NOFILE) 40996283Sobrien if ( fp == fdp->fd_ofiles[fd] ) 41096283Sobrien break; 41118334Speter 41296283Sobrien ioctl_type = (0xe0000000 & cmd) >> 29; 41396283Sobrien ioctl_len = (cmd >> 16) & SS_IOCPARM_MASK; 41496283Sobrien 41596283Sobrien printf("ss_fop_ioctl: [%d] fd=%d ",p->p_pid, fd); 41696283Sobrien if(cmd_type != '?'){ 41796283Sobrien if(cmd_ordinal != -1) 41896283Sobrien printf("%s %s('%c',%d,l=%d) ",ioctl_strings[cmd_ordinal], 41996283Sobrien ioctl_type_strings[ioctl_type], 42096283Sobrien cmd_type, 42190091Sobrien cmd_ordinal, 42218334Speter ioctl_len); 42318334Speter else { 42418334Speter cmd_ordinal = cmd & 0xff; 42518334Speter printf("[unknown ordinal %d] %s('%c',%d,l=%d) ",cmd_ordinal, 42690091Sobrien ioctl_type_strings[ioctl_type], 42718334Speter cmd_type, 42818334Speter cmd_ordinal, 42990091Sobrien ioctl_len); 43090091Sobrien } 43118334Speter } 43218334Speter else { 43318334Speter printf("? %s('%c',%d,l=%d) ", 43490091Sobrien ioctl_type_strings[ioctl_type], 43590091Sobrien cmd_type, 43690091Sobrien cmd_ordinal, 43790091Sobrien ioctl_len); 43890091Sobrien } 43990091Sobrien 44090091Sobrien printf("0x%x (0x%x) <0x%x>\n", 44190091Sobrien fp, cmd, arg); 44290091Sobrien } 44390091Sobrien#endif /* SS_DEBUG */ 44490091Sobrien 44590091Sobrien /* No dogs allowed */ 44690091Sobrien 44790091Sobrien if(*(((int *)arg) - 3) != IBCS2_MAGIC_IN){ 44890091Sobrien printf("ss_fop_ioctl: bad magic (sys_generic.c has no socksys mods?)\n"); 44990091Sobrien return(EINVAL); 45090091Sobrien } 45190091Sobrien 45290091Sobrien if(fp->f_type != DTYPE_SOCKET) 45390091Sobrien return (ENOTSOCK); 45490091Sobrien 45590091Sobrien retval[0] = retval[1] = 0; 45690091Sobrien 45790091Sobrien 45890091Sobrien error = 0; 45990091Sobrien 46090091Sobrien switch (cmd) { 46190091Sobrien case SS_SIOCSHIWAT: /* set high watermark */ 46290091Sobrien case SS_SIOCSLOWAT: /* set low watermark */ 46390091Sobrien break; /* return value of 0 and no error */ 46490091Sobrien 46590091Sobrien case SS_SIOCGHIWAT: /* get high watermark */ 46690091Sobrien case SS_SIOCGLOWAT: /* get low watermark */ 46790091Sobrien break; /* return value of 0 and no error */ 46890091Sobrien 46990091Sobrien case SS_SIOCATMARK: /* at oob mark */ 47090091Sobrien IOCTL(SIOCATMARK); 47190091Sobrien break; 47290091Sobrien 47390091Sobrien case SS_SIOCSPGRP: /* set process group */ 47490091Sobrien IOCTL(SIOCSPGRP); 47590091Sobrien break; 47690091Sobrien case SS_SIOCGPGRP: /* get process group */ 47790091Sobrien IOCTL(SIOCGPGRP); 47890091Sobrien break; 47990091Sobrien 48090091Sobrien case FIONREAD: 48190091Sobrien case SS_FIONREAD: /* get # bytes to read */ 48290091Sobrien IOCTL(FIONREAD); 48390091Sobrien break; 48490091Sobrien 48590091Sobrien case SS_FIONBIO: /* set/clear non-blocking i/o */ 48690091Sobrien IOCTL(FIONBIO); 48790091Sobrien break; 48890091Sobrien 48990091Sobrien case SS_FIOASYNC: /* set/clear async i/o */ 49090091Sobrien IOCTL(FIOASYNC); 49190091Sobrien break; 49290091Sobrien 49390091Sobrien case SS_SIOCADDRT: /* add route - uses struct ortentry */ 49490091Sobrien IOCTL(SIOCADDRT); 49590091Sobrien break; 49690091Sobrien 49790091Sobrien case SS_SIOCDELRT: /* delete route - uses struct ortentry */ 49890091Sobrien IOCTL(SIOCDELRT); 49990091Sobrien break; 50018334Speter 50118334Speter case SS_SIOCSIFADDR: /* set ifnet address */ 50218334Speter IOCTL(SIOCSIFADDR); 50390091Sobrien break; 50490091Sobrien 50552518Sobrien case SS_SIOCGIFADDR: /* get ifnet address */ 50618334Speter IOCTL(SIOCGIFADDR); 50718334Speter break; 50852268Sobrien 50990091Sobrien case SS_SIOCSIFDSTADDR: /* set p-p address */ 51090091Sobrien IOCTL(SIOCSIFDSTADDR); 51118334Speter break; 51218334Speter 51390091Sobrien case SS_SIOCGIFDSTADDR: /* get p-p address */ 51418334Speter IOCTL(SIOCGIFDSTADDR); 51590091Sobrien break; 51618334Speter 51718334Speter case SS_SIOCSIFFLAGS: /* set ifnet flags */ 51818334Speter IOCTL(SIOCSIFFLAGS); 51990091Sobrien break; 52090091Sobrien 52190091Sobrien case SS_SIOCGIFFLAGS: /* get ifnet flags */ 52290091Sobrien IOCTL(SIOCGIFFLAGS); 52390091Sobrien break; 52490091Sobrien 52590091Sobrien case SS_SIOCGIFCONF: /* get ifnet ltst */ 52690091Sobrien IOCTL(SIOCGIFCONF); 52790091Sobrien break; 52818334Speter 52918334Speter case SS_SIOCGIFBRDADDR: /* get broadcast addr */ 53090091Sobrien IOCTL(SIOCGIFBRDADDR); 53118334Speter break; 53218334Speter 53318334Speter case SS_SIOCSIFBRDADDR: /* set broadcast addr */ 53418334Speter IOCTL(SIOCSIFBRDADDR); 53518334Speter break; 53690091Sobrien 53718334Speter case SS_SIOCGIFNETMASK: /* get net addr mask */ 53890091Sobrien IOCTL(SIOCGIFNETMASK); 53990091Sobrien break; 54090091Sobrien 54190091Sobrien case SS_SIOCSIFNETMASK: /* set net addr mask */ 54218334Speter IOCTL(SIOCSIFNETMASK); 54352268Sobrien break; 54418334Speter 54590091Sobrien case SS_SIOCGIFMETRIC: /* get IF metric */ 54618334Speter IOCTL(SIOCGIFMETRIC); 54790091Sobrien break; 54818334Speter 54918334Speter case SS_SIOCSIFMETRIC: /* set IF metric */ 55090091Sobrien IOCTL(SIOCSIFMETRIC); 55118334Speter break; 55218334Speter 55318334Speter/* FreeBSD 2.0 does not have socket ARPs */ 55452518Sobrien 55552518Sobrien#ifdef SIOCSARP 55618334Speter 55752518Sobrien case SS_SIOCSARP: /* set arp entry */ 55890091Sobrien IOCTL(SIOCSARP); 55990091Sobrien break; 56052518Sobrien 56152518Sobrien case SS_SIOCGARP: /* get arp entry */ 56252518Sobrien IOCTL(SIOCGARP); 56352518Sobrien break; 56452518Sobrien 56552518Sobrien case SS_SIOCDARP: /* delete arp entry */ 56652518Sobrien IOCTL(SIOCDARP); 56752518Sobrien break; 56818334Speter 56918334Speter#else /* SIOCSARP */ 57018334Speter 57118334Speter case SS_SIOCSARP: /* set arp entry */ 57218334Speter return(EINVAL); 57318334Speter 57418334Speter case SS_SIOCGARP: /* get arp entry */ 57518334Speter return(EINVAL); 57618334Speter 57752518Sobrien case SS_SIOCDARP: /* delete arp entry */ 57890091Sobrien return(EINVAL); 57952518Sobrien 58052518Sobrien#endif /* SIOCSARP */ 58190091Sobrien 58290091Sobrien case SS_SIOCGENADDR: /* Get ethernet addr XXX */ 58390091Sobrien return (EINVAL); 58490091Sobrien/* return (error = ioctl_s(fp, SIOCGIFHWADDR, arg, p)); */ 58590091Sobrien 58690091Sobrien case SS_SIOCSIFMTU: /* get if_mtu */ 58790091Sobrien IOCTL(SIOCSIFMTU); 58890091Sobrien break; 58990091Sobrien 59090091Sobrien case SS_SIOCGIFMTU: /* set if_mtu */ 59190091Sobrien IOCTL(SIOCGIFMTU); 59290091Sobrien break; 59390091Sobrien 59418334Speter case SS_SIOCGETNAME: /* getsockname XXX */ 59518334Speter return (EINVAL); 59618334Speter/* return (ioctl_s(fp, SIOCGIFNAME, arg, p)); MMM */ 59718334Speter 59818334Speter case SS_SIOCGETPEER: { /* getpeername */ 59918334Speter struct moose { 60090091Sobrien int fd; 60118334Speter caddr_t asa; 60290091Sobrien int *alen; 60318334Speter int compat_43; 60418334Speter } args; 60518334Speter 60618334Speter struct alien_sockaddr uaddr; 60718334Speter struct sockaddr nuaddr; 60818334Speter int nuaddr_len = sizeof(struct sockaddr); 60918334Speter struct filedesc *fdp; 61018334Speter 61118334Speter if(fp->f_type != DTYPE_SOCKET) 61290091Sobrien return (ENOTSOCK); 61318334Speter 61418334Speter bzero((caddr_t)&nuaddr, sizeof(struct sockaddr)); 61518334Speter fdp = p->p_fd; 61618334Speter args.fd = -1; 61718334Speter while(++args.fd < NOFILE) 61890091Sobrien if ( fp == fdp->fd_ofiles[args.fd] ) 61918334Speter break; 62018334Speter if(args.fd == NOFILE){ 62190091Sobrien printf("ss_fop_ioctl: [%d] SS_SIOCGETPEER args.fd > NOFILE\n", p->p_pid); 62218334Speter return(EBADF); 62318334Speter } 62452268Sobrien args.asa = (caddr_t)&nuaddr; 62518334Speter args.alen = &nuaddr_len; 62690091Sobrien args.compat_43 = 0; 62790091Sobrien error = SYSCALLX(SYS_getpeername, &args); 62818334Speter if(error) 62918334Speter return(error); 63018334Speter 63118334Speter bzero((caddr_t)&uaddr, sizeof(struct alien_sockaddr)); 63290091Sobrien uaddr.sa_family = (unsigned short)nuaddr.sa_family; 63390091Sobrien bcopy(&nuaddr.sa_data, &uaddr.sa_data, __ALIEN_SOCK_SIZE__ - sizeof(unsigned short)); 63418334Speter 63590091Sobrien error = copyout((caddr_t)&uaddr, (caddr_t)arg, sizeof(struct alien_sockaddr)); 63690091Sobrien return error; 63718334Speter } 63852268Sobrien 63918334Speter default: 64018334Speter printf("ss_fop_ioctl: [%d] %lx unknown ioctl 0x%x, 0x%lx\n", 64190091Sobrien p->p_pid, (unsigned long)fp, 64218334Speter cmd, (unsigned long)arg); 64318334Speter return (EINVAL); 64418334Speter } 64518334Speter IBCS2_MAGIC_RETURN; 64618334Speter} 64718334Speter 64818334Speterint 64918334Spetersockioctl(dev, cmd, arg, fflag, p) 65018334Speter dev_t dev; 65118334Speter int cmd; 65218334Speter caddr_t arg; 65318334Speter int fflag; 65452268Sobrien struct proc *p; 65552268Sobrien{ 65652268Sobrien int error; 65790091Sobrien int retval[2]; 65818334Speter 65952518Sobrien#ifdef SS_DEBUG 66052518Sobrien if(ss_debug) { 66190091Sobrien char cmd_type; 66252518Sobrien int cmd_ordinal; 66318334Speter static char **ioctl_strings; 66452268Sobrien unsigned int ioctl_type; 66518334Speter unsigned int ioctl_len; 66652518Sobrien 66718334Speter static char *ioctl_type_strings[] = { 66890091Sobrien "NIOCxx", "SS_IO", "SS_IOR", "3?", "SS_IOW", "5?", "SS_IOWR" 66918334Speter }; 670102794Skan static char *ioctl_S_strings[] = { 67118334Speter "0?", "SIOCSHIWAT", "SIOCGHIWAT", "SIOCSLOWAT", "SIOCGLOWAT", 67218334Speter "SIOCATMARK", "SIOCSPGRP", "SIOCGPGRP", "FIONREAD", 67318334Speter "FIONBIO", "FIOASYNC", "SIOCPROTO", "SIOCGETNAME", 67418334Speter "SIOCGETPEER", "IF_UNITSEL", "SIOCXPROTO" 67518334Speter }; 67618334Speter static char *ioctl_R_strings[] = { 67752518Sobrien "0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?", 67852518Sobrien "SIOCADDRT", "SIOCDELRT" 67990091Sobrien }; 68090091Sobrien static char *ioctl_I_strings[] = { 68152518Sobrien "0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?", 68252518Sobrien "9?", "10?", "SIOCSIFADDR", "SIOCGIFADDR", "SIOCSIFDSTADDR", 68352518Sobrien "SIOCGIFDSTADDR", "SIOCSIFFLAGS", "SIOCGIFFLAGS", 68490091Sobrien "SIOCGIFCONF", "18?", "19?", "20?", "SIOCSIFMTU", 68552518Sobrien "SIOCGIFMTU", "23?", "24?", "25?", "SIOCIFDETACH", 68652518Sobrien "SIOCGENPSTATS", "28?", "SIOCX25XMT", "SS_SIOCX25RCV", 68752518Sobrien "SS_SIOCX25TBL", "SIOCGIFBRDADDR" ,"SIOCSIFBRDADDR", 68852518Sobrien "SIOCGIFNETMASK", "SIOCSIFNETMASK", "SIOCGIFMETRIC", 68952518Sobrien "SIOCSIFMETRIC", "SIOCSARP", "SIOCGARP", "SIOCDARP", 69052518Sobrien "SIOCSIFNAME", "SIOCGIFONEP", "SIOCSIFONEP ", 69118334Speter "44?", "45?", "46?", "47?", "48?", "49?", "50?", "51?", 69252518Sobrien "52?", "53?", "54?", "55?", "56?", "57?", "58?", "59?", 69352518Sobrien "60?", "61?", "62?", "63?", "64?", "SIOCGENADDR", 69490091Sobrien "SIOCSOCKSYS" 69552518Sobrien }; 69652518Sobrien static char *ioctl_NIOC_strings[] = { 69752518Sobrien "0?", "NIOCNFSD", "NIOCOLDGETFH", "NIOCASYNCD", 69852518Sobrien "NIOCSETDOMNAM", "NIOCGETDOMNAM", "NIOCCLNTHAND", 69952518Sobrien "NIOCEXPORTFS", "NIOCGETFH", "NIOCLSTAT" 70052518Sobrien }; 70152518Sobrien 70252518Sobrien cmd_ordinal = cmd & 0xff; 70318334Speter cmd_type = (cmd >> 8) & 0xff; 70452518Sobrien switch (cmd_type) { 70518334Speter 70618334Speter case 0: 70718334Speter ioctl_strings = ioctl_NIOC_strings; 70818334Speter cmd_type = ' '; 70918334Speter if (cmd_ordinal > 9) 71018334Speter cmd_ordinal = -1; 71118334Speter break; 71290091Sobrien 71318334Speter case 'S': 71452518Sobrien ioctl_strings = ioctl_S_strings; 71552268Sobrien if (cmd_ordinal > 15) 71618334Speter cmd_ordinal = -1; 71718334Speter break; 71818334Speter 71990091Sobrien case 'R': 72018334Speter ioctl_strings = ioctl_R_strings; 72118334Speter if (cmd_ordinal > 10) 72218334Speter cmd_ordinal = -1; 72318334Speter break; 72452268Sobrien 72552268Sobrien case 'I': 72652268Sobrien ioctl_strings = ioctl_I_strings; 72752518Sobrien if (cmd_ordinal > 66) 72818334Speter cmd_ordinal = -1; 72918334Speter break; 73090091Sobrien 73118334Speter default: 73218334Speter cmd_type = '?'; 73318334Speter break; 73452268Sobrien 73552268Sobrien } 73618334Speter ioctl_type = (0xe0000000 & cmd) >> 29; 73718334Speter ioctl_len = (cmd >> 16) & SS_IOCPARM_MASK; 73818334Speter 73918334Speter printf("sockioctl: [%d] ",p->p_pid); 74018334Speter if(cmd_type != '?'){ 74118334Speter if(cmd_ordinal != -1) 74218334Speter printf("%s %s('%c',%d,l=%d) ",ioctl_strings[cmd_ordinal], 74318334Speter ioctl_type_strings[ioctl_type], 74490091Sobrien cmd_type, 74518334Speter cmd_ordinal, 74618334Speter ioctl_len); 74718334Speter else { 74852268Sobrien cmd_ordinal = cmd & 0xff; 74952268Sobrien printf("[unknown ordinal %d] %s('%c',%d,l=%d) ",cmd_ordinal, 75090091Sobrien ioctl_type_strings[ioctl_type], 75152268Sobrien cmd_type, 75252518Sobrien cmd_ordinal, 75352518Sobrien ioctl_len); 75452518Sobrien } 75552268Sobrien } 75652518Sobrien else { 75752518Sobrien printf("? %s('%c',%d,l=%d) ", 75852518Sobrien ioctl_type_strings[ioctl_type], 75952763Sobrien cmd_type, 76090091Sobrien cmd_ordinal, 76152518Sobrien ioctl_len); 76252763Sobrien } 76352763Sobrien 76452763Sobrien printf("0x%x (0x%x) <0x%x>\n", 76552518Sobrien dev, cmd, arg); 76652518Sobrien } 76752518Sobrien#endif /* SS_DEBUG */ 76852518Sobrien 76918334Speter if(*(((int *)arg) - 3) != IBCS2_MAGIC_IN){ 77018334Speter printf("sockioctl: bad magic (sys_generic.c has no socksys mods?)\n"); 77118334Speter return(EINVAL); 77218334Speter } 77318334Speter 77418334Speter switch (cmd) { 77518334Speter 77618334Speter case SS_SIOCSOCKSYS: /* ss syscall */ 77718334Speter return ss_syscall(arg, p); 77818334Speter 77918334Speter /* NIOCxx: These ioctls are really just integers 78018334Speter * (no other information to go on). 78152268Sobrien */ 78218334Speter 78318334Speter case NIOCSETDOMNAM: { 78418334Speter struct sgdomarg domargs; 78518334Speter 78618334Speter if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&domargs, sizeof(struct sgdomarg))) 78718334Speter return(error); 78818334Speter 78918334Speter arg = (caddr_t)&domargs; 79018334Speter SYSCALL_N(SYS_setdomainname, 0, 0); 79118334Speter break; 79218334Speter } 79318334Speter 79418334Speter case NIOCGETDOMNAM: { 79518334Speter struct sgdomarg domargs; 79618334Speter 79790091Sobrien if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&domargs, sizeof(struct sgdomarg))) 79890091Sobrien return(error); 79918334Speter 80018334Speter arg = (caddr_t)&domargs; 80118334Speter SYSCALL_N(SYS_getdomainname, 0, 0); 80218334Speter break; 80318334Speter } 80418334Speter 80552268Sobrien case NIOCLSTAT: { 80652268Sobrien struct lstatarg st; 80752268Sobrien 80852268Sobrien if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&st, sizeof(struct lstatarg))) 80952268Sobrien return(error); 81018334Speter 81118334Speter /* DO WE HAVE A FOREIGN LSTAT */ 81218334Speter/* return mumbo_lstat(st.fname, st.statb); */ 81318334Speter return (EINVAL); 81418334Speter } 81552268Sobrien 81690091Sobrien case NIOCNFSD: 817102794Skan case NIOCOLDGETFH: 818102794Skan case NIOCASYNCD: 819102794Skan case NIOCCLNTHAND: 820102794Skan case NIOCEXPORTFS: 82190091Sobrien case NIOCGETFH: 82290091Sobrien return (EINVAL); 82390091Sobrien 824102794Skan 825102794Skan case SS_IF_UNITSEL: /* set unit number */ 82690091Sobrien case SS_SIOCXPROTO: /* empty proto table */ 82790091Sobrien 82890091Sobrien case SS_SIOCIFDETACH: /* detach interface */ 82990091Sobrien case SS_SIOCGENPSTATS: /* get ENP stats */ 830107605Sobrien 831107605Sobrien case SS_SIOCSIFNAME: /* set interface name */ 832102794Skan case SS_SIOCGIFONEP: /* get one-packet params */ 833102794Skan case SS_SIOCSIFONEP: /* set one-packet params */ 83490091Sobrien 83590091Sobrien case SS_SIOCPROTO: /* link proto */ 836102794Skan case SS_SIOCX25XMT: 83718334Speter case SS_SIOCX25RCV: 83852518Sobrien case SS_SIOCX25TBL: 83952518Sobrien 84052518Sobrien printf("sockioctl: [%d] unsupported ioctl 0x%x , 0x%lx\n", 84152518Sobrien p->p_pid, 84252518Sobrien cmd, (unsigned long)arg); 84352518Sobrien return (EINVAL); 84452518Sobrien 84552518Sobrien default: 84652518Sobrien printf("sockioctl: [%d] unknown ioctl 0x%x , 0x%lx\n", 84752518Sobrien p->p_pid, 84852518Sobrien cmd, (unsigned long)arg); 84952518Sobrien return (EINVAL); 85052268Sobrien } 85196283Sobrien IBCS2_MAGIC_RETURN; 85296283Sobrien} 85396283Sobrien 85496283Sobrien 85552268Sobrienint sockopen(dev, mode, devtype, p) 85652268Sobrien dev_t dev; 85752268Sobrien int mode; 85852268Sobrien int devtype; 85952268Sobrien struct proc *p; 86018334Speter{ 86152268Sobrien 86296283Sobrien#ifdef SS_DEBUG 86396283Sobrien if(ss_debug) 86452268Sobrien printf("sockopen: [%d] 0x%x\n", p->p_pid, dev); 86552268Sobrien#endif /* SS_DEBUG */ 86690091Sobrien 86752268Sobrien /* minor = 0 is the socksys device itself. No special handling 86896283Sobrien * will be needed as it is controlled by the application 86996283Sobrien * via ioctls. 87090091Sobrien */ 87196283Sobrien if (minor(dev) == 0) 87290091Sobrien return 0; 87352268Sobrien 87496283Sobrien /* minor = 1 is the spx device. This is the client side of a 87596283Sobrien * streams pipe to the X server. Under SCO and friends 87696283Sobrien * the library code messes around setting the connection 87796283Sobrien * up itself. We do it ourselves - this means we don't 87896283Sobrien * need to worry about the implementation of the server 87996283Sobrien * side (/dev/X0R - which must exist but can be a link 88096283Sobrien * to /dev/null) nor do we need to actually implement 88196283Sobrien * getmsg/putmsg. 88296283Sobrien */ 88396283Sobrien{ /* SPX */ 88452268Sobrien int fd, error, args[3]; 88552268Sobrien int retval[2]; 88652268Sobrien#define SUN_LEN(su) \ 88752268Sobrien (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) + 1 88852268Sobrien struct sockaddr_un *Xaddr = (struct sockaddr_un *)UA_ALLOC(); 88990091Sobrien retval[0] = retval[1] = 0; 89090091Sobrien#ifdef SS_DEBUG 89190091Sobrien if(ss_debug) 89290091Sobrien printf("sockopen: SPX: [%d] opening\n", p->p_pid); 89390091Sobrien#endif /* SS_DEBUG */ 89452268Sobrien 89552268Sobrien /* Grab a socket. */ 89652268Sobrien#ifdef SS_DEBUG 89752268Sobrien if(ss_debug) 89852268Sobrien printf("sockopen: SPX: [%d] get a unix domain socket\n", 89952268Sobrien p->p_pid); 90090091Sobrien#endif /* SS_DEBUG */ 90190091Sobrien args[0] = AF_UNIX; 90252268Sobrien args[1] = SOCK_STREAM; 90396283Sobrien args[2] = 0; 90496283Sobrien error = SYSCALLX(SYS_socket, args); 90596283Sobrien if (error) 90696283Sobrien return error; 90796283Sobrien fd = retval[0]; 90896283Sobrien if(fd < 1) { 90996283Sobrien printf("sockopen: SPX: [%d] unexpected fd of %d\n", 91096283Sobrien p->p_pid, fd); 91196283Sobrien return(EOPNOTSUPP); /* MRL whatever */ 91296283Sobrien } 91396283Sobrien 91452518Sobrien /* Connect the socket to X. */ 91552268Sobrien#ifdef SS_DEBUG 91652268Sobrien if(ss_debug) 91752268Sobrien printf("sockopen: SPX: [%d] connect to /tmp/X11-unix/X0\n", 91852268Sobrien p->p_pid); 91952268Sobrien#endif /* SS_DEBUG */ 92052268Sobrien args[0] = fd; 92152268Sobrien Xaddr->sun_family = AF_UNIX; 92252268Sobrien copyout("/tmp/.X11-unix/X0", Xaddr->sun_path, 18); 92352268Sobrien Xaddr->sun_len = SUN_LEN(Xaddr); 92452268Sobrien args[1] = (int)Xaddr; 92552268Sobrien args[2] = sizeof(struct sockaddr_un); 92618334Speter error = SYSCALLX(SYS_connect, args); 92718334Speter if (error) { 92818334Speter (void)SYSCALLX(SYS_close, &fd); 92918334Speter return error; 93018334Speter } 93118334Speter 93218334Speter put_socket_fops(p,fd); 93318334Speter 93418334Speter return 0; 93518334Speter} /* SPX */ 93618334Speter} 93752268Sobrien 93818334Speter 93952518Sobrienint sockclose(dev, flag, mode, p) 94052518Sobrien dev_t dev; 94152518Sobrien int flag; 94252518Sobrien int mode; 94352518Sobrien struct proc *p; 94490091Sobrien{ 94590091Sobrien#ifdef SS_DEBUG 94652268Sobrien if(ss_debug) 94752268Sobrien printf("sockclose: [%d] 0x%x\n", p->p_pid, dev); 94852268Sobrien#endif /* SS_DEBUG */ 94952268Sobrien return(0); 95052268Sobrien} 95118334Speter 95218334Speterstatic 95318334Speterint ss_fop_close(struct file *fp, struct proc *p) 95452268Sobrien{ 95518334Speter 95618334Speter#ifdef SS_DEBUG 95718334Speterint fd; 95818334Speterstruct filedesc *fdp; 95918334Speter 96018334Speter if(ss_debug){ 96118334Speter fdp = p->p_fd; 96218334Speter fd = -1; 96318334Speter while(++fd < NOFILE) 96418334Speter if ( fp == fdp->fd_ofiles[fd] ) 96518334Speter break; 96618334Speter printf("ss_fop_close: [%d] fd=%d ", p->p_pid, fd); 96718334Speter } 96818334Speter#endif /* SS_DEBUG */ 96918334Speter 97018334Speter if(fp->f_type == DTYPE_SOCKET) { 97118334Speter#ifdef SS_DEBUG 97218334Speter if(ss_debug) 97318334Speter printf("is a socket\n"); 97418334Speter#endif /* SS_DEBUG */ 97518334Speter return(close_s(fp, p)); 97618334Speter } 97718334Speter else { 97818334Speter#ifdef SS_DEBUG 97918334Speter if(ss_debug) 98018334Speter printf("is not a socket\n"); 98118334Speter#endif /* SS_DEBUG */ 98218334Speter return(ENOTSOCK); 98318334Speter } 98418334Speter} 98518334Speter 98618334Spetervoid put_socket_fops(struct proc *p, int fd) 98718334Speter{ 98818334Speterstruct filedesc *fdp; 98918334Speterstruct file *fp; 99018334Speter 99118334Speter fdp = p->p_fd; 99218334Speter fp = fdp->fd_ofiles[fd]; 99318334Speter if (ss_socket_fops.fo_ioctl != fp->f_ops->fo_ioctl) { 99418334Speter bcopy(fp->f_ops, &ss_socket_fops, sizeof(struct fileops)); 99518334Speter ioctl_s = ss_socket_fops.fo_ioctl; /* save standard ioctl */ 99618334Speter close_s = ss_socket_fops.fo_close; /* save standard close */ 99718334Speter ss_socket_fops.fo_ioctl = ss_fop_ioctl; 99818334Speter ss_socket_fops.fo_close = ss_fop_close; 99918334Speter } 100018334Speter fp->f_ops = &ss_socket_fops; 100118334Speter 100218334Speter return; 100318334Speter} 100418334Speter 100518334Speterint ss_SYSCALL(n,convert_arg,indicator,arg,p,retval) 100618334Speter int n; /* syscall ordinal */ 100718334Speter int convert_arg; /* if not 0, argument to convert */ 100818334Speter int indicator; /* type of argument to convert */ 100952268Sobrien int *arg; /* address of alien arg */ 101018334Speter struct proc *p; 101152268Sobrien int *retval; 101252268Sobrien{ 101352268Sobrienint error; 101452268Sobrienint rc; 101552268Sobrien 101652268Sobrien if(convert_arg){ 101718334Speter if(rc = ss_convert_struct( (caddr_t)*(arg + convert_arg), 101818334Speter indicator, 101918334Speter SS_ALIEN_TO_NATIVE)) 102018334Speter return(rc); 102118334Speter 102218334Speter error = (*sysent[n].sy_call)(p, arg + 1, retval); 102318334Speter rc = ss_convert_struct( (caddr_t)*(arg + convert_arg), 102418334Speter indicator, 102590091Sobrien SS_NATIVE_TO_ALIEN); 102690091Sobrien#ifdef SS_DEBUG 102790091Sobrien if(ss_debug) 102890091Sobrien printf("ss_SYSCALL: [%d] error=%d, rc=%d\n", 102990091Sobrien p->p_pid, error, rc); 103090091Sobrien#endif /* SS_DEBUG */ 103190091Sobrien } 103290091Sobrien else { 103390091Sobrien rc = 0; 103418334Speter error = (*sysent[n].sy_call)(p, arg + 1, retval); 103518334Speter#ifdef SS_DEBUG 103690091Sobrien if(ss_debug) 103718334Speter printf("ss_SYSCALL: [%d] error=%d\n",p->p_pid, error); 103852268Sobrien#endif /* SS_DEBUG */ 103918334Speter } 104018334Speter 104118334Speter return(error ? error : rc); 104218334Speter} 104318334Speter 104490091Sobrienint ss_IOCTL(fp, cmd, arg, p) 104518334Speter struct file *fp; 104690091Sobrien int cmd; 104790091Sobrien int *arg; /* address of alien arg */ 104890091Sobrien struct proc *p; 104990091Sobrien{ 105090091Sobrienint error, rc; 105190091Sobrienint these[2]; 105290091Sobrienchar cmd_type; 105390091Sobrienint cmd_ordinal; 105490091Sobrienint indicator; 105590091Sobrien 105618334Speter cmd_type = (cmd >> 8) & 0xff; 105790091Sobrien cmd_ordinal = cmd & 0xff; 105890091Sobrien these[0] = cmd_type; 105990091Sobrien these[1] = cmd_ordinal; 106090091Sobrien#ifdef SS_DEBUG 106190091Sobrien if(ss_debug > 1) 106290091Sobrien printf("ss_IOCTL: calling ss_convert with %d(%c) %d\n", 106390091Sobrien these[0],these[0],these[1]); 106490091Sobrien#endif /* SS_DEBUG */ 106590091Sobrien indicator = ss_convert( struct_whatevers, these, 0); 106690091Sobrien#ifdef SS_DEBUG 106790091Sobrien if(ss_debug > 1) 106890091Sobrien printf("ss_IOCTL: ss_convert returns indicator %d\n",indicator); 106990091Sobrien#endif /* SS_DEBUG */ 107090091Sobrien if(indicator){ 107190091Sobrien error = ss_convert_struct((caddr_t)*(arg + 2), 107290091Sobrien indicator, 107390091Sobrien SS_ALIEN_TO_NATIVE); 107490091Sobrien#ifdef SS_DEBUG 107590091Sobrien if(ss_debug > 1) 107690091Sobrien printf("ss_IOCTL: ss_convert_struct returns %d\n",error); 107790091Sobrien#endif /* SS_DEBUG */ 107890091Sobrien if(error) 107990091Sobrien return(error); 108090091Sobrien /* change len in ioctl now - in the general case */ 108190091Sobrien error = ioctl_s(fp, cmd, (caddr_t)arg, p); 108290091Sobrien rc = ss_convert_struct( (caddr_t)*(arg + 2), 108318334Speter indicator, 108418334Speter SS_NATIVE_TO_ALIEN); 108518334Speter#ifdef SS_DEBUG 108618334Speter if(ss_debug) 108718334Speter printf("ss_IOCTL: [%d] error=%d, rc=%d\n",p->p_pid, 108852268Sobrien error, rc); 108918334Speter#endif /* SS_DEBUG */ 109052268Sobrien } 109118334Speter else { 109218334Speter rc = 0; 109318334Speter error = ioctl_s(fp, cmd, (caddr_t)arg, p); 109418334Speter#ifdef SS_DEBUG 109518334Speter if(ss_debug) 109618334Speter printf("ss_IOCTL: [%d] error=%d\n",p->p_pid, error); 109718334Speter#endif /* SS_DEBUG */ 109818334Speter } 109918334Speter 110018334Speter return(error ? error : rc); 110118334Speter} 110218334Speter 110318334Speter 110418334Speterstruct ss_socketopt_args { 110518334Speter int s; 110618334Speter int level; 110718334Speter int name; 110818334Speter caddr_t val; 110918334Speter int valsize; 111018334Speter}; 111118334Speter 111218334Speterint 111318334Speterss_setsockopt(arg, ret, p) 111418334Speter struct ss_socketopt_args *arg; 111518334Speter int *ret; 111652268Sobrien struct proc *p; 111752268Sobrien{ 111852268Sobrien int error, optname; 111952268Sobrien int retval[2]; 112052268Sobrien 112118334Speter if (arg->level != 0xffff) /* FreeBSD, SCO and ? */ 112218334Speter return (ENOPROTOOPT); 112318334Speter 112418334Speter optname = ss_convert(sopt_whatevers, &arg->name, 0); 112518334Speter 112618334Speter switch (optname) { 112718334Speter 112818334Speter case SO_ACCEPTCONN: 112918334Speter case SO_BROADCAST: 113018334Speter case SO_DEBUG: 113118334Speter case SO_DONTROUTE: 113218334Speter case SO_LINGER: 113318334Speter case SO_KEEPALIVE: 113418334Speter case SO_OOBINLINE: 113518334Speter case SO_RCVBUF: 113618334Speter case SO_RCVLOWAT: 113718334Speter case SO_RCVTIMEO: 113818334Speter case SO_REUSEADDR: 113918334Speter case SO_SNDBUF: 114018334Speter case SO_SNDLOWAT: 114118334Speter case SO_SNDTIMEO: 114218334Speter case SO_USELOOPBACK: 114318334Speter error = SYSCALLX(SYS_setsockopt, arg); 114418334Speter *ret = retval[0]; 114518334Speter *(ret + 1) = retval[1]; 114690091Sobrien return(error); 114718334Speter 114818334Speter case SO_ERROR: 114918334Speter case SO_IMASOCKET: 115018334Speter case SO_NO_CHECK: 115118334Speter case SO_ORDREL: 115218334Speter case SO_PRIORITY: 115318334Speter case SO_PROTOTYPE: 115418334Speter case SO_TYPE: 115518334Speter return (ENOPROTOOPT); 115618334Speter 115718334Speter } 115818334Speter 115918334Speter return (ENOPROTOOPT); 116018334Speter} 116118334Speter 116218334Speter 116318334Speterint 116418334Speterss_getsockopt(arg, ret, p) 116518334Speter struct ss_socketopt_args *arg; 116618334Speter int *ret; 116718334Speter struct proc *p; 116818334Speter{ 116918334Speter int error, optname; 117018334Speter int retval[2]; 117152268Sobrien 117252268Sobrien if (arg->level != 0xffff) /* FreeBSD, SCO and ? */ 117352268Sobrien return (ENOPROTOOPT); 117452268Sobrien 117552268Sobrien optname = ss_convert(sopt_whatevers, &arg->name, 0); 117618334Speter 117752268Sobrien switch (optname) { 117852268Sobrien 117952268Sobrien case SO_ACCEPTCONN: 118018334Speter case SO_BROADCAST: 118118334Speter case SO_DEBUG: 118218334Speter case SO_DONTROUTE: 118318334Speter case SO_ERROR: 118418334Speter case SO_KEEPALIVE: 118518334Speter case SO_LINGER: 118618334Speter case SO_OOBINLINE: 118718334Speter case SO_RCVBUF: 118818334Speter case SO_RCVLOWAT: 118918334Speter case SO_RCVTIMEO: 119018334Speter case SO_REUSEADDR: 119118334Speter case SO_SNDBUF: 119218334Speter case SO_SNDLOWAT: 119318334Speter case SO_SNDTIMEO: 119418334Speter case SO_TYPE: 119518334Speter case SO_USELOOPBACK: 119618334Speter error = SYSCALLX(SYS_getsockopt, arg); 119718334Speter *ret = retval[0]; 119818334Speter *(ret + 1) = retval[1]; 119918334Speter return(error); 120018334Speter 120118334Speter 120218334Speter case SO_PROTOTYPE: { 120318334Speter int value = 0; 120418334Speter 120518334Speter error = copyout((caddr_t)&value, (caddr_t)arg->s, sizeof(int)); 120618334Speter return(error); 120718334Speter } 120818334Speter 120918334Speter 121018334Speter case SO_IMASOCKET: { 121118334Speter int value = 1; 121218334Speter 121318334Speter error = copyout((caddr_t)&value, (caddr_t)arg->s, sizeof(int)); 121418334Speter return(error); 121518334Speter } 121618334Speter 121718334Speter case SO_NO_CHECK: 121818334Speter case SO_ORDREL: 121918334Speter case SO_PRIORITY: 122018334Speter return (ENOPROTOOPT); 122118334Speter } 122218334Speter 122318334Speter return (ENOPROTOOPT); 122418334Speter} 122518334Speter 122618334Speter#define SS_CONVERT 122718334Speterint system_type = SS_FREEBSD; /* FreeBSD */ 122818334Speter 122918334Speterint 123018334Speterss_convert(what, this, otherwise) 123118334Speter struct whatever **what; 123218334Speter int *this; 123318334Speter int otherwise; 123418334Speter{ 123518334Speter struct whatever *specific; 123618334Speter 123718334Speter if(!(specific = what[system_type])) 123818334Speter return *this; 123918334Speter 124018334Speter for (; specific->from != -1; specific++) 124118334Speter if(specific->from <= *this && *this <= specific->to) 124218334Speter if(specific->from == specific->to){ 124318334Speter if(specific->more){ 124418334Speter specific = specific->more; 124518334Speter this++; 124618334Speter continue; 124770639Sobrien } 124870639Sobrien else { 124970639Sobrien return((int)specific->conversion); 125070639Sobrien } 125190091Sobrien } 125270639Sobrien else { 125370639Sobrien return(specific->conversion ? ( 125470639Sobrien specific->all_the_same ? (int)specific->conversion : specific->conversion[*this - specific->from] ) : *this); 125570639Sobrien } 125670639Sobrien 125718334Speter return otherwise; 125818334Speter} 125918334Speter 126018334Speter/* Returns 0 - no conversion, no pointer modification 126152268Sobrien 1 - converted, relevant pointer modification 126252268Sobrien -1 - error 126352268Sobrien */ 126452268Sobrienint 126552268Sobrienss_convert_struct(alien, indicator, direction) 126652268Sobrien char *alien; 126752268Sobrien int indicator; 126852268Sobrien int direction; 126952268Sobrien{ 127052268Sobrienint error, len; 127152268Sobrien 127252268Sobrien switch (system_type) { 127352268Sobrien 127452268Sobrien case SS_FREEBSD: 127552268Sobrien return(0); 127618334Speter case SS_SYSVR4: 127718334Speter case SS_SYSVR3: 127818334Speter case SS_SCO_32: 127918334Speter case SS_WYSE_321: 128018334Speter case SS_ISC: 128118334Speter case SS_LINUX: 128218334Speter 128318334Speter switch(direction){ 128452268Sobrien 128552268Sobrien case SS_ALIEN_TO_NATIVE: 128652268Sobrien 128790091Sobrien error = ss_atn(alien, indicator); 128852268Sobrien#ifdef SS_DEBUG 128952268Sobrien if(ss_debug > 1) 129052268Sobrien printf("ss_convert: ATN ss_atn error %d\n",error); 129152268Sobrien#endif /* SS_DEBUG */ 129252268Sobrien return(error); 129352268Sobrien 129452268Sobrien case SS_NATIVE_TO_ALIEN: 129552268Sobrien 129652268Sobrien error = ss_nta(alien, indicator); 129752268Sobrien#ifdef SS_DEBUG 129852268Sobrien if(ss_debug > 1) 129952268Sobrien printf("ss_convert: NTA ss_nta error %d\n",error); 130052268Sobrien#endif /* SS_DEBUG */ 130152268Sobrien return(error); 130252268Sobrien 130352268Sobrien } 130452268Sobrien 130552268Sobrien default: 130652268Sobrien 130752268Sobrien printf("ss_convert_struct: not expecting system_type %d\n", system_type); 130852268Sobrien break; 130952268Sobrien 131052268Sobrien } 131152268Sobrien return(EINVAL); 131252268Sobrien} 131352268Sobrien 131452268Sobrien/* note sockaddr_un linux unsigned short fam, 108 path 131552268Sobrien BSD uchar , uchar 104 */ 131652268Sobrienint 131752268Sobrienss_atn(alien, indicator) 131852268Sobrien char *alien; 131952268Sobrien int indicator; 132052268Sobrien{ 132152268Sobrienint error; 132290091Sobrien 132352268Sobrien switch (indicator) { 132418334Speter 132518334Speter case SS_STRUCT_ARPREQ: 132618334Speter /* compatible */ 132718334Speter return(0); 132818334Speter 132918334Speter case SS_STRUCT_IFCONF: 133018334Speter /* compatible */ 133118334Speter return(0); 133218334Speter 133318334Speter case SS_STRUCT_IFREQ: 133418334Speter /* length OK - more unions - function dependent */ 133518334Speter return(0); 133618334Speter 133718334Speter case SS_STRUCT_ORTENTRY: 133818334Speter /* compatible */ 133918334Speter return(0); 134052268Sobrien 134152268Sobrien case SS_STRUCT_SOCKADDR:{ 134252268Sobrien struct native_hdr { 134352268Sobrien u_char len; 134452268Sobrien u_char family; 134552268Sobrien }; 134652268Sobrien union hdr_part { 134752268Sobrien struct native_hdr native; 134852268Sobrien u_short alien_family; 134952268Sobrien } hdr; 135052268Sobrien 135152268Sobrien if(error = copyin((caddr_t)alien,(caddr_t)&hdr,sizeof(hdr))) 135218334Speter return(error); 135318334Speter#ifdef SS_DEBUG 135418334Speter if(ss_debug > 1) 135518334Speter printf("ss_atn:copyin 0x%x\n",hdr.alien_family); 135618334Speter#endif /* SS_DEBUG */ 135718334Speter 135818334Speter if( hdr.alien_family < AF_MAX){ 135918334Speter hdr.native.family = hdr.alien_family >> 8; /* 386 endianess */ 136090091Sobrien /* OR LEN FOM A PARAM ? */ 136118334Speter hdr.native.len = sizeof(struct sockaddr); 136218334Speter#ifdef SS_DEBUG 136318334Speter if(ss_debug > 1) 136452268Sobrien printf("ss_atn:copyout 0x%x\n",hdr.alien_family); 136590091Sobrien#endif /* SS_DEBUG */ 136690091Sobrien error = copyout((caddr_t)&hdr,(caddr_t)alien,sizeof(hdr)); 136790091Sobrien return(error); 136818334Speter } 136918334Speter else { 137018334Speter printf("ss_atn: sa_family = %d\n", hdr.alien_family); 137152268Sobrien return(EINVAL); 137290091Sobrien } 137390091Sobrien 137490091Sobrien } 137518334Speter 137618334Speter case SS_STRUCT_SOCKNEWPROTO: 137718334Speter /* don't have */ 137818334Speter printf("ss_atn: not expecting SS_STRUCT_SOCKNEWPROTO\n"); 137918334Speter return(EINVAL); 138018334Speter 138118334Speter default: 138218334Speter printf("ss_atn: not expecting case %d\n",indicator); 138318334Speter return(EINVAL); 138418334Speter 138518334Speter } 138618334Speter} 138718334Speter 138890091Sobrien/* note sockaddr_un linux unsigned short fam, 108 path 138990091Sobrien BSD uchar , uchar 104 */ 139090091Sobrienint 139190091Sobrienss_nta(alien, indicator) 139290091Sobrien char *alien; 139352268Sobrien int indicator; 139490091Sobrien{ 139518334Speterint error; 139618334Speter 139718334Speter switch (indicator) { 139818334Speter 139918334Speter case SS_STRUCT_ARPREQ: 140090091Sobrien /* compatible */ 140118334Speter return(0); 140218334Speter 140318334Speter case SS_STRUCT_IFCONF: 140418334Speter /* compatible */ 140518334Speter return(0); 140618334Speter 140718334Speter case SS_STRUCT_IFREQ: 140818334Speter /* length OK - more unions - function dependent */ 140952268Sobrien return(0); 141052268Sobrien 141152268Sobrien case SS_STRUCT_ORTENTRY: 141252268Sobrien /* compatible */ 141352268Sobrien return(0); 141452268Sobrien 141552268Sobrien case SS_STRUCT_SOCKADDR:{ 141652268Sobrien struct native_hdr { 141752268Sobrien u_char len; 141852268Sobrien u_char family; 141952268Sobrien }; 142052268Sobrien union hdr_part { 142152268Sobrien struct native_hdr native; 142252268Sobrien u_short alien_family; 142352268Sobrien } hdr; 142452268Sobrien 142518334Speter if(error = copyin((caddr_t)alien,(caddr_t)&hdr,sizeof(hdr))) 142618334Speter return(error); 142718334Speter#ifdef SS_DEBUG 142852268Sobrien if(ss_debug > 1) 142952268Sobrien printf("ss_nta:copyin 0x%x\n",hdr.alien_family); 143052268Sobrien#endif /* SS_DEBUG */ 143152268Sobrien hdr.alien_family = hdr.native.family; 143252268Sobrien#ifdef SS_DEBUG 143352268Sobrien if(ss_debug > 1) 143452268Sobrien printf("ss_nta:copyout 0x%x\n",hdr.alien_family); 143590091Sobrien#endif /* SS_DEBUG */ 143690091Sobrien error = copyout((caddr_t)&hdr,(caddr_t)alien,sizeof(hdr)); 143752268Sobrien return(error); 143818334Speter } 143918334Speter 144018334Speter case SS_STRUCT_SOCKNEWPROTO: 144190091Sobrien /* don't have */ 144290091Sobrien printf("ss_nta: not expecting SS_STRUCT_SOCKNEWPROTO\n"); 144390091Sobrien return(EINVAL); 144490091Sobrien 144518334Speter default: 144690091Sobrien printf("ss_nta: not expecting case %d\n",indicator); 144790091Sobrien return(EINVAL); 144890091Sobrien 144918334Speter } 145018334Speter} 145190091Sobrien