1/* $Id: sunos_ioctl.c,v 1.1.1.1 2008/10/15 03:26:18 james26_jang Exp $
2 * sunos_ioctl.c: The Linux Operating system: SunOS ioctl compatibility.
3 *
4 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#include <asm/uaccess.h>
9
10#include <linux/sched.h>
11#include <linux/errno.h>
12#include <linux/string.h>
13#include <linux/termios.h>
14#include <linux/ioctl.h>
15#include <linux/route.h>
16#include <linux/sockios.h>
17#include <linux/if.h>
18#include <linux/netdevice.h>
19#include <linux/if_arp.h>
20#include <linux/fs.h>
21#include <linux/mm.h>
22#include <linux/smp.h>
23#include <linux/smp_lock.h>
24#include <linux/file.h>
25#include <asm/kbio.h>
26
27
28/* NR_OPEN is now larger and dynamic in recent kernels. */
29#define SUNOS_NR_OPEN	256
30
31extern asmlinkage int sys_ioctl(unsigned int, unsigned int, unsigned long);
32extern asmlinkage int sys_setsid(void);
33
34asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg)
35{
36	int ret = -EBADF;
37
38	if (fd >= SUNOS_NR_OPEN || !fcheck(fd))
39		goto out;
40
41	/* First handle an easy compat. case for tty ldisc. */
42	if(cmd == TIOCSETD) {
43		int *p, ntty = N_TTY, tmp;
44		mm_segment_t oldfs;
45
46		p = (int *) arg;
47		ret = -EFAULT;
48		if(get_user(tmp, p))
49			goto out;
50		if(tmp == 2) {
51			oldfs = get_fs();
52			set_fs(KERNEL_DS);
53			ret = sys_ioctl(fd, cmd, (int) &ntty);
54			set_fs(oldfs);
55			ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
56			goto out;
57		}
58	}
59
60	/* Binary compatibility is good American knowhow fuckin' up. */
61	if(cmd == TIOCNOTTY) {
62		ret = sys_setsid();
63		goto out;
64	}
65
66	/* SunOS networking ioctls. */
67	switch (cmd) {
68	case _IOW('r', 10, struct rtentry):
69		ret = sys_ioctl(fd, SIOCADDRT, arg);
70		goto out;
71	case _IOW('r', 11, struct rtentry):
72		ret = sys_ioctl(fd, SIOCDELRT, arg);
73		goto out;
74	case _IOW('i', 12, struct ifreq):
75		ret = sys_ioctl(fd, SIOCSIFADDR, arg);
76		goto out;
77	case _IOWR('i', 13, struct ifreq):
78		ret = sys_ioctl(fd, SIOCGIFADDR, arg);
79		goto out;
80	case _IOW('i', 14, struct ifreq):
81		ret = sys_ioctl(fd, SIOCSIFDSTADDR, arg);
82		goto out;
83	case _IOWR('i', 15, struct ifreq):
84		ret = sys_ioctl(fd, SIOCGIFDSTADDR, arg);
85		goto out;
86	case _IOW('i', 16, struct ifreq):
87		ret = sys_ioctl(fd, SIOCSIFFLAGS, arg);
88		goto out;
89	case _IOWR('i', 17, struct ifreq):
90		ret = sys_ioctl(fd, SIOCGIFFLAGS, arg);
91		goto out;
92	case _IOW('i', 18, struct ifreq):
93		ret = sys_ioctl(fd, SIOCSIFMEM, arg);
94		goto out;
95	case _IOWR('i', 19, struct ifreq):
96		ret = sys_ioctl(fd, SIOCGIFMEM, arg);
97		goto out;
98	case _IOWR('i', 20, struct ifconf):
99		ret = sys_ioctl(fd, SIOCGIFCONF, arg);
100		goto out;
101	case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */
102		ret = sys_ioctl(fd, SIOCSIFMTU, arg);
103		goto out;
104	case _IOWR('i', 22, struct ifreq): /* SIOCGIFMTU */
105		ret = sys_ioctl(fd, SIOCGIFMTU, arg);
106		goto out;
107
108	case _IOWR('i', 23, struct ifreq):
109		ret = sys_ioctl(fd, SIOCGIFBRDADDR, arg);
110		goto out;
111	case _IOW('i', 24, struct ifreq):
112		ret = sys_ioctl(fd, SIOCSIFBRDADDR, arg);
113		goto out;
114	case _IOWR('i', 25, struct ifreq):
115		ret = sys_ioctl(fd, SIOCGIFNETMASK, arg);
116		goto out;
117	case _IOW('i', 26, struct ifreq):
118		ret = sys_ioctl(fd, SIOCSIFNETMASK, arg);
119		goto out;
120	case _IOWR('i', 27, struct ifreq):
121		ret = sys_ioctl(fd, SIOCGIFMETRIC, arg);
122		goto out;
123	case _IOW('i', 28, struct ifreq):
124		ret = sys_ioctl(fd, SIOCSIFMETRIC, arg);
125		goto out;
126
127	case _IOW('i', 30, struct arpreq):
128		ret = sys_ioctl(fd, SIOCSARP, arg);
129		goto out;
130	case _IOWR('i', 31, struct arpreq):
131		ret = sys_ioctl(fd, SIOCGARP, arg);
132		goto out;
133	case _IOW('i', 32, struct arpreq):
134		ret = sys_ioctl(fd, SIOCDARP, arg);
135		goto out;
136
137	case _IOW('i', 40, struct ifreq): /* SIOCUPPER */
138	case _IOW('i', 41, struct ifreq): /* SIOCLOWER */
139	case _IOW('i', 44, struct ifreq): /* SIOCSETSYNC */
140	case _IOW('i', 45, struct ifreq): /* SIOCGETSYNC */
141	case _IOW('i', 46, struct ifreq): /* SIOCSSDSTATS */
142	case _IOW('i', 47, struct ifreq): /* SIOCSSESTATS */
143	case _IOW('i', 48, struct ifreq): /* SIOCSPROMISC */
144		ret = -EOPNOTSUPP;
145		goto out;
146
147	case _IOW('i', 49, struct ifreq):
148		ret = sys_ioctl(fd, SIOCADDMULTI, arg);
149		goto out;
150	case _IOW('i', 50, struct ifreq):
151		ret = sys_ioctl(fd, SIOCDELMULTI, arg);
152		goto out;
153
154	/* FDDI interface ioctls, unsupported. */
155
156	case _IOW('i', 51, struct ifreq): /* SIOCFDRESET */
157	case _IOW('i', 52, struct ifreq): /* SIOCFDSLEEP */
158	case _IOW('i', 53, struct ifreq): /* SIOCSTRTFMWAR */
159	case _IOW('i', 54, struct ifreq): /* SIOCLDNSTRTFW */
160	case _IOW('i', 55, struct ifreq): /* SIOCGETFDSTAT */
161	case _IOW('i', 56, struct ifreq): /* SIOCFDNMIINT */
162	case _IOW('i', 57, struct ifreq): /* SIOCFDEXUSER */
163	case _IOW('i', 58, struct ifreq): /* SIOCFDGNETMAP */
164	case _IOW('i', 59, struct ifreq): /* SIOCFDGIOCTL */
165		printk("FDDI ioctl, returning EOPNOTSUPP\n");
166		ret = -EOPNOTSUPP;
167		goto out;
168
169	case _IOW('t', 125, int):
170		/* More stupid tty sunos ioctls, just
171		 * say it worked.
172		 */
173		ret = 0;
174		goto out;
175	/* Non posix grp */
176	case _IOW('t', 118, int): {
177		int oldval, newval, *ptr;
178
179		cmd = TIOCSPGRP;
180		ptr = (int *) arg;
181		ret = -EFAULT;
182		if(get_user(oldval, ptr))
183			goto out;
184		ret = sys_ioctl(fd, cmd, arg);
185		__get_user(newval, ptr);
186		if(newval == -1) {
187			__put_user(oldval, ptr);
188			ret = -EIO;
189		}
190		if(ret == -ENOTTY)
191			ret = -EIO;
192		goto out;
193	}
194
195	case _IOR('t', 119, int): {
196		int oldval, newval, *ptr;
197
198		cmd = TIOCGPGRP;
199		ptr = (int *) arg;
200		ret = -EFAULT;
201		if(get_user(oldval, ptr))
202			goto out;
203		ret = sys_ioctl(fd, cmd, arg);
204		__get_user(newval, ptr);
205		if(newval == -1) {
206			__put_user(oldval, ptr);
207			ret = -EIO;
208		}
209		if(ret == -ENOTTY)
210			ret = -EIO;
211		goto out;
212	}
213	}
214
215
216	ret = sys_ioctl(fd, cmd, arg);
217	/* so stupid... */
218	ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
219out:
220	return ret;
221}
222
223
224