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