ibcs2_socksys.c revision 3584
1/*-
2 * Copyright (c) 1994 Mostyn Lewis
3 * All rights reserved.
4 *
5 * This software is based on code which is:
6 * Copyright (c) 1994  Mike Jagdis (jaggy@purplet.demon.co.uk)
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer
13 *    in this position and unchanged.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 *    derived from this software withough specific prior written permission
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 *	$Id: ibcs2_socksys.c,v 1.2 1994/10/13 23:10:58 sos Exp $
32 */
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/filedesc.h>
37#include <sys/file.h>
38#include <sys/kernel.h>
39#include <sys/mbuf.h>
40#include <sys/protosw.h>
41#include <sys/socket.h>
42#include <sys/socketvar.h>
43#include <sys/ioctl.h>
44#include <sys/sockio.h>
45#include <sys/proc.h>
46#include <sys/exec.h>
47#include <sys/stat.h>
48#include <sys/syscall.h>
49#include <sys/sysent.h>
50#include <sys/malloc.h>
51#include <sys/un.h>
52#include <net/if.h>
53#include <net/if_arp.h>
54#include <net/route.h>
55#include <netinet/in.h>
56#include <vm/vm.h>
57#include <i386/ibcs2/ibcs2.h>
58#include <i386/ibcs2/ibcs2_socksys.h>
59
60/* Socksys pseudo driver entry points */
61
62int sockopen (dev_t dev, int mode, int devtype, struct proc *p);
63int sockioctl(dev_t dev, int cmd, caddr_t arg, int fflag, struct proc *p);
64int sockclose(dev_t dev, int flag, int mode, struct proc *p);
65
66/* Socksys internal functions */
67
68static void put_socket_fops(struct proc *p, int fd);
69static int  ss_fop_close(struct file *fp, struct proc *p);
70static int  ss_fop_ioctl(struct file*fp, int cmd, caddr_t arg, struct proc *p);
71static int  ss_syscall(caddr_t arg, struct proc *p);
72
73/*
74 *	This structure is setup on first usage. Its address is planted
75 *	into a socket's file structure fileops pointer after a successful
76 *	socket creation or accept.
77 */
78static struct fileops ss_socket_fops = {
79	NULL,	/* normal socket read */
80	NULL,	/* normal socket write */
81	NULL,	/* socksys ioctl */
82	NULL,	/* normal socket select */
83	NULL,	/* socksys close */
84};
85
86static int (*close_s)__P((struct file *fp, struct proc *p));
87static int (*ioctl_s)__P((struct file *fp, int cmd, caddr_t data, struct proc *p));
88
89int	ss_debug = 1;
90
91static int
92ss_syscall(arg, p)
93	caddr_t arg;
94	struct proc *p;
95{
96	int cmd;
97	int error;
98	int retval[2];
99
100	retval[0] = retval[1] = 0;
101	cmd = ((struct ss_call *)arg)->arg[0];
102
103#ifdef SS_DEBUG
104	if(ss_debug) {
105	static char *ss_syscall_strings[] = {
106		"0?", "accept", "bind", "connect", "getpeername",
107		"getsockname", "getsockopt", "listen", "recv(from)",
108		"recvfrom", "send(to)", "sendto", "setsockopt", "shutdown",
109		"socket", "select", "getipdomain", "setipdomain",
110		"adjtime", "setreuid", "setregid", "gettimeofday",
111		"settimeofday", "getitimer", "setitimer",
112	};
113
114	printf("ss_syscall: [%d] ",p->p_pid);
115	if(cmd < 0 || (cmd > CMD_SO_SETITIMER && cmd != CMD_SO_SS_DEBUG) )
116		printf("? ");
117	else {
118		if(cmd == CMD_SO_SS_DEBUG)
119			printf("%s ","ss_debug");
120		else
121			printf("%s ",ss_syscall_strings[cmd]);
122	}
123	printf("(%d) <0x%x,0x%x,0x%x,0x%x,0x%x,0x%x>\n",
124		cmd,
125		((struct ss_call *)arg)->arg[1],
126		((struct ss_call *)arg)->arg[2],
127		((struct ss_call *)arg)->arg[3],
128		((struct ss_call *)arg)->arg[4],
129		((struct ss_call *)arg)->arg[5],
130		((struct ss_call *)arg)->arg[6]);
131	}
132#endif	/* SS_DEBUG */
133
134	error = 0;
135
136	switch (cmd) {
137
138	case CMD_SO_SS_DEBUG:
139
140		ss_debug = ((struct ss_call *)arg)->arg[1];
141		break;
142
143	case CMD_SO_SOCKET: { /* NO CONV */
144
145#ifdef SS_DEBUG
146		if(ss_debug > 1)
147			printf("SO_SOCKET af in %d\n",
148				((struct ss_call *)arg)->arg[1]);
149#endif	/* SS_DEBUG */
150		((struct ss_call *)arg)->arg[1] = ss_convert(
151			af_whatevers,
152			&(((struct ss_call *)arg)->arg[1]),
153			0);
154#ifdef SS_DEBUG
155		if(ss_debug > 1) {
156			printf("SO_SOCKET af out %d\n",
157				((struct ss_call *)arg)->arg[1]);
158
159			printf("SO_SOCKET type in %d\n",
160				((struct ss_call *)arg)->arg[2]);
161		}
162#endif	/* SS_DEBUG */
163		((struct ss_call *)arg)->arg[2] = ss_convert(
164			type_whatevers,
165			&(((struct ss_call *)arg)->arg[2]),
166			0);
167#ifdef SS_DEBUG
168		if(ss_debug > 1)
169			printf("SO_SOCKET type out %d\n",
170				((struct ss_call *)arg)->arg[2]);
171#endif	/* SS_DEBUG */
172
173		SYSCALL(SYS_socket, 0, 0);
174
175#ifdef SS_DEBUG
176		if(ss_debug)
177			printf("ss_syscall: [%d] socket fd=%d\n",
178				p->p_pid, retval[0]);
179#endif	/* SS_DEBUG */
180		put_socket_fops(p,retval[0]);
181
182		break;
183	}
184
185	case CMD_SO_ACCEPT: { /* CONVERSION in arg 2 */
186
187		SYSCALL(SYS_accept, 2, SS_STRUCT_SOCKADDR);
188
189#ifdef SS_DEBUG
190		if(ss_debug)
191			printf("ss_syscall: [%d] accept fd=%d\n",
192				p->p_pid, retval[0]);
193#endif	/* SS_DEBUG */
194		put_socket_fops(p,retval[0]);
195
196		break;
197	}
198
199	case CMD_SO_BIND:
200		SYSCALL(SYS_bind, 2, SS_STRUCT_SOCKADDR);
201		break;
202
203	case CMD_SO_CONNECT: {
204		struct alien_sockaddr *sa;
205		unsigned short family;
206
207		/* Remap any INADDR_ANY (0.0.0.0) to localhost */
208
209		sa = (struct alien_sockaddr *)((struct ss_call *)arg)->arg[1];
210		if(error = copyin((caddr_t)&sa->sa_family,
211					(caddr_t)&family, sizeof(short)))
212			return(error);
213		if (family == AF_INET) {
214			unsigned long *addr;
215			unsigned long saddr;
216
217			addr = &(((struct alien_sockaddr_in *)sa)->sin_addr.s_addr);
218			if(error = copyin((caddr_t)addr, (caddr_t)&saddr, sizeof(long)))
219				return(error);
220			if (saddr == INADDR_ANY) {
221				/* 0x0100007f is 127.0.0.1 reversed */
222				saddr = 0x0100007f;
223				if(error = copyout((caddr_t)&saddr,
224						(caddr_t)addr, sizeof(long)))
225					return(error);
226#ifdef SS_DEBUG
227				if (ss_debug)
228					printf("ss_syscall: remapped INADDR_ANY to localhost\n");
229#endif	/* SS_DEBUG */
230			}
231		}
232		SYSCALL(SYS_connect, 2, SS_STRUCT_SOCKADDR);
233		break;
234	}
235
236	case CMD_SO_GETPEERNAME:
237		SYSCALL(SYS_getpeername, 2, SS_STRUCT_SOCKADDR);
238		break;
239
240	case CMD_SO_GETSOCKNAME:
241		SYSCALL(SYS_getsockname, 2, SS_STRUCT_SOCKADDR);
242		break;
243
244	case CMD_SO_GETSOCKOPT:
245		if(error = ss_getsockopt((caddr_t)(((int *)arg) + 1),retval,p))
246			return(error);
247		break;
248
249	case CMD_SO_LISTEN:
250		SYSCALL(SYS_listen, 0, 0);
251		break;
252
253	case CMD_SO_RECV:
254		((struct ss_call *)arg)->arg[5] = (int)((struct sockaddr *)NULL);
255		((struct ss_call *)arg)->arg[6] = 0;
256		SYSCALL(SYS_recvfrom, 0, 0);
257		break;
258
259	case CMD_SO_RECVFROM:
260		SYSCALL(SYS_recvfrom, 5, SS_STRUCT_SOCKADDR);
261		break;
262
263	case CMD_SO_SEND:
264		((struct ss_call *)arg)->arg[5] = (int)((struct sockaddr *)NULL);
265		((struct ss_call *)arg)->arg[6] = 0;
266		SYSCALL(SYS_sendto, 0, 0);
267		break;
268
269	case CMD_SO_SENDTO:
270		SYSCALL(SYS_sendto, 5, SS_STRUCT_SOCKADDR);
271		break;
272
273	case CMD_SO_SETSOCKOPT:
274		if(error = ss_setsockopt((caddr_t)(((int *)arg) + 1),retval,p))
275			return(error);
276
277	case CMD_SO_SHUTDOWN:
278		SYSCALL(SYS_shutdown, 0, 0);
279		break;
280
281	case CMD_SO_GETIPDOMAIN:
282		SYSCALL(SYS_getdomainname, 0, 0);
283		break;
284
285	case CMD_SO_SETIPDOMAIN: /* Note check on BSD utsname no change? */
286		SYSCALL(SYS_setdomainname, 0, 0);
287		break;
288
289	case CMD_SO_SETREUID:
290		SYSCALL(126/*SYS_setreuid*/, 0, 0);
291		break;
292
293	case CMD_SO_SETREGID:
294		SYSCALL(127/*SYS_setregid*/, 0, 0);
295		break;
296
297	case CMD_SO_GETTIME:
298		SYSCALL(SYS_gettimeofday, 0, 0);
299		break;
300
301	case CMD_SO_SETTIME:
302		SYSCALL(SYS_settimeofday, 0, 0);
303		break;
304
305	case CMD_SO_GETITIMER:
306		SYSCALL(SYS_getitimer, 0, 0);
307		break;
308
309	case CMD_SO_SETITIMER:
310		SYSCALL(SYS_setitimer, 0, 0);
311		break;
312
313	case CMD_SO_SELECT:
314		SYSCALL(SYS_select, 0, 0);
315		break;
316
317	case CMD_SO_ADJTIME:
318		SYSCALL(SYS_adjtime, 0, 0);
319		break;
320
321	default:
322		printf("ss_syscall: default 0x%x\n",cmd);
323		return (EINVAL);
324	}
325	IBCS2_MAGIC_RETURN;
326}
327
328
329static int
330ss_fop_ioctl(fp, cmd, arg, p)
331	struct file *fp;
332	int cmd;
333	caddr_t arg;
334	struct proc *p;
335{
336	int error;
337	int retval[2];
338
339#ifdef SS_DEBUG
340	if(ss_debug) {
341	static char **ioctl_strings;
342	int	fd;
343	struct filedesc *fdp;
344	unsigned int ioctl_type;
345	unsigned int ioctl_len;
346	char	cmd_type;
347	int	cmd_ordinal;
348
349	static char *ioctl_type_strings[] = {
350		"0?", "SS_IO", "SS_IOR", "3?", "SS_IOW", "5?", "SS_IOWR"
351	};
352	static char *ioctl_S_strings[] = {
353		"0?", "SIOCSHIWAT", "SIOCGHIWAT", "SIOCSLOWAT", "SIOCGLOWAT",
354		"SIOCATMARK", "SIOCSPGRP", "SIOCGPGRP", "FIONREAD",
355		"FIONBIO", "FIOASYNC", "SIOCPROTO", "SIOCGETNAME",
356		"SIOCGETPEER", "IF_UNITSEL", "SIOCXPROTO"
357	};
358	static char *ioctl_R_strings[] = {
359		"0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?",
360		"SIOCADDRT", "SIOCDELRT"
361	};
362	static char *ioctl_I_strings[] = {
363		"0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?",
364		"9?", "10?", "SIOCSIFADDR", "SIOCGIFADDR", "SIOCSIFDSTADDR",
365		"SIOCGIFDSTADDR", "SIOCSIFFLAGS", "SIOCGIFFLAGS",
366		"SIOCGIFCONF", "18?", "19?", "20?", "SIOCSIFMTU",
367		"SIOCGIFMTU", "23?", "24?", "25?", "SIOCIFDETACH",
368		"SIOCGENPSTATS", "28?", "SIOCX25XMT", "SS_SIOCX25RCV",
369		"SS_SIOCX25TBL", "SIOCGIFBRDADDR" ,"SIOCSIFBRDADDR",
370		"SIOCGIFNETMASK", "SIOCSIFNETMASK", "SIOCGIFMETRIC",
371		"SIOCSIFMETRIC", "SIOCSARP", "SIOCGARP", "SIOCDARP",
372		"SIOCSIFNAME", "SIOCGIFONEP", "SIOCSIFONEP ",
373		"44?", "45?", "46?", "47?", "48?", "49?", "50?", "51?",
374		"52?", "53?", "54?", "55?", "56?", "57?", "58?", "59?",
375		"60?", "61?", "62?", "63?", "64?", "SIOCGENADDR",
376		"SIOCSOCKSYS"
377	};
378
379	cmd_type = (cmd >> 8) & 0xff;
380	cmd_ordinal = cmd & 0xff;
381
382	switch (cmd_type) {
383
384	case 'S':
385		ioctl_strings = ioctl_S_strings;
386		if (cmd_ordinal > 15)
387			cmd_ordinal = -1;
388		break;
389
390	case 'R':
391		ioctl_strings = ioctl_R_strings;
392		if (cmd_ordinal > 10)
393			cmd_ordinal = -1;
394		break;
395
396	case 'I':
397		ioctl_strings = ioctl_I_strings;
398		if (cmd_ordinal > 66)
399			cmd_ordinal = -1;
400		break;
401
402	default:
403		cmd_type = '?';
404		break;
405	}
406	fdp = p->p_fd;
407	fd = -1;
408	while(++fd < NOFILE)
409		if ( fp == fdp->fd_ofiles[fd] )
410			break;
411
412	ioctl_type = (0xe0000000 & cmd) >> 29;
413	ioctl_len = (cmd >> 16) & SS_IOCPARM_MASK;
414
415	printf("ss_fop_ioctl: [%d] fd=%d ",p->p_pid, fd);
416	if(cmd_type != '?'){
417		if(cmd_ordinal != -1)
418			printf("%s %s('%c',%d,l=%d) ",ioctl_strings[cmd_ordinal],
419				ioctl_type_strings[ioctl_type],
420				cmd_type,
421				cmd_ordinal,
422				ioctl_len);
423		else {
424			cmd_ordinal = cmd & 0xff;
425			printf("[unknown ordinal %d] %s('%c',%d,l=%d) ",cmd_ordinal,
426				ioctl_type_strings[ioctl_type],
427				cmd_type,
428				cmd_ordinal,
429				ioctl_len);
430		}
431	}
432	else {
433		printf("? %s('%c',%d,l=%d) ",
434			ioctl_type_strings[ioctl_type],
435			cmd_type,
436			cmd_ordinal,
437			ioctl_len);
438	}
439
440	printf("0x%x (0x%x) <0x%x>\n",
441		fp, cmd, arg);
442	}
443#endif	/* SS_DEBUG */
444
445	/* No dogs allowed */
446
447	if(*(((int *)arg) - 3) != IBCS2_MAGIC_IN){
448		printf("ss_fop_ioctl: bad magic (sys_generic.c has no socksys mods?)\n");
449		return(EINVAL);
450	}
451
452	if(fp->f_type != DTYPE_SOCKET)
453		return (ENOTSOCK);
454
455	retval[0] = retval[1] = 0;
456
457
458	error = 0;
459
460	switch (cmd) {
461	case SS_SIOCSHIWAT:	/* set high watermark */
462	case SS_SIOCSLOWAT:	/* set low watermark */
463		break;		/* return value of 0 and no error */
464
465	case SS_SIOCGHIWAT:	/* get high watermark */
466	case SS_SIOCGLOWAT: 	/* get low watermark */
467		break;		/* return value of 0 and no error */
468
469	case SS_SIOCATMARK:	/* at oob mark */
470		IOCTL(SIOCATMARK);
471		break;
472
473	case SS_SIOCSPGRP:	/* set process group */
474		IOCTL(SIOCSPGRP);
475		break;
476	case SS_SIOCGPGRP:	/* get process group */
477		IOCTL(SIOCGPGRP);
478		break;
479
480	case FIONREAD:
481	case SS_FIONREAD:	/* get # bytes to read */
482		IOCTL(FIONREAD);
483		break;
484
485	case SS_FIONBIO:	/* set/clear non-blocking i/o */
486		IOCTL(FIONBIO);
487		break;
488
489	case SS_FIOASYNC:	/* set/clear async i/o */
490		IOCTL(FIOASYNC);
491		break;
492
493	case SS_SIOCADDRT:	/* add route - uses struct ortentry */
494		IOCTL(SIOCADDRT);
495		break;
496
497	case SS_SIOCDELRT:	/* delete route - uses struct ortentry */
498		IOCTL(SIOCDELRT);
499		break;
500
501	case SS_SIOCSIFADDR:	/* set ifnet address */
502		IOCTL(SIOCSIFADDR);
503		break;
504
505	case SS_SIOCGIFADDR:	/* get ifnet address */
506		IOCTL(SIOCGIFADDR);
507		break;
508
509	case SS_SIOCSIFDSTADDR:	/* set p-p address */
510		IOCTL(SIOCSIFDSTADDR);
511		break;
512
513	case SS_SIOCGIFDSTADDR:	/* get p-p address */
514		IOCTL(SIOCGIFDSTADDR);
515		break;
516
517	case SS_SIOCSIFFLAGS:	/* set ifnet flags */
518		IOCTL(SIOCSIFFLAGS);
519		break;
520
521	case SS_SIOCGIFFLAGS:	/* get ifnet flags */
522		IOCTL(SIOCGIFFLAGS);
523		break;
524
525	case SS_SIOCGIFCONF:	/* get ifnet ltst */
526		IOCTL(SIOCGIFCONF);
527		break;
528
529	case SS_SIOCGIFBRDADDR:	/* get broadcast addr */
530		IOCTL(SIOCGIFBRDADDR);
531		break;
532
533	case SS_SIOCSIFBRDADDR:	/* set broadcast addr */
534		IOCTL(SIOCSIFBRDADDR);
535		break;
536
537	case SS_SIOCGIFNETMASK:	/* get net addr mask */
538		IOCTL(SIOCGIFNETMASK);
539		break;
540
541	case SS_SIOCSIFNETMASK:	/* set net addr mask */
542		IOCTL(SIOCSIFNETMASK);
543		break;
544
545	case SS_SIOCGIFMETRIC:	/* get IF metric */
546		IOCTL(SIOCGIFMETRIC);
547		break;
548
549	case SS_SIOCSIFMETRIC:	/* set IF metric */
550		IOCTL(SIOCSIFMETRIC);
551		break;
552
553/*		FreeBSD 2.0 does not have socket ARPs */
554
555#ifdef	SIOCSARP
556
557	case SS_SIOCSARP:	/* set arp entry */
558		IOCTL(SIOCSARP);
559		break;
560
561	case SS_SIOCGARP:	/* get arp entry */
562		IOCTL(SIOCGARP);
563		break;
564
565	case SS_SIOCDARP:	/* delete arp entry */
566		IOCTL(SIOCDARP);
567		break;
568
569#else	/* SIOCSARP */
570
571	case SS_SIOCSARP:	/* set arp entry */
572		return(EINVAL);
573
574	case SS_SIOCGARP:	/* get arp entry */
575		return(EINVAL);
576
577	case SS_SIOCDARP:	/* delete arp entry */
578		return(EINVAL);
579
580#endif	/* SIOCSARP */
581
582	case SS_SIOCGENADDR:	/* Get ethernet addr XXX */
583		return (EINVAL);
584/*		return (error = ioctl_s(fp, SIOCGIFHWADDR, arg, p)); */
585
586	case SS_SIOCSIFMTU:	/* get if_mtu */
587		IOCTL(SIOCSIFMTU);
588		break;
589
590	case SS_SIOCGIFMTU:	/* set if_mtu */
591		IOCTL(SIOCGIFMTU);
592		break;
593
594	case SS_SIOCGETNAME:	/* getsockname XXX */
595		return (EINVAL);
596/*		return (ioctl_s(fp, SIOCGIFNAME, arg, p)); MMM */
597
598	case SS_SIOCGETPEER: {	/* getpeername */
599		struct moose {
600			int	fd;
601			caddr_t	asa;
602			int	*alen;
603			int	compat_43;
604		} args;
605
606		struct alien_sockaddr uaddr;
607		struct sockaddr nuaddr;
608		int nuaddr_len = sizeof(struct sockaddr);
609		struct filedesc *fdp;
610
611		if(fp->f_type != DTYPE_SOCKET)
612			return (ENOTSOCK);
613
614		bzero((caddr_t)&nuaddr, sizeof(struct sockaddr));
615		fdp = p->p_fd;
616		args.fd = -1;
617		while(++args.fd < NOFILE)
618			if ( fp == fdp->fd_ofiles[args.fd] )
619				break;
620		if(args.fd == NOFILE){
621			printf("ss_fop_ioctl: [%d] SS_SIOCGETPEER args.fd > NOFILE\n", p->p_pid);
622			return(EBADF);
623		}
624		args.asa = (caddr_t)&nuaddr;
625		args.alen = &nuaddr_len;
626		args.compat_43 = 0;
627		error = SYSCALLX(SYS_getpeername, &args);
628		if(error)
629			return(error);
630
631		bzero((caddr_t)&uaddr, sizeof(struct alien_sockaddr));
632		uaddr.sa_family = (unsigned short)nuaddr.sa_family;
633		bcopy(&nuaddr.sa_data, &uaddr.sa_data, __ALIEN_SOCK_SIZE__ - sizeof(unsigned short));
634
635		error = copyout((caddr_t)&uaddr, (caddr_t)arg, sizeof(struct alien_sockaddr));
636		return error;
637	}
638
639	default:
640		printf("ss_fop_ioctl: [%d] %lx unknown ioctl 0x%x, 0x%lx\n",
641				p->p_pid, (unsigned long)fp,
642				cmd, (unsigned long)arg);
643		return (EINVAL);
644	}
645	IBCS2_MAGIC_RETURN;
646}
647
648int
649sockioctl(dev, cmd, arg, fflag, p)
650	dev_t dev;
651	int cmd;
652	caddr_t arg;
653	int fflag;
654	struct proc *p;
655{
656	int error;
657	int retval[2];
658
659#ifdef SS_DEBUG
660	if(ss_debug) {
661	char	cmd_type;
662	int	cmd_ordinal;
663	static char **ioctl_strings;
664	unsigned int ioctl_type;
665	unsigned int ioctl_len;
666
667	static char *ioctl_type_strings[] = {
668		"NIOCxx", "SS_IO", "SS_IOR", "3?", "SS_IOW", "5?", "SS_IOWR"
669	};
670	static char *ioctl_S_strings[] = {
671		"0?", "SIOCSHIWAT", "SIOCGHIWAT", "SIOCSLOWAT", "SIOCGLOWAT",
672		"SIOCATMARK", "SIOCSPGRP", "SIOCGPGRP", "FIONREAD",
673		"FIONBIO", "FIOASYNC", "SIOCPROTO", "SIOCGETNAME",
674		"SIOCGETPEER", "IF_UNITSEL", "SIOCXPROTO"
675	};
676	static char *ioctl_R_strings[] = {
677		"0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?",
678		"SIOCADDRT", "SIOCDELRT"
679	};
680	static char *ioctl_I_strings[] = {
681		"0?", "1?", "2?", "3?", "4?", "5?", "6?", "7?", "8?",
682		"9?", "10?", "SIOCSIFADDR", "SIOCGIFADDR", "SIOCSIFDSTADDR",
683		"SIOCGIFDSTADDR", "SIOCSIFFLAGS", "SIOCGIFFLAGS",
684		"SIOCGIFCONF", "18?", "19?", "20?", "SIOCSIFMTU",
685		"SIOCGIFMTU", "23?", "24?", "25?", "SIOCIFDETACH",
686		"SIOCGENPSTATS", "28?", "SIOCX25XMT", "SS_SIOCX25RCV",
687		"SS_SIOCX25TBL", "SIOCGIFBRDADDR" ,"SIOCSIFBRDADDR",
688		"SIOCGIFNETMASK", "SIOCSIFNETMASK", "SIOCGIFMETRIC",
689		"SIOCSIFMETRIC", "SIOCSARP", "SIOCGARP", "SIOCDARP",
690		"SIOCSIFNAME", "SIOCGIFONEP", "SIOCSIFONEP ",
691		"44?", "45?", "46?", "47?", "48?", "49?", "50?", "51?",
692		"52?", "53?", "54?", "55?", "56?", "57?", "58?", "59?",
693		"60?", "61?", "62?", "63?", "64?", "SIOCGENADDR",
694		"SIOCSOCKSYS"
695	};
696	static char *ioctl_NIOC_strings[] = {
697		"0?", "NIOCNFSD", "NIOCOLDGETFH", "NIOCASYNCD",
698		"NIOCSETDOMNAM", "NIOCGETDOMNAM", "NIOCCLNTHAND",
699		"NIOCEXPORTFS", "NIOCGETFH", "NIOCLSTAT"
700	};
701
702	cmd_ordinal = cmd & 0xff;
703	cmd_type = (cmd >> 8) & 0xff;
704	switch (cmd_type) {
705
706	case   0:
707		ioctl_strings = ioctl_NIOC_strings;
708		cmd_type = ' ';
709		if (cmd_ordinal > 9)
710			cmd_ordinal = -1;
711		break;
712
713	case 'S':
714		ioctl_strings = ioctl_S_strings;
715		if (cmd_ordinal > 15)
716			cmd_ordinal = -1;
717		break;
718
719	case 'R':
720		ioctl_strings = ioctl_R_strings;
721		if (cmd_ordinal > 10)
722			cmd_ordinal = -1;
723		break;
724
725	case 'I':
726		ioctl_strings = ioctl_I_strings;
727		if (cmd_ordinal > 66)
728			cmd_ordinal = -1;
729		break;
730
731	default:
732		cmd_type = '?';
733			break;
734
735	}
736	ioctl_type = (0xe0000000 & cmd) >> 29;
737	ioctl_len = (cmd >> 16) & SS_IOCPARM_MASK;
738
739	printf("sockioctl: [%d] ",p->p_pid);
740	if(cmd_type != '?'){
741		if(cmd_ordinal != -1)
742			printf("%s %s('%c',%d,l=%d) ",ioctl_strings[cmd_ordinal],
743				ioctl_type_strings[ioctl_type],
744				cmd_type,
745				cmd_ordinal,
746				ioctl_len);
747		else {
748			cmd_ordinal = cmd & 0xff;
749			printf("[unknown ordinal %d] %s('%c',%d,l=%d) ",cmd_ordinal,
750				ioctl_type_strings[ioctl_type],
751				cmd_type,
752				cmd_ordinal,
753				ioctl_len);
754		}
755	}
756	else {
757		printf("? %s('%c',%d,l=%d) ",
758			ioctl_type_strings[ioctl_type],
759			cmd_type,
760			cmd_ordinal,
761			ioctl_len);
762	}
763
764	printf("0x%x (0x%x) <0x%x>\n",
765		dev, cmd, arg);
766	}
767#endif	/* SS_DEBUG */
768
769	if(*(((int *)arg) - 3) != IBCS2_MAGIC_IN){
770		printf("sockioctl: bad magic (sys_generic.c has no socksys mods?)\n");
771		return(EINVAL);
772	}
773
774	switch (cmd) {
775
776	case SS_SIOCSOCKSYS:		/* ss syscall */
777		return ss_syscall(arg, p);
778
779	/* NIOCxx: These ioctls are really just integers
780	 *	   (no other information to go on).
781	 */
782
783	case NIOCSETDOMNAM: {
784		struct sgdomarg domargs;
785
786		if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&domargs, sizeof(struct sgdomarg)))
787			return(error);
788
789		arg = (caddr_t)&domargs;
790		SYSCALL_N(SYS_setdomainname, 0, 0);
791		break;
792	}
793
794	case NIOCGETDOMNAM: {
795		struct sgdomarg domargs;
796
797		if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&domargs, sizeof(struct sgdomarg)))
798			return(error);
799
800		arg = (caddr_t)&domargs;
801		SYSCALL_N(SYS_getdomainname, 0, 0);
802		break;
803	}
804
805	case NIOCLSTAT: {
806		struct lstatarg st;
807
808		if(error = copyin((caddr_t)*((caddr_t *)arg), (caddr_t)&st, sizeof(struct lstatarg)))
809			return(error);
810
811		/* DO WE HAVE A FOREIGN LSTAT */
812/*		return mumbo_lstat(st.fname, st.statb); */
813		return (EINVAL);
814	}
815
816	case NIOCNFSD:
817	case NIOCOLDGETFH:
818	case NIOCASYNCD:
819	case NIOCCLNTHAND:
820	case NIOCEXPORTFS:
821	case NIOCGETFH:
822		return (EINVAL);
823
824
825	case SS_IF_UNITSEL:		/* set unit number */
826	case SS_SIOCXPROTO:		/* empty proto table */
827
828	case SS_SIOCIFDETACH:		/* detach interface */
829	case SS_SIOCGENPSTATS:		/* get ENP stats */
830
831	case SS_SIOCSIFNAME:		/* set interface name */
832	case SS_SIOCGIFONEP:		/* get one-packet params */
833	case SS_SIOCSIFONEP:		/* set one-packet params */
834
835	case SS_SIOCPROTO:		/* link proto */
836	case SS_SIOCX25XMT:
837	case SS_SIOCX25RCV:
838	case SS_SIOCX25TBL:
839
840		printf("sockioctl: [%d] unsupported ioctl 0x%x , 0x%lx\n",
841			p->p_pid,
842			cmd, (unsigned long)arg);
843		return (EINVAL);
844
845	default:
846		printf("sockioctl: [%d] unknown ioctl 0x%x , 0x%lx\n",
847			p->p_pid,
848			cmd, (unsigned long)arg);
849		return (EINVAL);
850	}
851	IBCS2_MAGIC_RETURN;
852}
853
854
855int sockopen(dev, mode, devtype, p)
856	dev_t dev;
857	int mode;
858	int devtype;
859	struct proc *p;
860{
861
862#ifdef SS_DEBUG
863	if(ss_debug)
864		printf("sockopen: [%d] 0x%x\n", p->p_pid, dev);
865#endif	/* SS_DEBUG */
866
867	/* minor = 0 is the socksys device itself. No special handling
868	 *           will be needed as it is controlled by the application
869	 *           via ioctls.
870	 */
871	if (minor(dev) == 0)
872		return 0;
873
874	/* minor = 1 is the spx device. This is the client side of a
875	 *           streams pipe to the X server. Under SCO and friends
876	 *           the library code messes around setting the connection
877	 *           up itself. We do it ourselves - this means we don't
878	 *           need to worry about the implementation of the server
879	 *           side (/dev/X0R - which must exist but can be a link
880	 *           to /dev/null) nor do we need to actually implement
881	 *           getmsg/putmsg.
882	 */
883{ /* SPX */
884	int fd, error, args[3];
885	int retval[2];
886#define SUN_LEN(su) \
887        (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) + 1
888	struct sockaddr_un *Xaddr = (struct sockaddr_un *)UA_ALLOC();
889	retval[0] = retval[1] = 0;
890#ifdef SS_DEBUG
891	if(ss_debug)
892		printf("sockopen: SPX: [%d] opening\n", p->p_pid);
893#endif	/* SS_DEBUG */
894
895	/* Grab a socket. */
896#ifdef SS_DEBUG
897	if(ss_debug)
898		printf("sockopen: SPX: [%d] get a unix domain socket\n",
899					p->p_pid);
900#endif	/* SS_DEBUG */
901	args[0] = AF_UNIX;
902	args[1] = SOCK_STREAM;
903	args[2] = 0;
904	error = SYSCALLX(SYS_socket, args);
905	if (error)
906		return error;
907	fd = retval[0];
908	if(fd < 1) {
909		printf("sockopen: SPX: [%d] unexpected fd of %d\n",
910			 p->p_pid, fd);
911		return(EOPNOTSUPP); /* MRL whatever */
912	}
913
914	/* Connect the socket to X. */
915#ifdef SS_DEBUG
916	if(ss_debug)
917		printf("sockopen: SPX: [%d] connect to /tmp/X11-unix/X0\n",
918			p->p_pid);
919#endif	/* SS_DEBUG */
920	args[0] = fd;
921	Xaddr->sun_family = AF_UNIX;
922	copyout("/tmp/.X11-unix/X0", Xaddr->sun_path, 18);
923	Xaddr->sun_len = SUN_LEN(Xaddr);
924	args[1] = (int)Xaddr;
925	args[2] = sizeof(struct sockaddr_un);
926	error = SYSCALLX(SYS_connect, args);
927	if (error) {
928		(void)SYSCALLX(SYS_close, &fd);
929		return error;
930	}
931
932	put_socket_fops(p,fd);
933
934	return 0;
935} /* SPX */
936}
937
938
939int sockclose(dev, flag, mode, p)
940	dev_t dev;
941	int flag;
942	int mode;
943	struct proc *p;
944{
945#ifdef SS_DEBUG
946	if(ss_debug)
947		printf("sockclose: [%d] 0x%x\n", p->p_pid, dev);
948#endif	/* SS_DEBUG */
949	return(0);
950}
951
952static
953int ss_fop_close(struct file *fp, struct proc *p)
954{
955
956#ifdef SS_DEBUG
957int	fd;
958struct filedesc *fdp;
959
960	if(ss_debug){
961		fdp = p->p_fd;
962		fd = -1;
963		while(++fd < NOFILE)
964				if ( fp == fdp->fd_ofiles[fd] )
965					break;
966		printf("ss_fop_close: [%d] fd=%d ", p->p_pid, fd);
967	}
968#endif	/* SS_DEBUG */
969
970	if(fp->f_type == DTYPE_SOCKET) {
971#ifdef SS_DEBUG
972		if(ss_debug)
973			printf("is a socket\n");
974#endif	/* SS_DEBUG */
975		return(close_s(fp, p));
976	}
977	else {
978#ifdef SS_DEBUG
979		if(ss_debug)
980			printf("is not a socket\n");
981#endif	/* SS_DEBUG */
982		return(ENOTSOCK);
983	}
984}
985
986void put_socket_fops(struct proc *p, int fd)
987{
988struct filedesc *fdp;
989struct file *fp;
990
991	fdp = p->p_fd;
992	fp = fdp->fd_ofiles[fd];
993	if (ss_socket_fops.fo_ioctl != fp->f_ops->fo_ioctl) {
994		bcopy(fp->f_ops, &ss_socket_fops, sizeof(struct fileops));
995		ioctl_s = ss_socket_fops.fo_ioctl; /* save standard ioctl */
996		close_s = ss_socket_fops.fo_close; /* save standard close */
997		ss_socket_fops.fo_ioctl = ss_fop_ioctl;
998		ss_socket_fops.fo_close = ss_fop_close;
999	}
1000	fp->f_ops = &ss_socket_fops;
1001
1002	return;
1003}
1004
1005int	ss_SYSCALL(n,convert_arg,indicator,arg,p,retval)
1006	int	n;		/* syscall ordinal */
1007	int	convert_arg;	/* if not 0, argument to convert */
1008	int	indicator;	/* type of argument to convert */
1009	int	*arg;		/* address of alien arg */
1010	struct	proc *p;
1011	int	*retval;
1012{
1013int	error;
1014int	rc;
1015
1016	if(convert_arg){
1017		if(rc = ss_convert_struct( (caddr_t)*(arg + convert_arg),
1018					indicator,
1019					SS_ALIEN_TO_NATIVE))
1020			return(rc);
1021
1022		error = (*sysent[n].sy_call)(p, arg + 1, retval);
1023		rc = ss_convert_struct( (caddr_t)*(arg + convert_arg),
1024					indicator,
1025					SS_NATIVE_TO_ALIEN);
1026#ifdef SS_DEBUG
1027		if(ss_debug)
1028			printf("ss_SYSCALL: [%d] error=%d, rc=%d\n",
1029						p->p_pid, error, rc);
1030#endif /* SS_DEBUG */
1031	}
1032	else {
1033		rc = 0;
1034		error = (*sysent[n].sy_call)(p, arg + 1, retval);
1035#ifdef SS_DEBUG
1036		if(ss_debug)
1037			printf("ss_SYSCALL: [%d] error=%d\n",p->p_pid, error);
1038#endif /* SS_DEBUG */
1039	}
1040
1041	return(error ? error : rc);
1042}
1043
1044int	ss_IOCTL(fp, cmd, arg, p)
1045	struct file *fp;
1046	int	cmd;
1047	int	*arg;		/* address of alien arg */
1048	struct	proc *p;
1049{
1050int	error, rc;
1051int	these[2];
1052char	cmd_type;
1053int	cmd_ordinal;
1054int	indicator;
1055
1056	cmd_type = (cmd >> 8) & 0xff;
1057	cmd_ordinal = cmd & 0xff;
1058	these[0] = cmd_type;
1059	these[1] = cmd_ordinal;
1060#ifdef SS_DEBUG
1061	if(ss_debug > 1)
1062		printf("ss_IOCTL: calling ss_convert with %d(%c) %d\n",
1063				these[0],these[0],these[1]);
1064#endif /* SS_DEBUG */
1065	indicator = ss_convert( struct_whatevers, these, 0);
1066#ifdef SS_DEBUG
1067	if(ss_debug > 1)
1068		printf("ss_IOCTL: ss_convert returns indicator %d\n",indicator);
1069#endif /* SS_DEBUG */
1070	if(indicator){
1071		error = ss_convert_struct((caddr_t)*(arg + 2),
1072					  indicator,
1073					  SS_ALIEN_TO_NATIVE);
1074#ifdef SS_DEBUG
1075		if(ss_debug > 1)
1076			printf("ss_IOCTL: ss_convert_struct returns %d\n",error);
1077#endif /* SS_DEBUG */
1078		if(error)
1079			return(error);
1080		/* change len in ioctl now - in the general case */
1081		error = ioctl_s(fp, cmd, (caddr_t)arg, p);
1082		rc = ss_convert_struct( (caddr_t)*(arg + 2),
1083					indicator,
1084					SS_NATIVE_TO_ALIEN);
1085#ifdef SS_DEBUG
1086		if(ss_debug)
1087			printf("ss_IOCTL: [%d] error=%d, rc=%d\n",p->p_pid,
1088						error, rc);
1089#endif /* SS_DEBUG */
1090	}
1091	else {
1092		rc = 0;
1093		error = ioctl_s(fp, cmd, (caddr_t)arg, p);
1094#ifdef SS_DEBUG
1095		if(ss_debug)
1096			printf("ss_IOCTL: [%d] error=%d\n",p->p_pid, error);
1097#endif /* SS_DEBUG */
1098	}
1099
1100	return(error ? error : rc);
1101}
1102
1103
1104struct ss_socketopt_args {
1105        int     s;
1106	int     level;
1107	int     name;
1108	caddr_t val;
1109	int     valsize;
1110};
1111
1112int
1113ss_setsockopt(arg, ret, p)
1114	struct ss_socketopt_args  *arg;
1115	int	*ret;
1116	struct	proc *p;
1117{
1118	int error, optname;
1119	int retval[2];
1120
1121	if (arg->level != 0xffff) /* FreeBSD, SCO and ? */
1122		return (ENOPROTOOPT);
1123
1124	optname = ss_convert(sopt_whatevers, &arg->name, 0);
1125
1126	switch (optname) {
1127
1128	case SO_ACCEPTCONN:
1129	case SO_BROADCAST:
1130	case SO_DEBUG:
1131	case SO_DONTROUTE:
1132	case SO_LINGER:
1133	case SO_KEEPALIVE:
1134	case SO_OOBINLINE:
1135	case SO_RCVBUF:
1136	case SO_RCVLOWAT:
1137	case SO_RCVTIMEO:
1138	case SO_REUSEADDR:
1139	case SO_SNDBUF:
1140	case SO_SNDLOWAT:
1141	case SO_SNDTIMEO:
1142	case SO_USELOOPBACK:
1143		error = SYSCALLX(SYS_setsockopt, arg);
1144		*ret = retval[0];
1145		*(ret + 1) = retval[1];
1146		return(error);
1147
1148	case SO_ERROR:
1149	case SO_IMASOCKET:
1150	case SO_NO_CHECK:
1151	case SO_ORDREL:
1152	case SO_PRIORITY:
1153	case SO_PROTOTYPE:
1154	case SO_TYPE:
1155		return (ENOPROTOOPT);
1156
1157	}
1158
1159	return (ENOPROTOOPT);
1160}
1161
1162
1163int
1164ss_getsockopt(arg, ret, p)
1165	struct ss_socketopt_args  *arg;
1166	int	*ret;
1167	struct	proc *p;
1168{
1169	int error, optname;
1170	int retval[2];
1171
1172	if (arg->level != 0xffff) /* FreeBSD, SCO and ? */
1173		return (ENOPROTOOPT);
1174
1175	optname = ss_convert(sopt_whatevers, &arg->name, 0);
1176
1177	switch (optname) {
1178
1179	case SO_ACCEPTCONN:
1180	case SO_BROADCAST:
1181	case SO_DEBUG:
1182	case SO_DONTROUTE:
1183	case SO_ERROR:
1184	case SO_KEEPALIVE:
1185	case SO_LINGER:
1186	case SO_OOBINLINE:
1187	case SO_RCVBUF:
1188	case SO_RCVLOWAT:
1189	case SO_RCVTIMEO:
1190	case SO_REUSEADDR:
1191	case SO_SNDBUF:
1192	case SO_SNDLOWAT:
1193	case SO_SNDTIMEO:
1194	case SO_TYPE:
1195	case SO_USELOOPBACK:
1196		error = SYSCALLX(SYS_getsockopt, arg);
1197		*ret = retval[0];
1198		*(ret + 1) = retval[1];
1199		return(error);
1200
1201
1202	case SO_PROTOTYPE: {
1203		int	value = 0;
1204
1205		error = copyout((caddr_t)&value, (caddr_t)arg->s, sizeof(int));
1206			return(error);
1207	}
1208
1209
1210	case SO_IMASOCKET: {
1211		int	value = 1;
1212
1213		error = copyout((caddr_t)&value, (caddr_t)arg->s, sizeof(int));
1214			return(error);
1215	}
1216
1217	case SO_NO_CHECK:
1218	case SO_ORDREL:
1219	case SO_PRIORITY:
1220		return (ENOPROTOOPT);
1221	}
1222
1223	return (ENOPROTOOPT);
1224}
1225
1226#define	SS_CONVERT
1227int	system_type = SS_FREEBSD; /* FreeBSD */
1228
1229int
1230ss_convert(what, this, otherwise)
1231	struct whatever **what;
1232	int *this;
1233	int otherwise;
1234{
1235	struct whatever *specific;
1236
1237	if(!(specific = what[system_type]))
1238		return *this;
1239
1240	for (; specific->from != -1; specific++)
1241		if(specific->from <= *this && *this <= specific->to)
1242			if(specific->from == specific->to){
1243				if(specific->more){
1244					specific = specific->more;
1245					this++;
1246					continue;
1247				}
1248				else {
1249					return((int)specific->conversion);
1250				}
1251			}
1252			else {
1253				return(specific->conversion ? (
1254				       specific->all_the_same ? (int)specific->conversion : specific->conversion[*this - specific->from] ) : *this);
1255			}
1256
1257	return otherwise;
1258}
1259
1260/*	Returns	0 - no conversion, no pointer modification
1261		1 - converted, relevant pointer modification
1262	       -1 - error
1263 */
1264int
1265ss_convert_struct(alien, indicator, direction)
1266	char	*alien;
1267	int	indicator;
1268	int	direction;
1269{
1270int	error, len;
1271
1272	switch (system_type) {
1273
1274	case SS_FREEBSD:
1275		return(0);
1276	case SS_SYSVR4:
1277	case SS_SYSVR3:
1278	case SS_SCO_32:
1279	case SS_WYSE_321:
1280	case SS_ISC:
1281	case SS_LINUX:
1282
1283		switch(direction){
1284
1285		case SS_ALIEN_TO_NATIVE:
1286
1287		error = ss_atn(alien, indicator);
1288#ifdef SS_DEBUG
1289		if(ss_debug > 1)
1290			printf("ss_convert: ATN ss_atn error %d\n",error);
1291#endif /* SS_DEBUG */
1292		return(error);
1293
1294		case SS_NATIVE_TO_ALIEN:
1295
1296		error = ss_nta(alien, indicator);
1297#ifdef SS_DEBUG
1298		if(ss_debug > 1)
1299			printf("ss_convert: NTA ss_nta error %d\n",error);
1300#endif /* SS_DEBUG */
1301		return(error);
1302
1303		}
1304
1305	default:
1306
1307	printf("ss_convert_struct: not expecting system_type %d\n", system_type);
1308	break;
1309
1310	}
1311	return(EINVAL);
1312}
1313
1314/* note sockaddr_un linux unsigned short fam,  108 path
1315   BSD uchar , uchar 104 */
1316int
1317ss_atn(alien, indicator)
1318	char	*alien;
1319	int	indicator;
1320{
1321int	error;
1322
1323	switch (indicator) {
1324
1325	case SS_STRUCT_ARPREQ:
1326		/* compatible */
1327		return(0);
1328
1329	case SS_STRUCT_IFCONF:
1330		/* compatible */
1331		return(0);
1332
1333	case SS_STRUCT_IFREQ:
1334		/* length OK - more unions - function dependent */
1335		return(0);
1336
1337	case SS_STRUCT_ORTENTRY:
1338		/* compatible */
1339		return(0);
1340
1341	case SS_STRUCT_SOCKADDR:{
1342		struct native_hdr {
1343			u_char	len;
1344			u_char	family;
1345		};
1346		union hdr_part {
1347			struct native_hdr native;
1348			u_short alien_family;
1349		} hdr;
1350
1351		if(error = copyin((caddr_t)alien,(caddr_t)&hdr,sizeof(hdr)))
1352			return(error);
1353#ifdef SS_DEBUG
1354		if(ss_debug > 1)
1355			printf("ss_atn:copyin 0x%x\n",hdr.alien_family);
1356#endif /* SS_DEBUG */
1357
1358		if( hdr.alien_family < AF_MAX){
1359			hdr.native.family = hdr.alien_family >> 8; /* 386 endianess */
1360			/* OR LEN FOM A PARAM ? */
1361			hdr.native.len = sizeof(struct sockaddr);
1362#ifdef SS_DEBUG
1363		if(ss_debug > 1)
1364			printf("ss_atn:copyout 0x%x\n",hdr.alien_family);
1365#endif /* SS_DEBUG */
1366			error = copyout((caddr_t)&hdr,(caddr_t)alien,sizeof(hdr));
1367			return(error);
1368		}
1369		else {
1370			printf("ss_atn: sa_family = %d\n", hdr.alien_family);
1371			return(EINVAL);
1372		}
1373
1374	}
1375
1376	case SS_STRUCT_SOCKNEWPROTO:
1377		/* don't have */
1378		printf("ss_atn: not expecting SS_STRUCT_SOCKNEWPROTO\n");
1379		return(EINVAL);
1380
1381	default:
1382		printf("ss_atn: not expecting case %d\n",indicator);
1383		return(EINVAL);
1384
1385	}
1386}
1387
1388/* note sockaddr_un linux unsigned short fam,  108 path
1389   BSD uchar , uchar 104 */
1390int
1391ss_nta(alien, indicator)
1392	char	*alien;
1393	int	indicator;
1394{
1395int	error;
1396
1397	switch (indicator) {
1398
1399	case SS_STRUCT_ARPREQ:
1400		/* compatible */
1401		return(0);
1402
1403	case SS_STRUCT_IFCONF:
1404		/* compatible */
1405		return(0);
1406
1407	case SS_STRUCT_IFREQ:
1408		/* length OK - more unions - function dependent */
1409		return(0);
1410
1411	case SS_STRUCT_ORTENTRY:
1412		/* compatible */
1413		return(0);
1414
1415	case SS_STRUCT_SOCKADDR:{
1416		struct native_hdr {
1417			u_char	len;
1418			u_char	family;
1419		};
1420		union hdr_part {
1421			struct native_hdr native;
1422			u_short alien_family;
1423		} hdr;
1424
1425		if(error = copyin((caddr_t)alien,(caddr_t)&hdr,sizeof(hdr)))
1426			return(error);
1427#ifdef SS_DEBUG
1428		if(ss_debug > 1)
1429			printf("ss_nta:copyin 0x%x\n",hdr.alien_family);
1430#endif /* SS_DEBUG */
1431		hdr.alien_family = hdr.native.family;
1432#ifdef SS_DEBUG
1433		if(ss_debug > 1)
1434			printf("ss_nta:copyout 0x%x\n",hdr.alien_family);
1435#endif /* SS_DEBUG */
1436		error = copyout((caddr_t)&hdr,(caddr_t)alien,sizeof(hdr));
1437		return(error);
1438	}
1439
1440	case SS_STRUCT_SOCKNEWPROTO:
1441		/* don't have */
1442		printf("ss_nta: not expecting SS_STRUCT_SOCKNEWPROTO\n");
1443		return(EINVAL);
1444
1445	default:
1446		printf("ss_nta: not expecting case %d\n",indicator);
1447		return(EINVAL);
1448
1449	}
1450}
1451