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