summaryrefslogtreecommitdiffstats
path: root/sys/i386/ibcs2/ibcs2_socksys.c
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>1994-10-14 08:53:16 +0000
committersos <sos@FreeBSD.org>1994-10-14 08:53:16 +0000
commit8c25a4d2ace95c98887a2c73b1a1b7ac8c79f8ef (patch)
tree03e7e36f42559e1855d7488025f88b38a06ded17 /sys/i386/ibcs2/ibcs2_socksys.c
parente5a7fbf2bb8340c56fa8524e8b92c32ee9abb588 (diff)
downloadFreeBSD-src-8c25a4d2ace95c98887a2c73b1a1b7ac8c79f8ef.zip
FreeBSD-src-8c25a4d2ace95c98887a2c73b1a1b7ac8c79f8ef.tar.gz
iBCS2 emulator core files.
This is the main files for the iBCS2 emulator. It can be use compiled into the kernel by using: options IBCS2 options COMPAT_IBCS2 or as a lkm module using: options COMPAT_IBCS2 and then loading it via the ibcs2 script in /usr/bin REMEMBER: this code is still experimental ! NO WARRENTY ! Submitted by: sef@kithrup.com, mostyn@mrl.com, sos@kmd-ac.dk
Diffstat (limited to 'sys/i386/ibcs2/ibcs2_socksys.c')
-rw-r--r--sys/i386/ibcs2/ibcs2_socksys.c1450
1 files changed, 1450 insertions, 0 deletions
diff --git a/sys/i386/ibcs2/ibcs2_socksys.c b/sys/i386/ibcs2/ibcs2_socksys.c
new file mode 100644
index 0000000..a5076da
--- /dev/null
+++ b/sys/i386/ibcs2/ibcs2_socksys.c
@@ -0,0 +1,1450 @@
+/*-
+ * Copyright (c) 1994 Mostyn Lewis
+ * All rights reserved.
+ *
+ * This software is based on code which is:
+ * Copyright (c) 1994 Mike Jagdis (jaggy@purplet.demon.co.uk)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ibcs2_socksys.c,v 1.2 1994/10/13 23:10:58 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/filedesc.h>
+#include <sys/file.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/ioctl.h>
+#include <sys/sockio.h>
+#include <sys/proc.h>
+#include <sys/exec.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/malloc.h>
+#include <sys/un.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <vm/vm.h>
+#include <i386/ibcs2/ibcs2.h>
+#include <i386/ibcs2/ibcs2_socksys.h>
+
+/* Socksys pseudo driver entry points */
+
+int sockopen (dev_t dev, int mode, int devtype, struct proc *p);
+int sockioctl(dev_t dev, int cmd, caddr_t arg, int fflag, struct proc *p);
+int sockclose(dev_t dev, int flag, int mode, struct proc *p);
+
+/* Socksys internal functions */
+
+static void put_socket_fops(struct proc *p, int fd);
+static int ss_fop_close(struct file *fp, struct proc *p);
+static int ss_fop_ioctl(struct file*fp, int cmd, caddr_t arg, struct proc *p);
+static int ss_syscall(caddr_t arg, struct proc *p);
+
+/*
+ * This structure is setup on first usage. Its address is planted
+ * into a socket's file structure fileops pointer after a successful
+ * socket creation or accept.
+ */
+static struct fileops ss_socket_fops = {
+ NULL, /* normal socket read */
+ NULL, /* normal socket write */
+ NULL, /* socksys ioctl */
+ NULL, /* normal socket select */
+ NULL, /* socksys close */
+};
+
+static int (*close_s)__P((struct file *fp, struct proc *p));
+static int (*ioctl_s)__P((struct file *fp, int cmd, caddr_t data, struct proc *p));
+
+int ss_debug = 1;
+
+static int
+ss_syscall(arg, p)
+ caddr_t arg;
+ struct proc *p;
+{
+ int cmd;
+ int error;
+ int retval[2];
+
+ retval[0] = retval[1] = 0;
+ cmd = ((struct ss_call *)arg)->arg[0];
+
+#ifdef SS_DEBUG
+ if(ss_debug) {
+ static char *ss_syscall_strings[] = {
+ "0?", "accept", "bind", "connect", "getpeername",
+ "getsockname", "getsockopt", "listen", "recv(from)",
+ "recvfrom", "send(to)", "sendto", "setsockopt", "shutdown",
+ "socket", "select", "getipdomain", "setipdomain",
+ "adjtime", "setreuid", "setregid", "gettimeofday",
+ "settimeofday", "getitimer", "setitimer",
+ };
+
+ printf("ss_syscall: [%d] ",p->p_pid);
+ if(cmd < 0 || (cmd > CMD_SO_SETITIMER && cmd != CMD_SO_SS_DEBUG) )
+ printf("? ");
+ else {
+ if(cmd == CMD_SO_SS_DEBUG)
+ printf("%s ","ss_debug");
+ else
+ printf("%s ",ss_syscall_strings[cmd]);
+ }
+ printf("(%d) <0x%x,0x%x,0x%x,0x%x,0x%x,0x%x>\n",
+ cmd,
+ ((struct ss_call *)arg)->arg[1],
+ ((struct ss_call *)arg)->arg[2],
+ ((struct ss_call *)arg)->arg[3],
+ ((struct ss_call *)arg)->arg[4],
+ ((struct ss_call *)arg)->arg[5],
+ ((struct ss_call *)arg)->arg[6]);
+ }
+#endif /* SS_DEBUG */
+
+ error = 0;
+
+ switch (cmd) {
+
+ case CMD_SO_SS_DEBUG:
+
+ ss_debug = ((struct ss_call *)arg)->arg[1];
+ break;
+
+ case CMD_SO_SOCKET: { /* NO CONV */
+
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("SO_SOCKET af in %d\n",
+ ((struct ss_call *)arg)->arg[1]);
+#endif /* SS_DEBUG */
+ ((struct ss_call *)arg)->arg[1] = ss_convert(
+ af_whatevers,
+ &(((struct ss_call *)arg)->arg[1]),
+ 0);
+#ifdef SS_DEBUG
+ if(ss_debug > 1) {
+ printf("SO_SOCKET af out %d\n",
+ ((struct ss_call *)arg)->arg[1]);
+
+ printf("SO_SOCKET type in %d\n",
+ ((struct ss_call *)arg)->arg[2]);
+ }
+#endif /* SS_DEBUG */
+ ((struct ss_call *)arg)->arg[2] = ss_convert(
+ type_whatevers,
+ &(((struct ss_call *)arg)->arg[2]),
+ 0);
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("SO_SOCKET type out %d\n",
+ ((struct ss_call *)arg)->arg[2]);
+#endif /* SS_DEBUG */
+
+ SYSCALL(SYS_socket, 0, 0);
+
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("ss_syscall: [%d] socket fd=%d\n",
+ p->p_pid, retval[0]);
+#endif /* SS_DEBUG */
+ put_socket_fops(p,retval[0]);
+
+ break;
+ }
+
+ case CMD_SO_ACCEPT: { /* CONVERSION in arg 2 */
+
+ SYSCALL(SYS_accept, 2, SS_STRUCT_SOCKADDR);
+
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("ss_syscall: [%d] accept fd=%d\n",
+ p->p_pid, retval[0]);
+#endif /* SS_DEBUG */
+ put_socket_fops(p,retval[0]);
+
+ break;
+ }
+
+ case CMD_SO_BIND:
+ SYSCALL(SYS_bind, 2, SS_STRUCT_SOCKADDR);
+ break;
+
+ case CMD_SO_CONNECT: {
+ struct alien_sockaddr *sa;
+ unsigned short family;
+
+ /* Remap any INADDR_ANY (0.0.0.0) to localhost */
+
+ sa = (struct alien_sockaddr *)((struct ss_call *)arg)->arg[1];
+ if(error = copyin((caddr_t)&sa->sa_family,
+ (caddr_t)&family, sizeof(short)))
+ return(error);
+ if (family == AF_INET) {
+ unsigned long *addr;
+ unsigned long saddr;
+
+ addr = &(((struct alien_sockaddr_in *)sa)->sin_addr.s_addr);
+ if(error = copyin((caddr_t)addr, (caddr_t)&saddr, sizeof(long)))
+ return(error);
+ if (saddr == INADDR_ANY) {
+ /* 0x0100007f is 127.0.0.1 reversed */
+ saddr = 0x0100007f;
+ if(error = copyout((caddr_t)&saddr,
+ (caddr_t)addr, sizeof(long)))
+ return(error);
+#ifdef SS_DEBUG
+ if (ss_debug)
+ printf("ss_syscall: remapped INADDR_ANY to localhost\n");
+#endif /* SS_DEBUG */
+ }
+ }
+ SYSCALL(SYS_connect, 2, SS_STRUCT_SOCKADDR);
+ break;
+ }
+
+ case CMD_SO_GETPEERNAME:
+ SYSCALL(SYS_getpeername, 2, SS_STRUCT_SOCKADDR);
+ break;
+
+ case CMD_SO_GETSOCKNAME:
+ SYSCALL(SYS_getsockname, 2, SS_STRUCT_SOCKADDR);
+ break;
+
+ case CMD_SO_GETSOCKOPT:
+ if(error = ss_getsockopt((caddr_t)(((int *)arg) + 1),retval,p))
+ return(error);
+ break;
+
+ case CMD_SO_LISTEN:
+ SYSCALL(SYS_listen, 0, 0);
+ break;
+
+ case CMD_SO_RECV:
+ ((struct ss_call *)arg)->arg[5] = (int)((struct sockaddr *)NULL);
+ ((struct ss_call *)arg)->arg[6] = 0;
+ SYSCALL(SYS_recvfrom, 0, 0);
+ break;
+
+ case CMD_SO_RECVFROM:
+ SYSCALL(SYS_recvfrom, 5, SS_STRUCT_SOCKADDR);
+ break;
+
+ case CMD_SO_SEND:
+ ((struct ss_call *)arg)->arg[5] = (int)((struct sockaddr *)NULL);
+ ((struct ss_call *)arg)->arg[6] = 0;
+ SYSCALL(SYS_sendto, 0, 0);
+ break;
+
+ case CMD_SO_SENDTO:
+ SYSCALL(SYS_sendto, 5, SS_STRUCT_SOCKADDR);
+ break;
+
+ case CMD_SO_SETSOCKOPT:
+ if(error = ss_setsockopt((caddr_t)(((int *)arg) + 1),retval,p))
+ return(error);
+
+ case CMD_SO_SHUTDOWN:
+ SYSCALL(SYS_shutdown, 0, 0);
+ break;
+
+ case CMD_SO_GETIPDOMAIN:
+ SYSCALL(SYS_getdomainname, 0, 0);
+ break;
+
+ case CMD_SO_SETIPDOMAIN: /* Note check on BSD utsname no change? */
+ SYSCALL(SYS_setdomainname, 0, 0);
+ break;
+
+ case CMD_SO_SETREUID:
+ SYSCALL(126/*SYS_setreuid*/, 0, 0);
+ break;
+
+ case CMD_SO_SETREGID:
+ SYSCALL(127/*SYS_setregid*/, 0, 0);
+ break;
+
+ case CMD_SO_GETTIME:
+ SYSCALL(SYS_gettimeofday, 0, 0);
+ break;
+
+ case CMD_SO_SETTIME:
+ SYSCALL(SYS_settimeofday, 0, 0);
+ break;
+
+ case CMD_SO_GETITIMER:
+ SYSCALL(SYS_getitimer, 0, 0);
+ break;
+
+ case CMD_SO_SETITIMER:
+ SYSCALL(SYS_setitimer, 0, 0);
+ break;
+
+ case CMD_SO_SELECT:
+ SYSCALL(SYS_select, 0, 0);
+ break;
+
+ case CMD_SO_ADJTIME:
+ SYSCALL(SYS_adjtime, 0, 0);
+ break;
+
+ default:
+ printf("ss_syscall: default 0x%x\n",cmd);
+ return (EINVAL);
+ }
+ IBCS2_MAGIC_RETURN;
+}
+
+
+static int
+ss_fop_ioctl(fp, cmd, arg, p)
+ struct file *fp;
+ int cmd;
+ caddr_t arg;
+ struct proc *p;
+{
+ int error;
+ int retval[2];
+
+#ifdef SS_DEBUG
+ if(ss_debug) {
+ static char **ioctl_strings;
+ int fd;
+ struct filedesc *fdp;
+ unsigned int ioctl_type;
+ unsigned int ioctl_len;
+ char cmd_type;
+ int cmd_ordinal;
+
+ static char *ioctl_type_strings[] = {
+ "0?", "SS_IO", "SS_IOR", "3?", "SS_IOW", "5?", "SS_IOWR"
+ };
+ static char *ioctl_S_strings[] = {
+ "0?", "SIOCSHIWAT", "SIOCGHIWAT", "SIOCSLOWAT", "SIOCGLOWAT",
+ "SIOCATMARK", "SIOCSPGRP", "SIOCGPGRP", "FIONREAD",
+ "FIONBIO", "FIOASYNC", "SIOCPROTO", "SIOCGETNAME",
+ "SIOCGETPEER", "IF_UNITSEL", "SIOCXPROTO"
+ };
+ static char *ioctl_R_strings[] = {
+ "0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?",
+ "SIOCADDRT", "SIOCDELRT"
+ };
+ static char *ioctl_I_strings[] = {
+ "0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?",
+ "9?", "10?", "SIOCSIFADDR", "SIOCGIFADDR", "SIOCSIFDSTADDR",
+ "SIOCGIFDSTADDR", "SIOCSIFFLAGS", "SIOCGIFFLAGS",
+ "SIOCGIFCONF", "18?", "19?", "20?", "SIOCSIFMTU",
+ "SIOCGIFMTU", "23?", "24?", "25?", "SIOCIFDETACH",
+ "SIOCGENPSTATS", "28?", "SIOCX25XMT", "SS_SIOCX25RCV",
+ "SS_SIOCX25TBL", "SIOCGIFBRDADDR" ,"SIOCSIFBRDADDR",
+ "SIOCGIFNETMASK", "SIOCSIFNETMASK", "SIOCGIFMETRIC",
+ "SIOCSIFMETRIC", "SIOCSARP", "SIOCGARP", "SIOCDARP",
+ "SIOCSIFNAME", "SIOCGIFONEP", "SIOCSIFONEP ",
+ "44?", "45?", "46?", "47?", "48?", "49?", "50?", "51?",
+ "52?", "53?", "54?", "55?", "56?", "57?", "58?", "59?",
+ "60?", "61?", "62?", "63?", "64?", "SIOCGENADDR",
+ "SIOCSOCKSYS"
+ };
+
+ cmd_type = (cmd >> 8) & 0xff;
+ cmd_ordinal = cmd & 0xff;
+
+ switch (cmd_type) {
+
+ case 'S':
+ ioctl_strings = ioctl_S_strings;
+ if (cmd_ordinal > 15)
+ cmd_ordinal = -1;
+ break;
+
+ case 'R':
+ ioctl_strings = ioctl_R_strings;
+ if (cmd_ordinal > 10)
+ cmd_ordinal = -1;
+ break;
+
+ case 'I':
+ ioctl_strings = ioctl_I_strings;
+ if (cmd_ordinal > 66)
+ cmd_ordinal = -1;
+ break;
+
+ default:
+ cmd_type = '?';
+ break;
+ }
+ fdp = p->p_fd;
+ fd = -1;
+ while(++fd < NOFILE)
+ if ( fp == fdp->fd_ofiles[fd] )
+ break;
+
+ ioctl_type = (0xe0000000 & cmd) >> 29;
+ ioctl_len = (cmd >> 16) & SS_IOCPARM_MASK;
+
+ printf("ss_fop_ioctl: [%d] fd=%d ",p->p_pid, fd);
+ if(cmd_type != '?'){
+ if(cmd_ordinal != -1)
+ printf("%s %s('%c',%d,l=%d) ",ioctl_strings[cmd_ordinal],
+ ioctl_type_strings[ioctl_type],
+ cmd_type,
+ cmd_ordinal,
+ ioctl_len);
+ else {
+ cmd_ordinal = cmd & 0xff;
+ printf("[unknown ordinal %d] %s('%c',%d,l=%d) ",cmd_ordinal,
+ ioctl_type_strings[ioctl_type],
+ cmd_type,
+ cmd_ordinal,
+ ioctl_len);
+ }
+ }
+ else {
+ printf("? %s('%c',%d,l=%d) ",
+ ioctl_type_strings[ioctl_type],
+ cmd_type,
+ cmd_ordinal,
+ ioctl_len);
+ }
+
+ printf("0x%x (0x%x) <0x%x>\n",
+ fp, cmd, arg);
+ }
+#endif /* SS_DEBUG */
+
+ /* No dogs allowed */
+
+ if(*(((int *)arg) - 3) != IBCS2_MAGIC_IN){
+ printf("ss_fop_ioctl: bad magic (sys_generic.c has no socksys mods?)\n");
+ return(EINVAL);
+ }
+
+ if(fp->f_type != DTYPE_SOCKET)
+ return (ENOTSOCK);
+
+ retval[0] = retval[1] = 0;
+
+
+ error = 0;
+
+ switch (cmd) {
+ case SS_SIOCSHIWAT: /* set high watermark */
+ case SS_SIOCSLOWAT: /* set low watermark */
+ break; /* return value of 0 and no error */
+
+ case SS_SIOCGHIWAT: /* get high watermark */
+ case SS_SIOCGLOWAT: /* get low watermark */
+ break; /* return value of 0 and no error */
+
+ case SS_SIOCATMARK: /* at oob mark */
+ IOCTL(SIOCATMARK);
+ break;
+
+ case SS_SIOCSPGRP: /* set process group */
+ IOCTL(SIOCSPGRP);
+ break;
+ case SS_SIOCGPGRP: /* get process group */
+ IOCTL(SIOCGPGRP);
+ break;
+
+ case FIONREAD:
+ case SS_FIONREAD: /* get # bytes to read */
+ IOCTL(FIONREAD);
+ break;
+
+ case SS_FIONBIO: /* set/clear non-blocking i/o */
+ IOCTL(FIONBIO);
+ break;
+
+ case SS_FIOASYNC: /* set/clear async i/o */
+ IOCTL(FIOASYNC);
+ break;
+
+ case SS_SIOCADDRT: /* add route - uses struct ortentry */
+ IOCTL(SIOCADDRT);
+ break;
+
+ case SS_SIOCDELRT: /* delete route - uses struct ortentry */
+ IOCTL(SIOCDELRT);
+ break;
+
+ case SS_SIOCSIFADDR: /* set ifnet address */
+ IOCTL(SIOCSIFADDR);
+ break;
+
+ case SS_SIOCGIFADDR: /* get ifnet address */
+ IOCTL(SIOCGIFADDR);
+ break;
+
+ case SS_SIOCSIFDSTADDR: /* set p-p address */
+ IOCTL(SIOCSIFDSTADDR);
+ break;
+
+ case SS_SIOCGIFDSTADDR: /* get p-p address */
+ IOCTL(SIOCGIFDSTADDR);
+ break;
+
+ case SS_SIOCSIFFLAGS: /* set ifnet flags */
+ IOCTL(SIOCSIFFLAGS);
+ break;
+
+ case SS_SIOCGIFFLAGS: /* get ifnet flags */
+ IOCTL(SIOCGIFFLAGS);
+ break;
+
+ case SS_SIOCGIFCONF: /* get ifnet ltst */
+ IOCTL(SIOCGIFCONF);
+ break;
+
+ case SS_SIOCGIFBRDADDR: /* get broadcast addr */
+ IOCTL(SIOCGIFBRDADDR);
+ break;
+
+ case SS_SIOCSIFBRDADDR: /* set broadcast addr */
+ IOCTL(SIOCSIFBRDADDR);
+ break;
+
+ case SS_SIOCGIFNETMASK: /* get net addr mask */
+ IOCTL(SIOCGIFNETMASK);
+ break;
+
+ case SS_SIOCSIFNETMASK: /* set net addr mask */
+ IOCTL(SIOCSIFNETMASK);
+ break;
+
+ case SS_SIOCGIFMETRIC: /* get IF metric */
+ IOCTL(SIOCGIFMETRIC);
+ break;
+
+ case SS_SIOCSIFMETRIC: /* set IF metric */
+ IOCTL(SIOCSIFMETRIC);
+ break;
+
+/* FreeBSD 2.0 does not have socket ARPs */
+
+#ifdef SIOCSARP
+
+ case SS_SIOCSARP: /* set arp entry */
+ IOCTL(SIOCSARP);
+ break;
+
+ case SS_SIOCGARP: /* get arp entry */
+ IOCTL(SIOCGARP);
+ break;
+
+ case SS_SIOCDARP: /* delete arp entry */
+ IOCTL(SIOCDARP);
+ break;
+
+#else /* SIOCSARP */
+
+ case SS_SIOCSARP: /* set arp entry */
+ return(EINVAL);
+
+ case SS_SIOCGARP: /* get arp entry */
+ return(EINVAL);
+
+ case SS_SIOCDARP: /* delete arp entry */
+ return(EINVAL);
+
+#endif /* SIOCSARP */
+
+ case SS_SIOCGENADDR: /* Get ethernet addr XXX */
+ return (EINVAL);
+/* return (error = ioctl_s(fp, SIOCGIFHWADDR, arg, p)); */
+
+ case SS_SIOCSIFMTU: /* get if_mtu */
+ IOCTL(SIOCSIFMTU);
+ break;
+
+ case SS_SIOCGIFMTU: /* set if_mtu */
+ IOCTL(SIOCGIFMTU);
+ break;
+
+ case SS_SIOCGETNAME: /* getsockname XXX */
+ return (EINVAL);
+/* return (ioctl_s(fp, SIOCGIFNAME, arg, p)); MMM */
+
+ case SS_SIOCGETPEER: { /* getpeername */
+ struct moose {
+ int fd;
+ caddr_t asa;
+ int *alen;
+ int compat_43;
+ } args;
+
+ struct alien_sockaddr uaddr;
+ struct sockaddr nuaddr;
+ int nuaddr_len = sizeof(struct sockaddr);
+ struct filedesc *fdp;
+
+ if(fp->f_type != DTYPE_SOCKET)
+ return (ENOTSOCK);
+
+ bzero((caddr_t)&nuaddr, sizeof(struct sockaddr));
+ fdp = p->p_fd;
+ args.fd = -1;
+ while(++args.fd < NOFILE)
+ if ( fp == fdp->fd_ofiles[args.fd] )
+ break;
+ if(args.fd == NOFILE){
+ printf("ss_fop_ioctl: [%d] SS_SIOCGETPEER args.fd > NOFILE\n", p->p_pid);
+ return(EBADF);
+ }
+ args.asa = (caddr_t)&nuaddr;
+ args.alen = &nuaddr_len;
+ args.compat_43 = 0;
+ error = SYSCALLX(SYS_getpeername, &args);
+ if(error)
+ return(error);
+
+ bzero((caddr_t)&uaddr, sizeof(struct alien_sockaddr));
+ uaddr.sa_family = (unsigned short)nuaddr.sa_family;
+ bcopy(&nuaddr.sa_data, &uaddr.sa_data, __ALIEN_SOCK_SIZE__ - sizeof(unsigned short));
+
+ error = copyout((caddr_t)&uaddr, (caddr_t)arg, sizeof(struct alien_sockaddr));
+ return error;
+ }
+
+ default:
+ printf("ss_fop_ioctl: [%d] %lx unknown ioctl 0x%x, 0x%lx\n",
+ p->p_pid, (unsigned long)fp,
+ cmd, (unsigned long)arg);
+ return (EINVAL);
+ }
+ IBCS2_MAGIC_RETURN;
+}
+
+int
+sockioctl(dev, cmd, arg, fflag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t arg;
+ int fflag;
+ struct proc *p;
+{
+ int error;
+ int retval[2];
+
+#ifdef SS_DEBUG
+ if(ss_debug) {
+ char cmd_type;
+ int cmd_ordinal;
+ static char **ioctl_strings;
+ unsigned int ioctl_type;
+ unsigned int ioctl_len;
+
+ static char *ioctl_type_strings[] = {
+ "NIOCxx", "SS_IO", "SS_IOR", "3?", "SS_IOW", "5?", "SS_IOWR"
+ };
+ static char *ioctl_S_strings[] = {
+ "0?", "SIOCSHIWAT", "SIOCGHIWAT", "SIOCSLOWAT", "SIOCGLOWAT",
+ "SIOCATMARK", "SIOCSPGRP", "SIOCGPGRP", "FIONREAD",
+ "FIONBIO", "FIOASYNC", "SIOCPROTO", "SIOCGETNAME",
+ "SIOCGETPEER", "IF_UNITSEL", "SIOCXPROTO"
+ };
+ static char *ioctl_R_strings[] = {
+ "0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?",
+ "SIOCADDRT", "SIOCDELRT"
+ };
+ static char *ioctl_I_strings[] = {
+ "0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?",
+ "9?", "10?", "SIOCSIFADDR", "SIOCGIFADDR", "SIOCSIFDSTADDR",
+ "SIOCGIFDSTADDR", "SIOCSIFFLAGS", "SIOCGIFFLAGS",
+ "SIOCGIFCONF", "18?", "19?", "20?", "SIOCSIFMTU",
+ "SIOCGIFMTU", "23?", "24?", "25?", "SIOCIFDETACH",
+ "SIOCGENPSTATS", "28?", "SIOCX25XMT", "SS_SIOCX25RCV",
+ "SS_SIOCX25TBL", "SIOCGIFBRDADDR" ,"SIOCSIFBRDADDR",
+ "SIOCGIFNETMASK", "SIOCSIFNETMASK", "SIOCGIFMETRIC",
+ "SIOCSIFMETRIC", "SIOCSARP", "SIOCGARP", "SIOCDARP",
+ "SIOCSIFNAME", "SIOCGIFONEP", "SIOCSIFONEP ",
+ "44?", "45?", "46?", "47?", "48?", "49?", "50?", "51?",
+ "52?", "53?", "54?", "55?", "56?", "57?", "58?", "59?",
+ "60?", "61?", "62?", "63?", "64?", "SIOCGENADDR",
+ "SIOCSOCKSYS"
+ };
+ static char *ioctl_NIOC_strings[] = {
+ "0?", "NIOCNFSD", "NIOCOLDGETFH", "NIOCASYNCD",
+ "NIOCSETDOMNAM", "NIOCGETDOMNAM", "NIOCCLNTHAND",
+ "NIOCEXPORTFS", "NIOCGETFH", "NIOCLSTAT"
+ };
+
+ cmd_ordinal = cmd & 0xff;
+ cmd_type = (cmd >> 8) & 0xff;
+ switch (cmd_type) {
+
+ case 0:
+ ioctl_strings = ioctl_NIOC_strings;
+ cmd_type = ' ';
+ if (cmd_ordinal > 9)
+ cmd_ordinal = -1;
+ break;
+
+ case 'S':
+ ioctl_strings = ioctl_S_strings;
+ if (cmd_ordinal > 15)
+ cmd_ordinal = -1;
+ break;
+
+ case 'R':
+ ioctl_strings = ioctl_R_strings;
+ if (cmd_ordinal > 10)
+ cmd_ordinal = -1;
+ break;
+
+ case 'I':
+ ioctl_strings = ioctl_I_strings;
+ if (cmd_ordinal > 66)
+ cmd_ordinal = -1;
+ break;
+
+ default:
+ cmd_type = '?';
+ break;
+
+ }
+ ioctl_type = (0xe0000000 & cmd) >> 29;
+ ioctl_len = (cmd >> 16) & SS_IOCPARM_MASK;
+
+ printf("sockioctl: [%d] ",p->p_pid);
+ if(cmd_type != '?'){
+ if(cmd_ordinal != -1)
+ printf("%s %s('%c',%d,l=%d) ",ioctl_strings[cmd_ordinal],
+ ioctl_type_strings[ioctl_type],
+ cmd_type,
+ cmd_ordinal,
+ ioctl_len);
+ else {
+ cmd_ordinal = cmd & 0xff;
+ printf("[unknown ordinal %d] %s('%c',%d,l=%d) ",cmd_ordinal,
+ ioctl_type_strings[ioctl_type],
+ cmd_type,
+ cmd_ordinal,
+ ioctl_len);
+ }
+ }
+ else {
+ printf("? %s('%c',%d,l=%d) ",
+ ioctl_type_strings[ioctl_type],
+ cmd_type,
+ cmd_ordinal,
+ ioctl_len);
+ }
+
+ printf("0x%x (0x%x) <0x%x>\n",
+ dev, cmd, arg);
+ }
+#endif /* SS_DEBUG */
+
+ if(*(((int *)arg) - 3) != IBCS2_MAGIC_IN){
+ printf("sockioctl: bad magic (sys_generic.c has no socksys mods?)\n");
+ return(EINVAL);
+ }
+
+ switch (cmd) {
+
+ case SS_SIOCSOCKSYS: /* ss syscall */
+ return ss_syscall(arg, p);
+
+ /* NIOCxx: These ioctls are really just integers
+ * (no other information to go on).
+ */
+
+ case NIOCSETDOMNAM: {
+ struct sgdomarg domargs;
+
+ if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&domargs, sizeof(struct sgdomarg)))
+ return(error);
+
+ arg = (caddr_t)&domargs;
+ SYSCALL_N(SYS_setdomainname, 0, 0);
+ break;
+ }
+
+ case NIOCGETDOMNAM: {
+ struct sgdomarg domargs;
+
+ if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&domargs, sizeof(struct sgdomarg)))
+ return(error);
+
+ arg = (caddr_t)&domargs;
+ SYSCALL_N(SYS_getdomainname, 0, 0);
+ break;
+ }
+
+ case NIOCLSTAT: {
+ struct lstatarg st;
+
+ if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&st, sizeof(struct lstatarg)))
+ return(error);
+
+ /* DO WE HAVE A FOREIGN LSTAT */
+/* return mumbo_lstat(st.fname, st.statb); */
+ return (EINVAL);
+ }
+
+ case NIOCNFSD:
+ case NIOCOLDGETFH:
+ case NIOCASYNCD:
+ case NIOCCLNTHAND:
+ case NIOCEXPORTFS:
+ case NIOCGETFH:
+ return (EINVAL);
+
+
+ case SS_IF_UNITSEL: /* set unit number */
+ case SS_SIOCXPROTO: /* empty proto table */
+
+ case SS_SIOCIFDETACH: /* detach interface */
+ case SS_SIOCGENPSTATS: /* get ENP stats */
+
+ case SS_SIOCSIFNAME: /* set interface name */
+ case SS_SIOCGIFONEP: /* get one-packet params */
+ case SS_SIOCSIFONEP: /* set one-packet params */
+
+ case SS_SIOCPROTO: /* link proto */
+ case SS_SIOCX25XMT:
+ case SS_SIOCX25RCV:
+ case SS_SIOCX25TBL:
+
+ printf("sockioctl: [%d] unsupported ioctl 0x%x , 0x%lx\n",
+ p->p_pid,
+ cmd, (unsigned long)arg);
+ return (EINVAL);
+
+ default:
+ printf("sockioctl: [%d] unknown ioctl 0x%x , 0x%lx\n",
+ p->p_pid,
+ cmd, (unsigned long)arg);
+ return (EINVAL);
+ }
+ IBCS2_MAGIC_RETURN;
+}
+
+
+int sockopen(dev, mode, devtype, p)
+ dev_t dev;
+ int mode;
+ int devtype;
+ struct proc *p;
+{
+
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("sockopen: [%d] 0x%x\n", p->p_pid, dev);
+#endif /* SS_DEBUG */
+
+ /* minor = 0 is the socksys device itself. No special handling
+ * will be needed as it is controlled by the application
+ * via ioctls.
+ */
+ if (minor(dev) == 0)
+ return 0;
+
+ /* minor = 1 is the spx device. This is the client side of a
+ * streams pipe to the X server. Under SCO and friends
+ * the library code messes around setting the connection
+ * up itself. We do it ourselves - this means we don't
+ * need to worry about the implementation of the server
+ * side (/dev/X0R - which must exist but can be a link
+ * to /dev/null) nor do we need to actually implement
+ * getmsg/putmsg.
+ */
+{ /* SPX */
+ int fd, error, args[3];
+ int retval[2];
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) + 1
+ struct sockaddr_un *Xaddr = (struct sockaddr_un *)UA_ALLOC();
+ retval[0] = retval[1] = 0;
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("sockopen: SPX: [%d] opening\n", p->p_pid);
+#endif /* SS_DEBUG */
+
+ /* Grab a socket. */
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("sockopen: SPX: [%d] get a unix domain socket\n",
+ p->p_pid);
+#endif /* SS_DEBUG */
+ args[0] = AF_UNIX;
+ args[1] = SOCK_STREAM;
+ args[2] = 0;
+ error = SYSCALLX(SYS_socket, args);
+ if (error)
+ return error;
+ fd = retval[0];
+ if(fd < 1) {
+ printf("sockopen: SPX: [%d] unexpected fd of %d\n",
+ p->p_pid, fd);
+ return(EOPNOTSUPP); /* MRL whatever */
+ }
+
+ /* Connect the socket to X. */
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("sockopen: SPX: [%d] connect to /tmp/X11-unix/X0\n",
+ p->p_pid);
+#endif /* SS_DEBUG */
+ args[0] = fd;
+ Xaddr->sun_family = AF_UNIX;
+ copyout("/tmp/.X11-unix/X0", Xaddr->sun_path, 18);
+ Xaddr->sun_len = SUN_LEN(Xaddr);
+ args[1] = (int)Xaddr;
+ args[2] = sizeof(struct sockaddr_un);
+ error = SYSCALLX(SYS_connect, args);
+ if (error) {
+ (void)SYSCALLX(SYS_close, &fd);
+ return error;
+ }
+
+ put_socket_fops(p,fd);
+
+ return 0;
+} /* SPX */
+}
+
+
+int sockclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("sockclose: [%d] 0x%x\n", p->p_pid, dev);
+#endif /* SS_DEBUG */
+ return(0);
+}
+
+static
+int ss_fop_close(struct file *fp, struct proc *p)
+{
+
+#ifdef SS_DEBUG
+int fd;
+struct filedesc *fdp;
+
+ if(ss_debug){
+ fdp = p->p_fd;
+ fd = -1;
+ while(++fd < NOFILE)
+ if ( fp == fdp->fd_ofiles[fd] )
+ break;
+ printf("ss_fop_close: [%d] fd=%d ", p->p_pid, fd);
+ }
+#endif /* SS_DEBUG */
+
+ if(fp->f_type == DTYPE_SOCKET) {
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("is a socket\n");
+#endif /* SS_DEBUG */
+ return(close_s(fp, p));
+ }
+ else {
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("is not a socket\n");
+#endif /* SS_DEBUG */
+ return(ENOTSOCK);
+ }
+}
+
+void put_socket_fops(struct proc *p, int fd)
+{
+struct filedesc *fdp;
+struct file *fp;
+
+ fdp = p->p_fd;
+ fp = fdp->fd_ofiles[fd];
+ if (ss_socket_fops.fo_ioctl != fp->f_ops->fo_ioctl) {
+ bcopy(fp->f_ops, &ss_socket_fops, sizeof(struct fileops));
+ ioctl_s = ss_socket_fops.fo_ioctl; /* save standard ioctl */
+ close_s = ss_socket_fops.fo_close; /* save standard close */
+ ss_socket_fops.fo_ioctl = ss_fop_ioctl;
+ ss_socket_fops.fo_close = ss_fop_close;
+ }
+ fp->f_ops = &ss_socket_fops;
+
+ return;
+}
+
+int ss_SYSCALL(n,convert_arg,indicator,arg,p,retval)
+ int n; /* syscall ordinal */
+ int convert_arg; /* if not 0, argument to convert */
+ int indicator; /* type of argument to convert */
+ int *arg; /* address of alien arg */
+ struct proc *p;
+ int *retval;
+{
+int error;
+int rc;
+
+ if(convert_arg){
+ if(rc = ss_convert_struct( (caddr_t)*(arg + convert_arg),
+ indicator,
+ SS_ALIEN_TO_NATIVE))
+ return(rc);
+
+ error = (*sysent[n].sy_call)(p, arg + 1, retval);
+ rc = ss_convert_struct( (caddr_t)*(arg + convert_arg),
+ indicator,
+ SS_NATIVE_TO_ALIEN);
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("ss_SYSCALL: [%d] error=%d, rc=%d\n",
+ p->p_pid, error, rc);
+#endif /* SS_DEBUG */
+ }
+ else {
+ rc = 0;
+ error = (*sysent[n].sy_call)(p, arg + 1, retval);
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("ss_SYSCALL: [%d] error=%d\n",p->p_pid, error);
+#endif /* SS_DEBUG */
+ }
+
+ return(error ? error : rc);
+}
+
+int ss_IOCTL(fp, cmd, arg, p)
+ struct file *fp;
+ int cmd;
+ int *arg; /* address of alien arg */
+ struct proc *p;
+{
+int error, rc;
+int these[2];
+char cmd_type;
+int cmd_ordinal;
+int indicator;
+
+ cmd_type = (cmd >> 8) & 0xff;
+ cmd_ordinal = cmd & 0xff;
+ these[0] = cmd_type;
+ these[1] = cmd_ordinal;
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_IOCTL: calling ss_convert with %d(%c) %d\n",
+ these[0],these[0],these[1]);
+#endif /* SS_DEBUG */
+ indicator = ss_convert( struct_whatevers, these, 0);
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_IOCTL: ss_convert returns indicator %d\n",indicator);
+#endif /* SS_DEBUG */
+ if(indicator){
+ error = ss_convert_struct((caddr_t)*(arg + 2),
+ indicator,
+ SS_ALIEN_TO_NATIVE);
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_IOCTL: ss_convert_struct returns %d\n",error);
+#endif /* SS_DEBUG */
+ if(error)
+ return(error);
+ /* change len in ioctl now - in the general case */
+ error = ioctl_s(fp, cmd, (caddr_t)arg, p);
+ rc = ss_convert_struct( (caddr_t)*(arg + 2),
+ indicator,
+ SS_NATIVE_TO_ALIEN);
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("ss_IOCTL: [%d] error=%d, rc=%d\n",p->p_pid,
+ error, rc);
+#endif /* SS_DEBUG */
+ }
+ else {
+ rc = 0;
+ error = ioctl_s(fp, cmd, (caddr_t)arg, p);
+#ifdef SS_DEBUG
+ if(ss_debug)
+ printf("ss_IOCTL: [%d] error=%d\n",p->p_pid, error);
+#endif /* SS_DEBUG */
+ }
+
+ return(error ? error : rc);
+}
+
+
+struct ss_socketopt_args {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int valsize;
+};
+
+int
+ss_setsockopt(arg, ret, p)
+ struct ss_socketopt_args *arg;
+ int *ret;
+ struct proc *p;
+{
+ int error, optname;
+ int retval[2];
+
+ if (arg->level != 0xffff) /* FreeBSD, SCO and ? */
+ return (ENOPROTOOPT);
+
+ optname = ss_convert(sopt_whatevers, &arg->name, 0);
+
+ switch (optname) {
+
+ case SO_ACCEPTCONN:
+ case SO_BROADCAST:
+ case SO_DEBUG:
+ case SO_DONTROUTE:
+ case SO_LINGER:
+ case SO_KEEPALIVE:
+ case SO_OOBINLINE:
+ case SO_RCVBUF:
+ case SO_RCVLOWAT:
+ case SO_RCVTIMEO:
+ case SO_REUSEADDR:
+ case SO_SNDBUF:
+ case SO_SNDLOWAT:
+ case SO_SNDTIMEO:
+ case SO_USELOOPBACK:
+ error = SYSCALLX(SYS_setsockopt, arg);
+ *ret = retval[0];
+ *(ret + 1) = retval[1];
+ return(error);
+
+ case SO_ERROR:
+ case SO_IMASOCKET:
+ case SO_NO_CHECK:
+ case SO_ORDREL:
+ case SO_PRIORITY:
+ case SO_PROTOTYPE:
+ case SO_TYPE:
+ return (ENOPROTOOPT);
+
+ }
+
+ return (ENOPROTOOPT);
+}
+
+
+int
+ss_getsockopt(arg, ret, p)
+ struct ss_socketopt_args *arg;
+ int *ret;
+ struct proc *p;
+{
+ int error, optname;
+ int retval[2];
+
+ if (arg->level != 0xffff) /* FreeBSD, SCO and ? */
+ return (ENOPROTOOPT);
+
+ optname = ss_convert(sopt_whatevers, &arg->name, 0);
+
+ switch (optname) {
+
+ case SO_ACCEPTCONN:
+ case SO_BROADCAST:
+ case SO_DEBUG:
+ case SO_DONTROUTE:
+ case SO_ERROR:
+ case SO_KEEPALIVE:
+ case SO_LINGER:
+ case SO_OOBINLINE:
+ case SO_RCVBUF:
+ case SO_RCVLOWAT:
+ case SO_RCVTIMEO:
+ case SO_REUSEADDR:
+ case SO_SNDBUF:
+ case SO_SNDLOWAT:
+ case SO_SNDTIMEO:
+ case SO_TYPE:
+ case SO_USELOOPBACK:
+ error = SYSCALLX(SYS_getsockopt, arg);
+ *ret = retval[0];
+ *(ret + 1) = retval[1];
+ return(error);
+
+
+ case SO_PROTOTYPE: {
+ int value = 0;
+
+ error = copyout((caddr_t)&value, (caddr_t)arg->s, sizeof(int));
+ return(error);
+ }
+
+
+ case SO_IMASOCKET: {
+ int value = 1;
+
+ error = copyout((caddr_t)&value, (caddr_t)arg->s, sizeof(int));
+ return(error);
+ }
+
+ case SO_NO_CHECK:
+ case SO_ORDREL:
+ case SO_PRIORITY:
+ return (ENOPROTOOPT);
+ }
+
+ return (ENOPROTOOPT);
+}
+
+#define SS_CONVERT
+int system_type = SS_FREEBSD; /* FreeBSD */
+
+int
+ss_convert(what, this, otherwise)
+ struct whatever **what;
+ int *this;
+ int otherwise;
+{
+ struct whatever *specific;
+
+ if(!(specific = what[system_type]))
+ return *this;
+
+ for (; specific->from != -1; specific++)
+ if(specific->from <= *this && *this <= specific->to)
+ if(specific->from == specific->to){
+ if(specific->more){
+ specific = specific->more;
+ this++;
+ continue;
+ }
+ else {
+ return((int)specific->conversion);
+ }
+ }
+ else {
+ return(specific->conversion ? (
+ specific->all_the_same ? (int)specific->conversion : specific->conversion[*this - specific->from] ) : *this);
+ }
+
+ return otherwise;
+}
+
+/* Returns 0 - no conversion, no pointer modification
+ 1 - converted, relevant pointer modification
+ -1 - error
+ */
+int
+ss_convert_struct(alien, indicator, direction)
+ char *alien;
+ int indicator;
+ int direction;
+{
+int error, len;
+
+ switch (system_type) {
+
+ case SS_FREEBSD:
+ return(0);
+ case SS_SYSVR4:
+ case SS_SYSVR3:
+ case SS_SCO_32:
+ case SS_WYSE_321:
+ case SS_ISC:
+ case SS_LINUX:
+
+ switch(direction){
+
+ case SS_ALIEN_TO_NATIVE:
+
+ error = ss_atn(alien, indicator);
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_convert: ATN ss_atn error %d\n",error);
+#endif /* SS_DEBUG */
+ return(error);
+
+ case SS_NATIVE_TO_ALIEN:
+
+ error = ss_nta(alien, indicator);
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_convert: NTA ss_nta error %d\n",error);
+#endif /* SS_DEBUG */
+ return(error);
+
+ }
+
+ default:
+
+ printf("ss_convert_struct: not expecting system_type %d\n", system_type);
+ break;
+
+ }
+ return(EINVAL);
+}
+
+/* note sockaddr_un linux unsigned short fam, 108 path
+ BSD uchar , uchar 104 */
+int
+ss_atn(alien, indicator)
+ char *alien;
+ int indicator;
+{
+int error;
+
+ switch (indicator) {
+
+ case SS_STRUCT_ARPREQ:
+ /* compatible */
+ return(0);
+
+ case SS_STRUCT_IFCONF:
+ /* compatible */
+ return(0);
+
+ case SS_STRUCT_IFREQ:
+ /* length OK - more unions - function dependent */
+ return(0);
+
+ case SS_STRUCT_ORTENTRY:
+ /* compatible */
+ return(0);
+
+ case SS_STRUCT_SOCKADDR:{
+ struct native_hdr {
+ u_char len;
+ u_char family;
+ };
+ union hdr_part {
+ struct native_hdr native;
+ u_short alien_family;
+ } hdr;
+
+ if(error = copyin((caddr_t)alien,(caddr_t)&hdr,sizeof(hdr)))
+ return(error);
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_atn:copyin 0x%x\n",hdr.alien_family);
+#endif /* SS_DEBUG */
+
+ if( hdr.alien_family < AF_MAX){
+ hdr.native.family = hdr.alien_family >> 8; /* 386 endianess */
+ /* OR LEN FOM A PARAM ? */
+ hdr.native.len = sizeof(struct sockaddr);
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_atn:copyout 0x%x\n",hdr.alien_family);
+#endif /* SS_DEBUG */
+ error = copyout((caddr_t)&hdr,(caddr_t)alien,sizeof(hdr));
+ return(error);
+ }
+ else {
+ printf("ss_atn: sa_family = %d\n", hdr.alien_family);
+ return(EINVAL);
+ }
+
+ }
+
+ case SS_STRUCT_SOCKNEWPROTO:
+ /* don't have */
+ printf("ss_atn: not expecting SS_STRUCT_SOCKNEWPROTO\n");
+ return(EINVAL);
+
+ default:
+ printf("ss_atn: not expecting case %d\n",indicator);
+ return(EINVAL);
+
+ }
+}
+
+/* note sockaddr_un linux unsigned short fam, 108 path
+ BSD uchar , uchar 104 */
+int
+ss_nta(alien, indicator)
+ char *alien;
+ int indicator;
+{
+int error;
+
+ switch (indicator) {
+
+ case SS_STRUCT_ARPREQ:
+ /* compatible */
+ return(0);
+
+ case SS_STRUCT_IFCONF:
+ /* compatible */
+ return(0);
+
+ case SS_STRUCT_IFREQ:
+ /* length OK - more unions - function dependent */
+ return(0);
+
+ case SS_STRUCT_ORTENTRY:
+ /* compatible */
+ return(0);
+
+ case SS_STRUCT_SOCKADDR:{
+ struct native_hdr {
+ u_char len;
+ u_char family;
+ };
+ union hdr_part {
+ struct native_hdr native;
+ u_short alien_family;
+ } hdr;
+
+ if(error = copyin((caddr_t)alien,(caddr_t)&hdr,sizeof(hdr)))
+ return(error);
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_nta:copyin 0x%x\n",hdr.alien_family);
+#endif /* SS_DEBUG */
+ hdr.alien_family = hdr.native.family;
+#ifdef SS_DEBUG
+ if(ss_debug > 1)
+ printf("ss_nta:copyout 0x%x\n",hdr.alien_family);
+#endif /* SS_DEBUG */
+ error = copyout((caddr_t)&hdr,(caddr_t)alien,sizeof(hdr));
+ return(error);
+ }
+
+ case SS_STRUCT_SOCKNEWPROTO:
+ /* don't have */
+ printf("ss_nta: not expecting SS_STRUCT_SOCKNEWPROTO\n");
+ return(EINVAL);
+
+ default:
+ printf("ss_nta: not expecting case %d\n",indicator);
+ return(EINVAL);
+
+ }
+}
OpenPOWER on IntegriCloud