ioctl32.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  3.  *
  4.  *  S390 version
  5.  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6.  *    Author(s): Gerhard Tonn (ton@de.ibm.com)
  7.  *
  8.  * Heavily inspired by the 32-bit Sparc compat code which is  
  9.  * Copyright (C) 2000 Silicon Graphics, Inc.
  10.  * Written by Ulf Carlsson (ulfc@engr.sgi.com) 
  11.  *
  12.  */
  13. #include <linux/types.h>
  14. #include <linux/kernel.h>
  15. #include <linux/fs.h>
  16. #include <linux/sched.h>
  17. #include <linux/mm.h>
  18. #include <linux/init.h>
  19. #include <linux/file.h>
  20. #include <linux/vt.h>
  21. #include <linux/kd.h>
  22. #include <linux/netdevice.h>
  23. #include <linux/route.h>
  24. #include <linux/ext2_fs.h>
  25. #include <linux/hdreg.h>
  26. #include <linux/if_bonding.h>
  27. #include <asm/types.h>
  28. #include <asm/uaccess.h>
  29. #include <asm/dasd.h>
  30. #include <asm/sockios.h>
  31. #include "linux32.h"
  32. long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
  33. struct hd_geometry32 {
  34. unsigned char heads;
  35. unsigned char sectors;
  36. unsigned short cylinders;
  37. __u32 start;
  38. };  
  39. static inline int hd_geometry_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
  40. {
  41. struct hd_geometry32 *hg32 = (struct hd_geometry32 *) A(arg);
  42. struct hd_geometry hg;
  43. int ret;
  44. mm_segment_t old_fs = get_fs();
  45. set_fs (KERNEL_DS);
  46. ret = sys_ioctl (fd, cmd, (long)&hg);
  47. set_fs (old_fs);
  48. if (ret)
  49. return ret;
  50. ret = put_user (hg.heads, &(hg32->heads));
  51. ret |= __put_user (hg.sectors, &(hg32->sectors));
  52. ret |= __put_user (hg.cylinders, &(hg32->cylinders));
  53. ret |= __put_user (hg.start, &(hg32->start));
  54. return ret;
  55. }
  56. struct timeval32 {
  57. int tv_sec;
  58. int tv_usec;
  59. };
  60. #define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
  61. #define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
  62. #define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
  63. #define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
  64. struct ifmap32 {
  65. unsigned int mem_start;
  66. unsigned int mem_end;
  67. unsigned short base_addr;
  68. unsigned char irq;
  69. unsigned char dma;
  70. unsigned char port;
  71. };
  72. struct ifreq32 {
  73. #define IFHWADDRLEN     6
  74. #define IFNAMSIZ        16
  75.         union {
  76.                 char    ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
  77.         } ifr_ifrn;
  78.         union {
  79.                 struct  sockaddr ifru_addr;
  80.                 struct  sockaddr ifru_dstaddr;
  81.                 struct  sockaddr ifru_broadaddr;
  82.                 struct  sockaddr ifru_netmask;
  83.                 struct  sockaddr ifru_hwaddr;
  84.                 short   ifru_flags;
  85.                 int     ifru_ivalue;
  86.                 int     ifru_mtu;
  87.                 struct  ifmap32 ifru_map;
  88.                 char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
  89. char ifru_newname[IFNAMSIZ];
  90.                 __u32 ifru_data;
  91.         } ifr_ifru;
  92. };
  93. struct ifconf32 {
  94.         int     ifc_len;                        /* size of buffer       */
  95.         __u32 ifcbuf;
  96. };
  97. static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
  98. {
  99. struct ireq32 *uir32 = (struct ireq32 *) A(arg);
  100. struct net_device *dev;
  101. struct ifreq32 ifr32;
  102. if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32)))
  103. return -EFAULT;
  104. read_lock(&dev_base_lock);
  105. dev = __dev_get_by_index(ifr32.ifr_ifindex);
  106. if (!dev) {
  107. read_unlock(&dev_base_lock);
  108. return -ENODEV;
  109. }
  110. strcpy(ifr32.ifr_name, dev->name);
  111. read_unlock(&dev_base_lock);
  112. if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32)))
  113.     return -EFAULT;
  114. return 0;
  115. }
  116. static inline int dev_ifconf(unsigned int fd, unsigned int cmd,
  117.      unsigned long arg)
  118. {
  119. struct ioconf32 *uifc32 = (struct ioconf32 *) A(arg);
  120. struct ifconf32 ifc32;
  121. struct ifconf ifc;
  122. struct ifreq32 *ifr32;
  123. struct ifreq *ifr;
  124. mm_segment_t old_fs;
  125. int len;
  126. int err;
  127. if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32)))
  128. return -EFAULT;
  129. if(ifc32.ifcbuf == 0) {
  130. ifc32.ifc_len = 0;
  131. ifc.ifc_len = 0;
  132. ifc.ifc_buf = NULL;
  133. } else {
  134. ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) *
  135. sizeof (struct ifreq);
  136. ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
  137. if (!ifc.ifc_buf)
  138. return -ENOMEM;
  139. }
  140. ifr = ifc.ifc_req;
  141. ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf);
  142. len = ifc32.ifc_len / sizeof (struct ifreq32);
  143. while (len--) {
  144. if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
  145. err = -EFAULT;
  146. goto out;
  147. }
  148. }
  149. old_fs = get_fs();
  150. set_fs (KERNEL_DS);
  151. err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);
  152. set_fs (old_fs);
  153. if (err)
  154. goto out;
  155. ifr = ifc.ifc_req;
  156. ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf);
  157. len = ifc.ifc_len / sizeof (struct ifreq);
  158. ifc32.ifc_len = len * sizeof (struct ifreq32);
  159. while (len--) {
  160. if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
  161. err = -EFAULT;
  162. goto out;
  163. }
  164. }
  165. if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) {
  166. err = -EFAULT;
  167. goto out;
  168. }
  169. out:
  170. if(ifc.ifc_buf != NULL)
  171. kfree (ifc.ifc_buf);
  172. return err;
  173. }
  174. static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
  175. {
  176. struct ifreq ifr;
  177. mm_segment_t old_fs;
  178. int err, len;
  179. u32 data;
  180. if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
  181. return -EFAULT;
  182. ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
  183. if (!ifr.ifr_data)
  184. return -EAGAIN;
  185. switch (cmd) {
  186. case SIOCBONDENSLAVE:
  187. case SIOCBONDRELEASE:
  188. case SIOCBONDSETHWADDR:
  189. case SIOCBONDCHANGEACTIVE:
  190. len = IFNAMSIZ * sizeof(char);
  191. break;
  192. case SIOCBONDSLAVEINFOQUERY:
  193. len = sizeof(struct ifslave);
  194. break;
  195. case SIOCBONDINFOQUERY:
  196. len = sizeof(struct ifbond);
  197. break;
  198. default:
  199. err = -EINVAL;
  200. goto out;
  201. };
  202. __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
  203. if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) {
  204. err = -EFAULT;
  205. goto out;
  206. }
  207. old_fs = get_fs();
  208. set_fs (KERNEL_DS);
  209. err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
  210. set_fs (old_fs);
  211. if (!err) {
  212. len = copy_to_user((char *)A(data), ifr.ifr_data, len);
  213. if (len)
  214. err = -EFAULT;
  215. }
  216. out:
  217. free_page((unsigned long)ifr.ifr_data);
  218. return err;
  219. }
  220. static inline int dev_ifsioc(unsigned int fd, unsigned int cmd,
  221.      unsigned long arg)
  222. {
  223. struct ifreq32 *uifr = (struct ifreq32 *) A(arg);
  224. struct ifreq ifr;
  225. mm_segment_t old_fs;
  226. int err;
  227. switch (cmd) {
  228. case SIOCSIFMAP:
  229. err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name));
  230. err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
  231. err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
  232. err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
  233. err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
  234. err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
  235. err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
  236. if (err)
  237. return -EFAULT;
  238. break;
  239. default:
  240. if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32)))
  241. return -EFAULT;
  242. break;
  243. }
  244. old_fs = get_fs();
  245. set_fs (KERNEL_DS);
  246. err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
  247. set_fs (old_fs);
  248. if (!err) {
  249. switch (cmd) {
  250. case SIOCGIFFLAGS:
  251. case SIOCGIFMETRIC:
  252. case SIOCGIFMTU:
  253. case SIOCGIFMEM:
  254. case SIOCGIFHWADDR:
  255. case SIOCGIFINDEX:
  256. case SIOCGIFADDR:
  257. case SIOCGIFBRDADDR:
  258. case SIOCGIFDSTADDR:
  259. case SIOCGIFNETMASK:
  260. case SIOCGIFTXQLEN:
  261. if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32)))
  262. return -EFAULT;
  263. break;
  264. case SIOCGIFMAP:
  265. err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name));
  266. err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
  267. err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
  268. err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
  269. err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
  270. err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
  271. err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
  272. if (err)
  273. err = -EFAULT;
  274. break;
  275. }
  276. }
  277. return err;
  278. }
  279. struct rtentry32
  280. {
  281. unsigned int rt_pad1;
  282. struct sockaddr rt_dst; /* target address */
  283. struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */
  284. struct sockaddr rt_genmask; /* target network mask (IP) */
  285. unsigned short rt_flags;
  286. short rt_pad2;
  287. unsigned int rt_pad3;
  288. unsigned int rt_pad4;
  289. short rt_metric; /* +1 for binary compatibility! */
  290. unsigned int rt_dev; /* forcing the device at add */
  291. unsigned int rt_mtu; /* per route MTU/Window  */
  292. #ifndef __KERNEL__
  293. #define rt_mss rt_mtu /* Compatibility :-(            */
  294. #endif
  295. unsigned int rt_window; /* Window clamping  */
  296. unsigned short rt_irtt; /* Initial RTT */
  297. };
  298. static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
  299. {
  300. struct rtentry32 *ur = (struct rtentry32 *) A(arg);
  301. struct rtentry r;
  302. char devname[16];
  303. u32 rtdev;
  304. int ret;
  305. mm_segment_t old_fs = get_fs();
  306. ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr));
  307. ret |= __get_user (r.rt_flags, &(ur->rt_flags));
  308. ret |= __get_user (r.rt_metric, &(ur->rt_metric));
  309. ret |= __get_user (r.rt_mtu, &(ur->rt_mtu));
  310. ret |= __get_user (r.rt_window, &(ur->rt_window));
  311. ret |= __get_user (r.rt_irtt, &(ur->rt_irtt));
  312. ret |= __get_user (rtdev, &(ur->rt_dev));
  313. if (rtdev) {
  314. ret |= copy_from_user (devname, (char *) A(rtdev), 15);
  315. r.rt_dev = devname; devname[15] = 0;
  316. } else
  317. r.rt_dev = 0;
  318. if (ret)
  319. return -EFAULT;
  320. set_fs (KERNEL_DS);
  321. ret = sys_ioctl (fd, cmd, (long)&r);
  322. set_fs (old_fs);
  323. return ret;
  324. }
  325. static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
  326. {
  327. /* These are just misnamed, they actually get/put from/to user an int */
  328. switch (cmd) {
  329. case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
  330. case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
  331. case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
  332. case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
  333. }
  334. return sys_ioctl(fd, cmd, arg);
  335. }
  336. static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
  337. {
  338. mm_segment_t old_fs = get_fs();
  339. int err;
  340. unsigned long val;
  341. set_fs (KERNEL_DS);
  342. err = sys_ioctl(fd, cmd, (unsigned long)&val);
  343. set_fs (old_fs);
  344. if (!err && put_user((unsigned int) val, (u32 *)arg))
  345. return -EFAULT;
  346. return err;
  347. }
  348. struct ioctl32_handler {
  349. unsigned int cmd;
  350. int (*function)(unsigned int, unsigned int, unsigned long);
  351. };
  352. struct ioctl32_list {
  353. struct ioctl32_handler handler;
  354. struct ioctl32_list *next;
  355. };
  356. #define IOCTL32_DEFAULT(cmd) { { cmd, (void *) sys_ioctl }, 0 }
  357. #define IOCTL32_HANDLER(cmd, handler) { { cmd, (void *) handler }, 0 }
  358. static struct ioctl32_list ioctl32_handler_table[] = {
  359. IOCTL32_DEFAULT(FIBMAP),
  360. IOCTL32_DEFAULT(FIGETBSZ),
  361. IOCTL32_DEFAULT(DASDAPIVER),
  362. IOCTL32_DEFAULT(BIODASDDISABLE),
  363. IOCTL32_DEFAULT(BIODASDENABLE),
  364. IOCTL32_DEFAULT(BIODASDRSRV),
  365. IOCTL32_DEFAULT(BIODASDRLSE),
  366. IOCTL32_DEFAULT(BIODASDSLCK),
  367. IOCTL32_DEFAULT(BIODASDINFO),
  368. IOCTL32_DEFAULT(BIODASDFMT),
  369. IOCTL32_DEFAULT(BLKRRPART),
  370. IOCTL32_HANDLER(HDIO_GETGEO, hd_geometry_ioctl),
  371. IOCTL32_DEFAULT(TCGETA),
  372. IOCTL32_DEFAULT(TCSETA),
  373. IOCTL32_DEFAULT(TCSETAW),
  374. IOCTL32_DEFAULT(TCSETAF),
  375. IOCTL32_DEFAULT(TCSBRK),
  376. IOCTL32_DEFAULT(TCXONC),
  377. IOCTL32_DEFAULT(TCFLSH),
  378. IOCTL32_DEFAULT(TCGETS),
  379. IOCTL32_DEFAULT(TCSETS),
  380. IOCTL32_DEFAULT(TCSETSW),
  381. IOCTL32_DEFAULT(TCSETSF),
  382. IOCTL32_DEFAULT(TIOCLINUX),
  383. IOCTL32_DEFAULT(TIOCGETD),
  384. IOCTL32_DEFAULT(TIOCSETD),
  385. IOCTL32_DEFAULT(TIOCEXCL),
  386. IOCTL32_DEFAULT(TIOCNXCL),
  387. IOCTL32_DEFAULT(TIOCCONS),
  388. IOCTL32_DEFAULT(TIOCGSOFTCAR),
  389. IOCTL32_DEFAULT(TIOCSSOFTCAR),
  390. IOCTL32_DEFAULT(TIOCSWINSZ),
  391. IOCTL32_DEFAULT(TIOCGWINSZ),
  392. IOCTL32_DEFAULT(TIOCMGET),
  393. IOCTL32_DEFAULT(TIOCMBIC),
  394. IOCTL32_DEFAULT(TIOCMBIS),
  395. IOCTL32_DEFAULT(TIOCMSET),
  396. IOCTL32_DEFAULT(TIOCPKT),
  397. IOCTL32_DEFAULT(TIOCNOTTY),
  398. IOCTL32_DEFAULT(TIOCSTI),
  399. IOCTL32_DEFAULT(TIOCOUTQ),
  400. IOCTL32_DEFAULT(TIOCSPGRP),
  401. IOCTL32_DEFAULT(TIOCGPGRP),
  402. IOCTL32_DEFAULT(TIOCSCTTY),
  403. IOCTL32_DEFAULT(TIOCGPTN),
  404. IOCTL32_DEFAULT(TIOCSPTLCK),
  405. IOCTL32_DEFAULT(TIOCGSERIAL),
  406. IOCTL32_DEFAULT(TIOCSSERIAL),
  407. IOCTL32_DEFAULT(TIOCSERGETLSR),
  408. IOCTL32_DEFAULT(FIOCLEX),
  409. IOCTL32_DEFAULT(FIONCLEX),
  410. IOCTL32_DEFAULT(FIOASYNC),
  411. IOCTL32_DEFAULT(FIONBIO),
  412. IOCTL32_DEFAULT(FIONREAD),
  413. IOCTL32_DEFAULT(PIO_FONT),
  414. IOCTL32_DEFAULT(GIO_FONT),
  415. IOCTL32_DEFAULT(KDSIGACCEPT),
  416. IOCTL32_DEFAULT(KDGETKEYCODE),
  417. IOCTL32_DEFAULT(KDSETKEYCODE),
  418. IOCTL32_DEFAULT(KIOCSOUND),
  419. IOCTL32_DEFAULT(KDMKTONE),
  420. IOCTL32_DEFAULT(KDGKBTYPE),
  421. IOCTL32_DEFAULT(KDSETMODE),
  422. IOCTL32_DEFAULT(KDGETMODE),
  423. IOCTL32_DEFAULT(KDSKBMODE),
  424. IOCTL32_DEFAULT(KDGKBMODE),
  425. IOCTL32_DEFAULT(KDSKBMETA),
  426. IOCTL32_DEFAULT(KDGKBMETA),
  427. IOCTL32_DEFAULT(KDGKBENT),
  428. IOCTL32_DEFAULT(KDSKBENT),
  429. IOCTL32_DEFAULT(KDGKBSENT),
  430. IOCTL32_DEFAULT(KDSKBSENT),
  431. IOCTL32_DEFAULT(KDGKBDIACR),
  432. IOCTL32_DEFAULT(KDSKBDIACR),
  433. IOCTL32_DEFAULT(KDGKBLED),
  434. IOCTL32_DEFAULT(KDSKBLED),
  435. IOCTL32_DEFAULT(KDGETLED),
  436. IOCTL32_DEFAULT(KDSETLED),
  437. IOCTL32_DEFAULT(GIO_SCRNMAP),
  438. IOCTL32_DEFAULT(PIO_SCRNMAP),
  439. IOCTL32_DEFAULT(GIO_UNISCRNMAP),
  440. IOCTL32_DEFAULT(PIO_UNISCRNMAP),
  441. IOCTL32_DEFAULT(PIO_FONTRESET),
  442. IOCTL32_DEFAULT(PIO_UNIMAPCLR),
  443. IOCTL32_DEFAULT(VT_SETMODE),
  444. IOCTL32_DEFAULT(VT_GETMODE),
  445. IOCTL32_DEFAULT(VT_GETSTATE),
  446. IOCTL32_DEFAULT(VT_OPENQRY),
  447. IOCTL32_DEFAULT(VT_ACTIVATE),
  448. IOCTL32_DEFAULT(VT_WAITACTIVE),
  449. IOCTL32_DEFAULT(VT_RELDISP),
  450. IOCTL32_DEFAULT(VT_DISALLOCATE),
  451. IOCTL32_DEFAULT(VT_RESIZE),
  452. IOCTL32_DEFAULT(VT_RESIZEX),
  453. IOCTL32_DEFAULT(VT_LOCKSWITCH),
  454. IOCTL32_DEFAULT(VT_UNLOCKSWITCH),
  455. IOCTL32_DEFAULT(SIOCGSTAMP),
  456. IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32),
  457. IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf),
  458. IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc),
  459. IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc),
  460. IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc),
  461. IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc),
  462. IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc),
  463. IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc),
  464. IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc),
  465. IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc),
  466. IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc),
  467. IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc),
  468. IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc),
  469. IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc),
  470. IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc),
  471. IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc),
  472. IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc),
  473. IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc),
  474. IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc),
  475. IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc),
  476. IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc),
  477. IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc),
  478. IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc),
  479. IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc),
  480. IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc),
  481. IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc),
  482. IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc),
  483. IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc),
  484. IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc),
  485. IOCTL32_HANDLER(SIOCADDRT, routing_ioctl),
  486. IOCTL32_HANDLER(SIOCDELRT, routing_ioctl),
  487. IOCTL32_HANDLER(SIOCBONDENSLAVE, bond_ioctl),
  488. IOCTL32_HANDLER(SIOCBONDRELEASE, bond_ioctl),
  489. IOCTL32_HANDLER(SIOCBONDSETHWADDR, bond_ioctl),
  490. IOCTL32_HANDLER(SIOCBONDSLAVEINFOQUERY, bond_ioctl),
  491. IOCTL32_HANDLER(SIOCBONDINFOQUERY, bond_ioctl),
  492. IOCTL32_HANDLER(SIOCBONDCHANGEACTIVE, bond_ioctl),
  493. IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl),
  494. IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl),
  495. IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
  496. IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl),
  497. IOCTL32_HANDLER(BLKGETSIZE, w_long)
  498. };
  499. #define NR_IOCTL32_HANDLERS (sizeof(ioctl32_handler_table) /
  500.  sizeof(ioctl32_handler_table[0]))
  501. static struct ioctl32_list *ioctl32_hash_table[1024];
  502. static inline int ioctl32_hash(unsigned int cmd)
  503. {
  504. return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
  505. }
  506. int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
  507. {
  508. int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
  509. struct file *filp;
  510. struct ioctl32_list *l;
  511. int error;
  512. l = ioctl32_hash_table[ioctl32_hash(cmd)];
  513. error = -EBADF;
  514. filp = fget(fd);
  515. if (!filp)
  516. return error;
  517. if (!filp->f_op || !filp->f_op->ioctl) {
  518. error = sys_ioctl (fd, cmd, arg);
  519. goto out;
  520. }
  521. while (l && l->handler.cmd != cmd)
  522. l = l->next;
  523. if (l) {
  524. handler = (void *)l->handler.function;
  525. error = handler(fd, cmd, arg, filp);
  526. } else {
  527. error = -EINVAL;
  528. printk("unknown ioctl: %08xn", cmd);
  529. }
  530. out:
  531. fput(filp);
  532. return error;
  533. }
  534. static void ioctl32_insert(struct ioctl32_list *entry)
  535. {
  536. int hash = ioctl32_hash(entry->handler.cmd);
  537. if (!ioctl32_hash_table[hash])
  538. ioctl32_hash_table[hash] = entry;
  539. else {
  540. struct ioctl32_list *l;
  541. l = ioctl32_hash_table[hash];
  542. while (l->next)
  543. l = l->next;
  544. l->next = entry;
  545. entry->next = 0;
  546. }
  547. }
  548. static int __init init_ioctl32(void)
  549. {
  550. int i;
  551. for (i = 0; i < NR_IOCTL32_HANDLERS; i++)
  552. ioctl32_insert(&ioctl32_handler_table[i]);
  553. return 0;
  554. }
  555. __initcall(init_ioctl32);