1 /* 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6 #include "linux/list.h" 7 #include "linux/sched.h" 8 #include "linux/slab.h" 9 #include "linux/interrupt.h" 10 #include "linux/spinlock.h" 11 #include "linux/errno.h" 12 #include "asm/atomic.h" 13 #include "asm/semaphore.h" 14 #include "asm/errno.h" 15 #include "kern_util.h" 16 #include "kern.h" 17 #include "irq_user.h" 18 #include "irq_kern.h" 19 #include "port.h" 20 #include "init.h" 21 #include "os.h" 22 23 struct port_list { 24 struct list_head list; 25 atomic_t wait_count; 26 int has_connection; 27 struct completion done; 28 int port; 29 int fd; 30 spinlock_t lock; 31 struct list_head pending; 32 struct list_head connections; 33 }; 34 35 struct port_dev { 36 struct port_list *port; 37 int helper_pid; 38 int telnetd_pid; 39 }; 40 41 struct connection { 42 struct list_head list; 43 int fd; 44 int helper_pid; 45 int socket[2]; 46 int telnetd_pid; 47 struct port_list *port; 48 }; 49 50 static irqreturn_t pipe_interrupt(int irq, void *data) 51 { 52 struct connection *conn = data; 53 int fd; 54 55 fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); 56 if(fd < 0){ 57 if(fd == -EAGAIN) 58 return IRQ_NONE; 59 60 printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", 61 -fd); 62 os_close_file(conn->fd); 63 } 64 65 list_del(&conn->list); 66 67 conn->fd = fd; 68 list_add(&conn->list, &conn->port->connections); 69 70 complete(&conn->port->done); 71 return IRQ_HANDLED; 72 } 73 74 #define NO_WAITER_MSG \ 75 "****\n" \ 76 "There are currently no UML consoles waiting for port connections.\n" \ 77 "Either disconnect from one to make it available or activate some more\n" \ 78 "by enabling more consoles in the UML /etc/inittab.\n" \ 79 "****\n" 80 81 static int port_accept(struct port_list *port) 82 { 83 struct connection *conn; 84 int fd, socket[2], pid, ret = 0; 85 86 fd = port_connection(port->fd, socket, &pid); 87 if(fd < 0){ 88 if(fd != -EAGAIN) 89 printk(KERN_ERR "port_accept : port_connection " 90 "returned %d\n", -fd); 91 goto out; 92 } 93 94 conn = kmalloc(sizeof(*conn), GFP_ATOMIC); 95 if(conn == NULL){ 96 printk(KERN_ERR "port_accept : failed to allocate " 97 "connection\n"); 98 goto out_close; 99 } 100 *conn = ((struct connection) 101 { .list = LIST_HEAD_INIT(conn->list), 102 .fd = fd, 103 .socket = { socket[0], socket[1] }, 104 .telnetd_pid = pid, 105 .port = port }); 106 107 if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, 108 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, 109 "telnetd", conn)){ 110 printk(KERN_ERR "port_accept : failed to get IRQ for " 111 "telnetd\n"); 112 goto out_free; 113 } 114 115 if(atomic_read(&port->wait_count) == 0){ 116 os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); 117 printk("No one waiting for port\n"); 118 } 119 list_add(&conn->list, &port->pending); 120 return 1; 121 122 out_free: 123 kfree(conn); 124 out_close: 125 os_close_file(fd); 126 if(pid != -1) 127 os_kill_process(pid, 1); 128 out: 129 return ret; 130 } 131 132 static DECLARE_MUTEX(ports_sem); 133 static LIST_HEAD(ports); 134 135 void port_work_proc(struct work_struct *unused) 136 { 137 struct port_list *port; 138 struct list_head *ele; 139 unsigned long flags; 140 141 local_irq_save(flags); 142 list_for_each(ele, &ports){ 143 port = list_entry(ele, struct port_list, list); 144 if(!port->has_connection) 145 continue; 146 reactivate_fd(port->fd, ACCEPT_IRQ); 147 while(port_accept(port)) ; 148 port->has_connection = 0; 149 } 150 local_irq_restore(flags); 151 } 152 153 DECLARE_WORK(port_work, port_work_proc); 154 155 static irqreturn_t port_interrupt(int irq, void *data) 156 { 157 struct port_list *port = data; 158 159 port->has_connection = 1; 160 schedule_work(&port_work); 161 return IRQ_HANDLED; 162 } 163 164 void *port_data(int port_num) 165 { 166 struct list_head *ele; 167 struct port_list *port; 168 struct port_dev *dev = NULL; 169 int fd; 170 171 down(&ports_sem); 172 list_for_each(ele, &ports){ 173 port = list_entry(ele, struct port_list, list); 174 if(port->port == port_num) goto found; 175 } 176 port = kmalloc(sizeof(struct port_list), GFP_KERNEL); 177 if(port == NULL){ 178 printk(KERN_ERR "Allocation of port list failed\n"); 179 goto out; 180 } 181 182 fd = port_listen_fd(port_num); 183 if(fd < 0){ 184 printk(KERN_ERR "binding to port %d failed, errno = %d\n", 185 port_num, -fd); 186 goto out_free; 187 } 188 if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, 189 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, 190 "port", port)){ 191 printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); 192 goto out_close; 193 } 194 195 *port = ((struct port_list) 196 { .list = LIST_HEAD_INIT(port->list), 197 .wait_count = ATOMIC_INIT(0), 198 .has_connection = 0, 199 .port = port_num, 200 .fd = fd, 201 .pending = LIST_HEAD_INIT(port->pending), 202 .connections = LIST_HEAD_INIT(port->connections) }); 203 spin_lock_init(&port->lock); 204 init_completion(&port->done); 205 list_add(&port->list, &ports); 206 207 found: 208 dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); 209 if(dev == NULL){ 210 printk(KERN_ERR "Allocation of port device entry failed\n"); 211 goto out; 212 } 213 214 *dev = ((struct port_dev) { .port = port, 215 .helper_pid = -1, 216 .telnetd_pid = -1 }); 217 goto out; 218 219 out_free: 220 kfree(port); 221 out_close: 222 os_close_file(fd); 223 out: 224 up(&ports_sem); 225 return dev; 226 } 227 228 int port_wait(void *data) 229 { 230 struct port_dev *dev = data; 231 struct connection *conn; 232 struct port_list *port = dev->port; 233 int fd; 234 235 atomic_inc(&port->wait_count); 236 while(1){ 237 fd = -ERESTARTSYS; 238 if(wait_for_completion_interruptible(&port->done)) 239 goto out; 240 241 spin_lock(&port->lock); 242 243 conn = list_entry(port->connections.next, struct connection, 244 list); 245 list_del(&conn->list); 246 spin_unlock(&port->lock); 247 248 os_shutdown_socket(conn->socket[0], 1, 1); 249 os_close_file(conn->socket[0]); 250 os_shutdown_socket(conn->socket[1], 1, 1); 251 os_close_file(conn->socket[1]); 252 253 /* This is done here because freeing an IRQ can't be done 254 * within the IRQ handler. So, pipe_interrupt always ups 255 * the semaphore regardless of whether it got a successful 256 * connection. Then we loop here throwing out failed 257 * connections until a good one is found. 258 */ 259 free_irq(TELNETD_IRQ, conn); 260 261 if(conn->fd >= 0) break; 262 os_close_file(conn->fd); 263 kfree(conn); 264 } 265 266 fd = conn->fd; 267 dev->helper_pid = conn->helper_pid; 268 dev->telnetd_pid = conn->telnetd_pid; 269 kfree(conn); 270 out: 271 atomic_dec(&port->wait_count); 272 return fd; 273 } 274 275 void port_remove_dev(void *d) 276 { 277 struct port_dev *dev = d; 278 279 if(dev->helper_pid != -1) 280 os_kill_process(dev->helper_pid, 0); 281 if(dev->telnetd_pid != -1) 282 os_kill_process(dev->telnetd_pid, 1); 283 dev->helper_pid = -1; 284 dev->telnetd_pid = -1; 285 } 286 287 void port_kern_free(void *d) 288 { 289 struct port_dev *dev = d; 290 291 port_remove_dev(dev); 292 kfree(dev); 293 } 294 295 static void free_port(void) 296 { 297 struct list_head *ele; 298 struct port_list *port; 299 300 list_for_each(ele, &ports){ 301 port = list_entry(ele, struct port_list, list); 302 free_irq_by_fd(port->fd); 303 os_close_file(port->fd); 304 } 305 } 306 307 __uml_exitcall(free_port); 308