socksys.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /* $Id: socksys.c,v 1.21 2002/02/08 03:57:14 davem Exp $
  2. * socksys.c: /dev/inet/ stuff for Solaris 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. * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
  7. */
  8. /*
  9. * Dave, _please_ give me specifications on this fscking mess so that I
  10. * could at least get it into the state when it wouldn't screw the rest of
  11. * the kernel over. socksys.c and timod.c _stink_ and we are not talking
  12. * H2S here, it's isopropilmercaptan in concentrations way over LD50. -- AV
  13. */
  14. #include <linux/types.h>
  15. #include <linux/kernel.h>
  16. #include <linux/sched.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/ioctl.h>
  20. #include <linux/fs.h>
  21. #include <linux/file.h>
  22. #include <linux/init.h>
  23. #include <linux/poll.h>
  24. #include <linux/slab.h>
  25. #include <linux/syscalls.h>
  26. #include <linux/in.h>
  27. #include <linux/devfs_fs_kernel.h>
  28. #include <net/sock.h>
  29. #include <asm/uaccess.h>
  30. #include <asm/termios.h>
  31. #include "conv.h"
  32. #include "socksys.h"
  33. static int af_inet_protocols[] = {
  34. IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP,
  35. IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW,
  36. 0, 0, 0, 0, 0, 0,
  37. };
  38. #ifndef DEBUG_SOLARIS_KMALLOC
  39. #define mykmalloc kmalloc
  40. #define mykfree kfree
  41. #else
  42. extern void * mykmalloc(size_t s, int gfp);
  43. extern void mykfree(void *);
  44. #endif
  45. static unsigned int (*sock_poll)(struct file *, poll_table *);
  46. static struct file_operations socksys_file_ops = {
  47. /* Currently empty */
  48. };
  49. static int socksys_open(struct inode * inode, struct file * filp)
  50. {
  51. int family, type, protocol, fd;
  52. struct dentry *dentry;
  53. int (*sys_socket)(int,int,int) =
  54. (int (*)(int,int,int))SUNOS(97);
  55. struct sol_socket_struct * sock;
  56. family = ((iminor(inode) >> 4) & 0xf);
  57. switch (family) {
  58. case AF_UNIX:
  59. type = SOCK_STREAM;
  60. protocol = 0;
  61. break;
  62. case AF_INET:
  63. protocol = af_inet_protocols[iminor(inode) & 0xf];
  64. switch (protocol) {
  65. case IPPROTO_TCP: type = SOCK_STREAM; break;
  66. case IPPROTO_UDP: type = SOCK_DGRAM; break;
  67. default: type = SOCK_RAW; break;
  68. }
  69. break;
  70. default:
  71. type = SOCK_RAW;
  72. protocol = 0;
  73. break;
  74. }
  75. fd = sys_socket(family, type, protocol);
  76. if (fd < 0)
  77. return fd;
  78. /*
  79. * N.B. The following operations are not legal!
  80. *
  81. * No shit. WTF is it supposed to do, anyway?
  82. *
  83. * Try instead:
  84. * d_delete(filp->f_dentry), then d_instantiate with sock inode
  85. */
  86. dentry = filp->f_dentry;
  87. filp->f_dentry = dget(fcheck(fd)->f_dentry);
  88. filp->f_dentry->d_inode->i_rdev = inode->i_rdev;
  89. filp->f_dentry->d_inode->i_flock = inode->i_flock;
  90. SOCKET_I(filp->f_dentry->d_inode)->file = filp;
  91. filp->f_op = &socksys_file_ops;
  92. sock = (struct sol_socket_struct*)
  93. mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL);
  94. if (!sock) return -ENOMEM;
  95. SOLDD(("sock=%016lx(%016lx)\n", sock, filp));
  96. sock->magic = SOLARIS_SOCKET_MAGIC;
  97. sock->modcount = 0;
  98. sock->state = TS_UNBND;
  99. sock->offset = 0;
  100. sock->pfirst = sock->plast = NULL;
  101. filp->private_data = sock;
  102. SOLDD(("filp->private_data %016lx\n", filp->private_data));
  103. sys_close(fd);
  104. dput(dentry);
  105. return 0;
  106. }
  107. static int socksys_release(struct inode * inode, struct file * filp)
  108. {
  109. struct sol_socket_struct * sock;
  110. struct T_primsg *it;
  111. /* XXX: check this */
  112. sock = (struct sol_socket_struct *)filp->private_data;
  113. SOLDD(("sock release %016lx(%016lx)\n", sock, filp));
  114. it = sock->pfirst;
  115. while (it) {
  116. struct T_primsg *next = it->next;
  117. SOLDD(("socksys_release %016lx->%016lx\n", it, next));
  118. mykfree((char*)it);
  119. it = next;
  120. }
  121. filp->private_data = NULL;
  122. SOLDD(("socksys_release %016lx\n", sock));
  123. mykfree((char*)sock);
  124. return 0;
  125. }
  126. static unsigned int socksys_poll(struct file * filp, poll_table * wait)
  127. {
  128. struct inode *ino;
  129. unsigned int mask = 0;
  130. ino=filp->f_dentry->d_inode;
  131. if (ino && S_ISSOCK(ino->i_mode)) {
  132. struct sol_socket_struct *sock;
  133. sock = (struct sol_socket_struct*)filp->private_data;
  134. if (sock && sock->pfirst) {
  135. mask |= POLLIN | POLLRDNORM;
  136. if (sock->pfirst->pri == MSG_HIPRI)
  137. mask |= POLLPRI;
  138. }
  139. }
  140. if (sock_poll)
  141. mask |= (*sock_poll)(filp, wait);
  142. return mask;
  143. }
  144. static struct file_operations socksys_fops = {
  145. .open = socksys_open,
  146. .release = socksys_release,
  147. };
  148. int __init
  149. init_socksys(void)
  150. {
  151. int ret;
  152. struct file * file;
  153. int (*sys_socket)(int,int,int) =
  154. (int (*)(int,int,int))SUNOS(97);
  155. int (*sys_close)(unsigned int) =
  156. (int (*)(unsigned int))SYS(close);
  157. ret = register_chrdev (30, "socksys", &socksys_fops);
  158. if (ret < 0) {
  159. printk ("Couldn't register socksys character device\n");
  160. return ret;
  161. }
  162. ret = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  163. if (ret < 0) {
  164. printk ("Couldn't create socket\n");
  165. return ret;
  166. }
  167. devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUSR|S_IWUSR, "socksys");
  168. file = fcheck(ret);
  169. /* N.B. Is this valid? Suppose the f_ops are in a module ... */
  170. socksys_file_ops = *file->f_op;
  171. sys_close(ret);
  172. sock_poll = socksys_file_ops.poll;
  173. socksys_file_ops.poll = socksys_poll;
  174. socksys_file_ops.release = socksys_release;
  175. return 0;
  176. }
  177. void
  178. cleanup_socksys(void)
  179. {
  180. if (unregister_chrdev(30, "socksys"))
  181. printk ("Couldn't unregister socksys character device\n");
  182. devfs_remove ("socksys");
  183. }