ioctl.c 21 KB

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