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