ioctl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:22k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: ioctl.c,v 1.16.2.1 2002/03/03 23:41:26 davem Exp $
  2.  * ioctl.c: Solaris ioctl emulation.
  3.  *
  4.  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  5.  * Copyright (C) 1997,1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
  6.  *
  7.  * Streams & timod emulation based on code
  8.  * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
  9.  *
  10.  * 1999-08-19 Implemented solaris 'm' (mag tape) and
  11.  *            'O' (openprom) ioctls, by Jason Rappleye
  12.  *             (rappleye@ccr.buffalo.edu)
  13.  */
  14. #include <linux/types.h>
  15. #include <linux/kernel.h>
  16. #include <linux/sched.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/ioctl.h>
  20. #include <linux/fs.h>
  21. #include <linux/file.h>
  22. #include <linux/netdevice.h>
  23. #include <linux/mtio.h>
  24. #include <linux/time.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/termios.h>
  27. #include <asm/openpromio.h>
  28. #include "conv.h"
  29. #include "socksys.h"
  30. extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, 
  31. unsigned long arg);
  32. extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd,
  33. u32 arg);
  34. asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
  35. extern int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len,
  36. char *data_buf, int data_len, int flags);
  37. extern int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, int *ctl_len,
  38. char *data_buf, int data_maxlen, int *data_len, int *flags);
  39. /* termio* stuff {{{ */
  40. struct solaris_termios {
  41. u32 c_iflag;
  42. u32 c_oflag;
  43. u32 c_cflag;
  44. u32 c_lflag;
  45. u8 c_cc[19];
  46. };
  47. struct solaris_termio {
  48. u16 c_iflag;
  49. u16 c_oflag;
  50. u16 c_cflag;
  51. u16 c_lflag;
  52. s8 c_line;
  53. u8 c_cc[8];
  54. };
  55. struct solaris_termiox {
  56. u16 x_hflag;
  57. u16 x_cflag;
  58. u16 x_rflag[5];
  59. u16 x_sflag;
  60. };
  61. static u32 solaris_to_linux_cflag(u32 cflag)
  62. {
  63. cflag &= 0x7fdff000;
  64. if (cflag & 0x200000) {
  65. int baud = cflag & 0xf;
  66. cflag &= ~0x20000f;
  67. switch (baud) {
  68. case 0: baud = B57600; break;
  69. case 1: baud = B76800; break;
  70. case 2: baud = B115200; break;
  71. case 3: baud = B153600; break;
  72. case 4: baud = B230400; break;
  73. case 5: baud = B307200; break;
  74. case 6: baud = B460800; break;
  75. }
  76. cflag |= CBAUDEX | baud;
  77. }
  78. return cflag;
  79. }
  80. static u32 linux_to_solaris_cflag(u32 cflag)
  81. {
  82. cflag &= ~(CMSPAR | CIBAUD);
  83. if (cflag & CBAUDEX) {
  84. int baud = cflag & CBAUD;
  85. cflag &= ~CBAUD;
  86. switch (baud) {
  87. case B57600: baud = 0; break;
  88. case B76800: baud = 1; break;
  89. case B115200: baud = 2; break;
  90. case B153600: baud = 3; break;
  91. case B230400: baud = 4; break;
  92. case B307200: baud = 5; break;
  93. case B460800: baud = 6; break;
  94. case B614400: baud = 7; break;
  95. case B921600: baud = 8; break;
  96. #if 0
  97. case B1843200: baud = 9; break;
  98. #endif
  99. }
  100. cflag |= 0x200000 | baud;
  101. }
  102. return cflag;
  103. }
  104. static inline int linux_to_solaris_termio(unsigned int fd, unsigned int cmd, u32 arg)
  105. {
  106. int ret;
  107. ret = sys_ioctl(fd, cmd, A(arg));
  108. if (!ret) {
  109. u32 cflag;
  110. if (__get_user (cflag, &((struct solaris_termio *)A(arg))->c_cflag))
  111. return -EFAULT;
  112. cflag = linux_to_solaris_cflag(cflag);
  113. if (__put_user (cflag, &((struct solaris_termio *)A(arg))->c_cflag))
  114. return -EFAULT;
  115. }
  116. return ret;
  117. }
  118. static int solaris_to_linux_termio(unsigned int fd, unsigned int cmd, u32 arg)
  119. {
  120. int ret;
  121. struct solaris_termio s;
  122. mm_segment_t old_fs = get_fs();
  123. if (copy_from_user (&s, (struct solaris_termio *)A(arg), sizeof(struct solaris_termio)))
  124. return -EFAULT;
  125. s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
  126. set_fs(KERNEL_DS);
  127. ret = sys_ioctl(fd, cmd, (unsigned long)&s);
  128. set_fs(old_fs);
  129. return ret;
  130. }
  131. static inline int linux_to_solaris_termios(unsigned int fd, unsigned int cmd, u32 arg)
  132. {
  133. int ret;
  134. struct solaris_termios s;
  135. mm_segment_t old_fs = get_fs();
  136. set_fs(KERNEL_DS);
  137. ret = sys_ioctl(fd, cmd, (unsigned long)&s);
  138. set_fs(old_fs);
  139. if (!ret) {
  140. if (put_user (s.c_iflag, &((struct solaris_termios *)A(arg))->c_iflag) ||
  141.     __put_user (s.c_oflag, &((struct solaris_termios *)A(arg))->c_oflag) ||
  142.     __put_user (linux_to_solaris_cflag(s.c_cflag), &((struct solaris_termios *)A(arg))->c_cflag) ||
  143.     __put_user (s.c_lflag, &((struct solaris_termios *)A(arg))->c_lflag) ||
  144.     __copy_to_user (((struct solaris_termios *)A(arg))->c_cc, s.c_cc, 16) ||
  145.     __clear_user (((struct solaris_termios *)A(arg))->c_cc + 16, 2))
  146. return -EFAULT;
  147. }
  148. return ret;
  149. }
  150. static int solaris_to_linux_termios(unsigned int fd, unsigned int cmd, u32 arg)
  151. {
  152. int ret;
  153. struct solaris_termios s;
  154. mm_segment_t old_fs = get_fs();
  155. set_fs(KERNEL_DS);
  156. ret = sys_ioctl(fd, TCGETS, (unsigned long)&s);
  157. set_fs(old_fs);
  158. if (ret) return ret;
  159. if (put_user (s.c_iflag, &((struct solaris_termios *)A(arg))->c_iflag) ||
  160.     __put_user (s.c_oflag, &((struct solaris_termios *)A(arg))->c_oflag) ||
  161.     __put_user (s.c_cflag, &((struct solaris_termios *)A(arg))->c_cflag) ||
  162.     __put_user (s.c_lflag, &((struct solaris_termios *)A(arg))->c_lflag) ||
  163.     __copy_from_user (s.c_cc, ((struct solaris_termios *)A(arg))->c_cc, 16))
  164. return -EFAULT;
  165. s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
  166. set_fs(KERNEL_DS);
  167. ret = sys_ioctl(fd, cmd, (unsigned long)&s);
  168. set_fs(old_fs);
  169. return ret;
  170. }
  171. static inline int solaris_T(unsigned int fd, unsigned int cmd, u32 arg)
  172. {
  173. switch (cmd & 0xff) {
  174. case 1: /* TCGETA */
  175. return linux_to_solaris_termio(fd, TCGETA, arg);
  176. case 2: /* TCSETA */
  177. return solaris_to_linux_termio(fd, TCSETA, arg);
  178. case 3: /* TCSETAW */
  179. return solaris_to_linux_termio(fd, TCSETAW, arg);
  180. case 4: /* TCSETAF */
  181. return solaris_to_linux_termio(fd, TCSETAF, arg);
  182. case 5: /* TCSBRK */
  183. return sys_ioctl(fd, TCSBRK, arg);
  184. case 6: /* TCXONC */
  185. return sys_ioctl(fd, TCXONC, arg);
  186. case 7: /* TCFLSH */
  187. return sys_ioctl(fd, TCFLSH, arg);
  188. case 13: /* TCGETS */
  189. return linux_to_solaris_termios(fd, TCGETS, arg);
  190. case 14: /* TCSETS */
  191. return solaris_to_linux_termios(fd, TCSETS, arg);
  192. case 15: /* TCSETSW */
  193. return solaris_to_linux_termios(fd, TCSETSW, arg);
  194. case 16: /* TCSETSF */
  195. return solaris_to_linux_termios(fd, TCSETSF, arg);
  196. case 103: /* TIOCSWINSZ */
  197. return sys_ioctl(fd, TIOCSWINSZ, arg);
  198. case 104: /* TIOCGWINSZ */
  199. return sys_ioctl(fd, TIOCGWINSZ, arg);
  200. }
  201. return -ENOSYS;
  202. }
  203. static inline int solaris_t(unsigned int fd, unsigned int cmd, u32 arg)
  204. {
  205. switch (cmd & 0xff) {
  206. case 20: /* TIOCGPGRP */
  207. return sys_ioctl(fd, TIOCGPGRP, arg);
  208. case 21: /* TIOCSPGRP */
  209. return sys_ioctl(fd, TIOCSPGRP, arg);
  210. }
  211. return -ENOSYS;
  212. }
  213. /* }}} */
  214. /* A pseudo STREAMS support {{{ */
  215. struct strioctl {
  216. int cmd, timeout, len;
  217. u32 data;
  218. };
  219. struct solaris_si_sockparams {
  220. int sp_family;
  221. int sp_type;
  222. int sp_protocol;
  223. };
  224. struct solaris_o_si_udata {
  225. int tidusize;
  226. int addrsize;
  227. int optsize;
  228. int etsdusize;
  229. int servtype;
  230. int so_state;
  231. int so_options;
  232. int tsdusize;
  233. };
  234. struct solaris_si_udata {
  235. int tidusize;
  236. int addrsize;
  237. int optsize;
  238. int etsdusize;
  239. int servtype;
  240. int so_state;
  241. int so_options;
  242. int tsdusize;
  243. struct solaris_si_sockparams sockparams;
  244. };
  245. #define SOLARIS_MODULE_TIMOD    0
  246. #define SOLARIS_MODULE_SOCKMOD  1
  247. #define SOLARIS_MODULE_MAX      2
  248. static struct module_info {
  249.         const char *name;
  250.         /* can be expanded further if needed */
  251. } module_table[ SOLARIS_MODULE_MAX + 1 ] = {
  252.         /* the ordering here must match the module numbers above! */
  253.         { "timod" },
  254.         { "sockmod" },
  255.         { NULL }
  256. };
  257. static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
  258. {
  259. struct inode *ino;
  260. /* I wonder which of these tests are superfluous... --patrik */
  261. read_lock(&current->files->file_lock);
  262. if (! current->files->fd[fd] ||
  263.     ! current->files->fd[fd]->f_dentry ||
  264.     ! (ino = current->files->fd[fd]->f_dentry->d_inode) ||
  265.     ! ino->i_sock) {
  266. read_unlock(&current->files->file_lock);
  267. return TBADF;
  268. }
  269. read_unlock(&current->files->file_lock);
  270. switch (cmd & 0xff) {
  271. case 109: /* SI_SOCKPARAMS */
  272. {
  273. struct solaris_si_sockparams si;
  274. if (copy_from_user (&si, (struct solaris_si_sockparams *) A(arg), sizeof(si)))
  275. return (EFAULT << 8) | TSYSERR;
  276. /* Should we modify socket ino->socket_i.ops and type? */
  277. return 0;
  278. }
  279. case 110: /* SI_GETUDATA */
  280. {
  281. int etsdusize, servtype;
  282. switch (ino->u.socket_i.type) {
  283. case SOCK_STREAM:
  284. etsdusize = 1;
  285. servtype = 2;
  286. break;
  287. default:
  288. etsdusize = -2;
  289. servtype = 3;
  290. break;
  291. }
  292. if (put_user(16384, &((struct solaris_si_udata *)A(arg))->tidusize) ||
  293.     __put_user(sizeof(struct sockaddr), &((struct solaris_si_udata *)A(arg))->addrsize) ||
  294.     __put_user(-1, &((struct solaris_si_udata *)A(arg))->optsize) ||
  295.     __put_user(etsdusize, &((struct solaris_si_udata *)A(arg))->etsdusize) ||
  296.     __put_user(servtype, &((struct solaris_si_udata *)A(arg))->servtype) ||
  297.     __put_user(0, &((struct solaris_si_udata *)A(arg))->so_state) ||
  298.     __put_user(0, &((struct solaris_si_udata *)A(arg))->so_options) ||
  299.     __put_user(16384, &((struct solaris_si_udata *)A(arg))->tsdusize) ||
  300.     __put_user(ino->u.socket_i.ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_family) ||
  301.     __put_user(ino->u.socket_i.type, &((struct solaris_si_udata *)A(arg))->sockparams.sp_type) ||
  302.     __put_user(ino->u.socket_i.ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_protocol))
  303. return (EFAULT << 8) | TSYSERR;
  304. return 0;
  305. }
  306. case 101: /* O_SI_GETUDATA */
  307. {
  308. int etsdusize, servtype;
  309. switch (ino->u.socket_i.type) {
  310. case SOCK_STREAM:
  311. etsdusize = 1;
  312. servtype = 2;
  313. break;
  314. default:
  315. etsdusize = -2;
  316. servtype = 3;
  317. break;
  318. }
  319. if (put_user(16384, &((struct solaris_o_si_udata *)A(arg))->tidusize) ||
  320.     __put_user(sizeof(struct sockaddr), &((struct solaris_o_si_udata *)A(arg))->addrsize) ||
  321.     __put_user(-1, &((struct solaris_o_si_udata *)A(arg))->optsize) ||
  322.     __put_user(etsdusize, &((struct solaris_o_si_udata *)A(arg))->etsdusize) ||
  323.     __put_user(servtype, &((struct solaris_o_si_udata *)A(arg))->servtype) ||
  324.     __put_user(0, &((struct solaris_o_si_udata *)A(arg))->so_state) ||
  325.     __put_user(0, &((struct solaris_o_si_udata *)A(arg))->so_options) ||
  326.     __put_user(16384, &((struct solaris_o_si_udata *)A(arg))->tsdusize))
  327. return (EFAULT << 8) | TSYSERR;
  328. return 0;
  329. }
  330. case 102: /* SI_SHUTDOWN */
  331. case 103: /* SI_LISTEN */
  332. case 104: /* SI_SETMYNAME */
  333. case 105: /* SI_SETPEERNAME */
  334. case 106: /* SI_GETINTRANSIT */
  335. case 107: /* SI_TCL_LINK */
  336. case 108: /* SI_TCL_UNLINK */
  337. }
  338. return TNOTSUPPORT;
  339. }
  340. static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
  341.                                     int len, int *len_p)
  342. {
  343. int ret;
  344. switch (cmd & 0xff) {
  345. case 141: /* TI_OPTMGMT */
  346. {
  347. int i;
  348. u32 prim;
  349. SOLD("TI_OPMGMT entry");
  350. ret = timod_putmsg(fd, (char *)A(arg), len, NULL, -1, 0);
  351. SOLD("timod_putmsg() returned");
  352. if (ret)
  353. return (-ret << 8) | TSYSERR;
  354. i = MSG_HIPRI;
  355. SOLD("calling timod_getmsg()");
  356. ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
  357. SOLD("timod_getmsg() returned");
  358. if (ret)
  359. return (-ret << 8) | TSYSERR;
  360. SOLD("ret ok");
  361. if (get_user(prim, (u32 *)A(arg)))
  362. return (EFAULT << 8) | TSYSERR;
  363. SOLD("got prim");
  364. if (prim == T_ERROR_ACK) {
  365. u32 tmp, tmp2;
  366. SOLD("prim is T_ERROR_ACK");
  367. if (get_user(tmp, (u32 *)A(arg)+3) ||
  368.     get_user(tmp2, (u32 *)A(arg)+2))
  369. return (EFAULT << 8) | TSYSERR;
  370. return (tmp2 << 8) | tmp;
  371. }
  372. SOLD("TI_OPMGMT return 0");
  373. return 0;
  374. }
  375. case 142: /* TI_BIND */
  376. {
  377. int i;
  378. u32 prim;
  379. SOLD("TI_BIND entry");
  380. ret = timod_putmsg(fd, (char *)A(arg), len, NULL, -1, 0);
  381. SOLD("timod_putmsg() returned");
  382. if (ret)
  383. return (-ret << 8) | TSYSERR;
  384. len = 1024; /* Solaris allows arbitrary return size */
  385. i = MSG_HIPRI;
  386. SOLD("calling timod_getmsg()");
  387. ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
  388. SOLD("timod_getmsg() returned");
  389. if (ret)
  390. return (-ret << 8) | TSYSERR;
  391. SOLD("ret ok");
  392. if (get_user(prim, (u32 *)A(arg)))
  393. return (EFAULT << 8) | TSYSERR;
  394. SOLD("got prim");
  395. if (prim == T_ERROR_ACK) {
  396. u32 tmp, tmp2;
  397. SOLD("prim is T_ERROR_ACK");
  398. if (get_user(tmp, (u32 *)A(arg)+3) ||
  399.     get_user(tmp2, (u32 *)A(arg)+2))
  400. return (EFAULT << 8) | TSYSERR;
  401. return (tmp2 << 8) | tmp;
  402. }
  403. SOLD("no ERROR_ACK requested");
  404. if (prim != T_OK_ACK)
  405. return TBADSEQ;
  406. SOLD("OK_ACK requested");
  407. i = MSG_HIPRI;
  408. SOLD("calling timod_getmsg()");
  409. ret = timod_getmsg(fd, (char *)A(arg), len, len_p, NULL, -1, NULL, &i);
  410. SOLD("timod_getmsg() returned");
  411. if (ret)
  412. return (-ret << 8) | TSYSERR;
  413. SOLD("TI_BIND return ok");
  414. return 0;
  415. }
  416. case 140: /* TI_GETINFO */
  417. case 143: /* TI_UNBIND */
  418. case 144: /* TI_GETMYNAME */
  419. case 145: /* TI_GETPEERNAME */
  420. case 146: /* TI_SETMYNAME */
  421. case 147: /* TI_SETPEERNAME */
  422. }
  423. return TNOTSUPPORT;
  424. }
  425. static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd, u32 arg)
  426. {
  427. char *p;
  428. int ret;
  429. mm_segment_t old_fs;
  430. struct strioctl si;
  431. struct inode *ino;
  432.         struct sol_socket_struct *sock;
  433.         struct module_info *mi;
  434.         ino = filp->f_dentry->d_inode;
  435.         if (! ino->i_sock)
  436. return -EBADF;
  437.         sock = filp->private_data;
  438.         if (! sock) {
  439.                 printk("solaris_S: NULL private_datan");
  440.                 return -EBADF;
  441.         }
  442.         if (sock->magic != SOLARIS_SOCKET_MAGIC) {
  443.                 printk("solaris_S: invalid magicn");
  444.                 return -EBADF;
  445.         }
  446.         
  447. switch (cmd & 0xff) {
  448. case 1: /* I_NREAD */
  449. return -ENOSYS;
  450. case 2: /* I_PUSH */
  451.         {
  452. p = getname ((char *)A(arg));
  453. if (IS_ERR (p))
  454. return PTR_ERR(p);
  455.                 ret = -EINVAL;
  456.                 for (mi = module_table; mi->name; mi++) {
  457.                         if (strcmp(mi->name, p) == 0) {
  458.                                 sol_module m;
  459.                                 if (sock->modcount >= MAX_NR_STREAM_MODULES) {
  460.                                         ret = -ENXIO;
  461.                                         break;
  462.                                 }
  463.                                 m = (sol_module) (mi - module_table);
  464.                                 sock->module[sock->modcount++] = m;
  465.                                 ret = 0;
  466.                                 break;
  467.                         }
  468.                 }
  469. putname (p);
  470. return ret;
  471.         }
  472. case 3: /* I_POP */
  473.                 if (sock->modcount <= 0) return -EINVAL;
  474.                 sock->modcount--;
  475. return 0;
  476.         case 4: /* I_LOOK */
  477.         {
  478.          const char *p;
  479.                 if (sock->modcount <= 0) return -EINVAL;
  480.                 p = module_table[(unsigned)sock->module[sock->modcount]].name;
  481.                 if (copy_to_user ((char *)A(arg), p, strlen(p)))
  482.                  return -EFAULT;
  483.                 return 0;
  484.         }
  485. case 5: /* I_FLUSH */
  486. return 0;
  487. case 8: /* I_STR */
  488. if (copy_from_user(&si, (struct strioctl *)A(arg), sizeof(struct strioctl)))
  489. return -EFAULT;
  490.                 /* We ignore what module is actually at the top of stack. */
  491. switch ((si.cmd >> 8) & 0xff) {
  492. case 'I':
  493.                         return solaris_sockmod(fd, si.cmd, si.data);
  494. case 'T':
  495.                         return solaris_timod(fd, si.cmd, si.data, si.len,
  496.                                                 &((struct strioctl*)A(arg))->len);
  497. default:
  498. return solaris_ioctl(fd, si.cmd, si.data);
  499. }
  500. case 9: /* I_SETSIG */
  501. return sys_ioctl(fd, FIOSETOWN, current->pid);
  502. case 10: /* I_GETSIG */
  503. old_fs = get_fs();
  504. set_fs(KERNEL_DS);
  505. sys_ioctl(fd, FIOGETOWN, (unsigned long)&ret);
  506. set_fs(old_fs);
  507. if (ret == current->pid) return 0x3ff;
  508. else return -EINVAL;
  509. case 11: /* I_FIND */
  510.         {
  511.                 int i;
  512. p = getname ((char *)A(arg));
  513. if (IS_ERR (p))
  514. return PTR_ERR(p);
  515.                 ret = 0;
  516.                 for (i = 0; i < sock->modcount; i++) {
  517.                         unsigned m = sock->module[i];
  518.                         if (strcmp(module_table[m].name, p) == 0) {
  519.                                 ret = 1;
  520.                                 break;
  521.                         } 
  522.                 }
  523. putname (p);
  524. return ret;
  525.         }
  526. case 19: /* I_SWROPT */
  527. case 32: /* I_SETCLTIME */
  528. return 0; /* Lie */
  529. }
  530. return -ENOSYS;
  531. }
  532. static inline int solaris_s(unsigned int fd, unsigned int cmd, u32 arg)
  533. {
  534. switch (cmd & 0xff) {
  535. case 0: /* SIOCSHIWAT */
  536. case 2: /* SIOCSLOWAT */
  537. return 0; /* We don't support them */
  538. case 1: /* SIOCGHIWAT */
  539. case 3: /* SIOCGLOWAT */
  540. if (put_user (0, (u32 *)A(arg)))
  541. return -EFAULT;
  542. return 0; /* Lie */
  543. case 7: /* SIOCATMARK */
  544. return sys_ioctl(fd, SIOCATMARK, arg);
  545. case 8: /* SIOCSPGRP */
  546. return sys_ioctl(fd, SIOCSPGRP, arg);
  547. case 9: /* SIOCGPGRP */
  548. return sys_ioctl(fd, SIOCGPGRP, arg);
  549. }
  550. return -ENOSYS;
  551. }
  552. static inline int solaris_r(unsigned int fd, unsigned int cmd, u32 arg)
  553. {
  554. switch (cmd & 0xff) {
  555. case 10: /* SIOCADDRT */
  556. return sys32_ioctl(fd, SIOCADDRT, arg);
  557. case 11: /* SIOCDELRT */
  558. return sys32_ioctl(fd, SIOCDELRT, arg);
  559. }
  560. return -ENOSYS;
  561. }
  562. static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
  563. {
  564. switch (cmd & 0xff) {
  565. case 12: /* SIOCSIFADDR */
  566. return sys32_ioctl(fd, SIOCSIFADDR, arg);
  567. case 13: /* SIOCGIFADDR */
  568. return sys32_ioctl(fd, SIOCGIFADDR, arg);
  569. case 14: /* SIOCSIFDSTADDR */
  570. return sys32_ioctl(fd, SIOCSIFDSTADDR, arg);
  571. case 15: /* SIOCGIFDSTADDR */
  572. return sys32_ioctl(fd, SIOCGIFDSTADDR, arg);
  573. case 16: /* SIOCSIFFLAGS */
  574. return sys32_ioctl(fd, SIOCSIFFLAGS, arg);
  575. case 17: /* SIOCGIFFLAGS */
  576. return sys32_ioctl(fd, SIOCGIFFLAGS, arg);
  577. case 18: /* SIOCSIFMEM */
  578. return sys32_ioctl(fd, SIOCSIFMEM, arg);
  579. case 19: /* SIOCGIFMEM */
  580. return sys32_ioctl(fd, SIOCGIFMEM, arg);
  581. case 20: /* SIOCGIFCONF */
  582. return sys32_ioctl(fd, SIOCGIFCONF, arg);
  583. case 21: /* SIOCSIFMTU */
  584. return sys32_ioctl(fd, SIOCSIFMTU, arg);
  585. case 22: /* SIOCGIFMTU */
  586. return sys32_ioctl(fd, SIOCGIFMTU, arg);
  587. case 23: /* SIOCGIFBRDADDR */
  588. return sys32_ioctl(fd, SIOCGIFBRDADDR, arg);
  589. case 24: /* SIOCSIFBRDADDR */
  590. return sys32_ioctl(fd, SIOCSIFBRDADDR, arg);
  591. case 25: /* SIOCGIFNETMASK */
  592. return sys32_ioctl(fd, SIOCGIFNETMASK, arg);
  593. case 26: /* SIOCSIFNETMASK */
  594. return sys32_ioctl(fd, SIOCSIFNETMASK, arg);
  595. case 27: /* SIOCGIFMETRIC */
  596. return sys32_ioctl(fd, SIOCGIFMETRIC, arg);
  597. case 28: /* SIOCSIFMETRIC */
  598. return sys32_ioctl(fd, SIOCSIFMETRIC, arg);
  599. case 30: /* SIOCSARP */
  600. return sys32_ioctl(fd, SIOCSARP, arg);
  601. case 31: /* SIOCGARP */
  602. return sys32_ioctl(fd, SIOCGARP, arg);
  603. case 32: /* SIOCDARP */
  604. return sys32_ioctl(fd, SIOCDARP, arg);
  605. case 52: /* SIOCGETNAME */
  606. case 53: /* SIOCGETPEER */
  607. {
  608. struct sockaddr uaddr;
  609. int uaddr_len = sizeof(struct sockaddr), ret;
  610. long args[3];
  611. mm_segment_t old_fs = get_fs();
  612. int (*sys_socketcall)(int, unsigned long *) =
  613. (int (*)(int, unsigned long *))SYS(socketcall);
  614. args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len;
  615. set_fs(KERNEL_DS);
  616. ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME,
  617. args);
  618. set_fs(old_fs);
  619. if (ret >= 0) {
  620. if (copy_to_user((char *)A(arg), &uaddr, uaddr_len))
  621. return -EFAULT;
  622. }
  623. return ret;
  624. }
  625. #if 0
  626. case 86: /* SIOCSOCKSYS */
  627. return socksys_syscall(fd, arg);
  628. #endif
  629. case 87: /* SIOCGIFNUM */
  630. {
  631. struct net_device *d;
  632. int i = 0;
  633. read_lock_bh(&dev_base_lock);
  634. for (d = dev_base; d; d = d->next) i++;
  635. read_unlock_bh(&dev_base_lock);
  636. if (put_user (i, (int *)A(arg)))
  637. return -EFAULT;
  638. return 0;
  639. }
  640. }
  641. return -ENOSYS;
  642. }
  643. static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg)
  644. {
  645. int ret;
  646. switch (cmd & 0xff) {
  647. case 1: /* MTIOCTOP */
  648. ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg);
  649. break;
  650. case 2: /* MTIOCGET */
  651. ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg);
  652. break;
  653. case 3: /* MTIOCGETDRIVETYPE */
  654. case 4: /* MTIOCPERSISTENT */
  655. case 5: /* MTIOCPERSISTENTSTATUS */
  656. case 6: /* MTIOCLRERR */
  657. case 7: /* MTIOCGUARANTEEDORDER */
  658. case 8: /* MTIOCRESERVE */
  659. case 9: /* MTIOCRELEASE */
  660. case 10: /* MTIOCFORCERESERVE */
  661. case 13: /* MTIOCSTATE */
  662. case 14: /* MTIOCREADIGNOREILI */
  663. case 15: /* MTIOCREADIGNOREEOFS */
  664. case 16: /* MTIOCSHORTFMK */
  665. default:
  666. ret = -ENOSYS; /* linux doesn't support these */
  667. break;
  668. };
  669. return ret;
  670. }
  671. static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg)
  672. {
  673. int ret = -EINVAL;
  674. switch (cmd & 0xff) {
  675. case 1: /* OPROMGETOPT */
  676. ret = sys_ioctl(fd, OPROMGETOPT, arg);
  677. break;
  678. case 2: /* OPROMSETOPT */
  679. ret = sys_ioctl(fd, OPROMSETOPT, arg);
  680. break;
  681. case 3: /* OPROMNXTOPT */
  682. ret = sys_ioctl(fd, OPROMNXTOPT, arg);
  683. break;
  684. case 4: /* OPROMSETOPT2 */
  685. ret = sys_ioctl(fd, OPROMSETOPT2, arg);
  686. break;
  687. case 5: /* OPROMNEXT */
  688. ret = sys_ioctl(fd, OPROMNEXT, arg);
  689. break;
  690. case 6: /* OPROMCHILD */
  691. ret = sys_ioctl(fd, OPROMCHILD, arg);
  692. break;
  693. case 7: /* OPROMGETPROP */
  694. ret = sys_ioctl(fd, OPROMGETPROP, arg);
  695. break;
  696. case 8: /* OPROMNXTPROP */
  697. ret = sys_ioctl(fd, OPROMNXTPROP, arg);
  698. break;
  699. case 9: /* OPROMU2P */
  700. ret = sys_ioctl(fd, OPROMU2P, arg);
  701. break;
  702. case 10: /* OPROMGETCONS */
  703. ret = sys_ioctl(fd, OPROMGETCONS, arg);
  704. break;
  705. case 11: /* OPROMGETFBNAME */
  706. ret = sys_ioctl(fd, OPROMGETFBNAME, arg);
  707. break;
  708. case 12: /* OPROMGETBOOTARGS */
  709. ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg);
  710. break;
  711. case 13: /* OPROMGETVERSION */
  712. case 14: /* OPROMPATH2DRV */
  713. case 15: /* OPROMDEV2PROMNAME */
  714. case 16: /* OPROMPROM2DEVNAME */
  715. case 17: /* OPROMGETPROPLEN */
  716. default:
  717. ret = -EINVAL;
  718. break;
  719. };
  720. return ret;
  721. }
  722. /* }}} */
  723. asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
  724. {
  725. struct file *filp;
  726. int error = -EBADF;
  727. filp = fget(fd);
  728. if (!filp)
  729. goto out;
  730. lock_kernel();
  731. error = -EFAULT;
  732. switch ((cmd >> 8) & 0xff) {
  733. case 'S': error = solaris_S(filp, fd, cmd, arg); break;
  734. case 'T': error = solaris_T(fd, cmd, arg); break;
  735. case 'i': error = solaris_i(fd, cmd, arg); break;
  736. case 'r': error = solaris_r(fd, cmd, arg); break;
  737. case 's': error = solaris_s(fd, cmd, arg); break;
  738. case 't': error = solaris_t(fd, cmd, arg); break;
  739. case 'f': error = sys_ioctl(fd, cmd, arg); break;
  740. case 'm': error = solaris_m(fd, cmd, arg); break;
  741. case 'O': error = solaris_O(fd, cmd, arg); break;
  742. default:
  743. error = -ENOSYS;
  744. break;
  745. }
  746. unlock_kernel();
  747. fput(filp);
  748. out:
  749. if (error == -ENOSYS) {
  750. unsigned char c = cmd>>8;
  751. if (c < ' ' || c > 126) c = '.';
  752. printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)n",
  753.        (int)fd, (unsigned int)cmd, c, (unsigned int)arg);
  754. error = -EINVAL;
  755. }
  756. return error;
  757. }