ioctl.c 21 KB

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