1/* $Id: socksys.c,v 1.1.1.1 2008/10/15 03:26:19 james26_jang 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#include <linux/types.h> 10#include <linux/kernel.h> 11#include <linux/sched.h> 12#include <linux/smp.h> 13#include <linux/smp_lock.h> 14#include <linux/ioctl.h> 15#include <linux/fs.h> 16#include <linux/file.h> 17#include <linux/init.h> 18#include <linux/poll.h> 19#include <linux/slab.h> 20#include <linux/in.h> 21#include <linux/devfs_fs_kernel.h> 22 23#include <asm/uaccess.h> 24#include <asm/termios.h> 25 26#include "conv.h" 27#include "socksys.h" 28 29extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, 30 unsigned long arg); 31 32static int af_inet_protocols[] = { 33IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP, 34IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW, 350, 0, 0, 0, 0, 0, 36}; 37 38#ifndef DEBUG_SOLARIS_KMALLOC 39 40#define mykmalloc kmalloc 41#define mykfree kfree 42 43#else 44 45extern void * mykmalloc(size_t s, int gfp); 46extern void mykfree(void *); 47 48#endif 49 50static unsigned int (*sock_poll)(struct file *, poll_table *); 51 52static struct file_operations socksys_file_ops = { 53 /* Currently empty */ 54}; 55 56static int socksys_open(struct inode * inode, struct file * filp) 57{ 58 int family, type, protocol, fd; 59 struct dentry *dentry; 60 int (*sys_socket)(int,int,int) = 61 (int (*)(int,int,int))SUNOS(97); 62 struct sol_socket_struct * sock; 63 64 family = ((MINOR(inode->i_rdev) >> 4) & 0xf); 65 switch (family) { 66 case AF_UNIX: 67 type = SOCK_STREAM; 68 protocol = 0; 69 break; 70 case AF_INET: 71 protocol = af_inet_protocols[MINOR(inode->i_rdev) & 0xf]; 72 switch (protocol) { 73 case IPPROTO_TCP: type = SOCK_STREAM; break; 74 case IPPROTO_UDP: type = SOCK_DGRAM; break; 75 default: type = SOCK_RAW; break; 76 } 77 break; 78 default: 79 type = SOCK_RAW; 80 protocol = 0; 81 break; 82 } 83 84 fd = sys_socket(family, type, protocol); 85 if (fd < 0) 86 return fd; 87 /* 88 * N.B. The following operations are not legal! 89 * Try instead: 90 * d_delete(filp->f_dentry), then d_instantiate with sock inode 91 */ 92 dentry = filp->f_dentry; 93 filp->f_dentry = dget(fcheck(fd)->f_dentry); 94 filp->f_dentry->d_inode->i_rdev = inode->i_rdev; 95 filp->f_dentry->d_inode->i_flock = inode->i_flock; 96 filp->f_dentry->d_inode->u.socket_i.file = filp; 97 filp->f_op = &socksys_file_ops; 98 sock = (struct sol_socket_struct*) 99 mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL); 100 if (!sock) return -ENOMEM; 101 SOLDD(("sock=%016lx(%016lx)\n", sock, filp)); 102 sock->magic = SOLARIS_SOCKET_MAGIC; 103 sock->modcount = 0; 104 sock->state = TS_UNBND; 105 sock->offset = 0; 106 sock->pfirst = sock->plast = NULL; 107 filp->private_data = sock; 108 SOLDD(("filp->private_data %016lx\n", filp->private_data)); 109 110 sys_close(fd); 111 dput(dentry); 112 return 0; 113} 114 115static int socksys_release(struct inode * inode, struct file * filp) 116{ 117 struct sol_socket_struct * sock; 118 struct T_primsg *it; 119 120 lock_kernel(); 121 sock = (struct sol_socket_struct *)filp->private_data; 122 SOLDD(("sock release %016lx(%016lx)\n", sock, filp)); 123 it = sock->pfirst; 124 while (it) { 125 struct T_primsg *next = it->next; 126 127 SOLDD(("socksys_release %016lx->%016lx\n", it, next)); 128 mykfree((char*)it); 129 it = next; 130 } 131 filp->private_data = NULL; 132 SOLDD(("socksys_release %016lx\n", sock)); 133 mykfree((char*)sock); 134 unlock_kernel(); 135 return 0; 136} 137 138static unsigned int socksys_poll(struct file * filp, poll_table * wait) 139{ 140 struct inode *ino; 141 unsigned int mask = 0; 142 143 ino=filp->f_dentry->d_inode; 144 if (ino && ino->i_sock) { 145 struct sol_socket_struct *sock; 146 sock = (struct sol_socket_struct*)filp->private_data; 147 if (sock && sock->pfirst) { 148 mask |= POLLIN | POLLRDNORM; 149 if (sock->pfirst->pri == MSG_HIPRI) 150 mask |= POLLPRI; 151 } 152 } 153 if (sock_poll) 154 mask |= (*sock_poll)(filp, wait); 155 return mask; 156} 157 158static struct file_operations socksys_fops = { 159 open: socksys_open, 160 release: socksys_release, 161}; 162 163static devfs_handle_t devfs_handle; 164 165int __init 166init_socksys(void) 167{ 168 int ret; 169 struct file * file; 170 int (*sys_socket)(int,int,int) = 171 (int (*)(int,int,int))SUNOS(97); 172 int (*sys_close)(unsigned int) = 173 (int (*)(unsigned int))SYS(close); 174 175 ret = devfs_register_chrdev (30, "socksys", &socksys_fops); 176 if (ret < 0) { 177 printk ("Couldn't register socksys character device\n"); 178 return ret; 179 } 180 ret = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 181 if (ret < 0) { 182 printk ("Couldn't create socket\n"); 183 return ret; 184 } 185 devfs_handle = devfs_register (NULL, "socksys", DEVFS_FL_DEFAULT, 186 30, 0, 187 S_IFCHR | S_IRUSR | S_IWUSR, 188 &socksys_fops, NULL); 189 file = fcheck(ret); 190 /* N.B. Is this valid? Suppose the f_ops are in a module ... */ 191 socksys_file_ops = *file->f_op; 192 sys_close(ret); 193 sock_poll = socksys_file_ops.poll; 194 socksys_file_ops.poll = socksys_poll; 195 socksys_file_ops.release = socksys_release; 196 return 0; 197} 198 199void 200cleanup_socksys(void) 201{ 202 if (devfs_unregister_chrdev(30, "socksys")) 203 printk ("Couldn't unregister socksys character device\n"); 204 devfs_unregister (devfs_handle); 205} 206