ioctl.c 21 KB

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