diff options
Diffstat (limited to 'arch/um/drivers')
| -rw-r--r-- | arch/um/drivers/Makefile | 4 | ||||
| -rw-r--r-- | arch/um/drivers/harddog_kern.c | 14 | ||||
| -rw-r--r-- | arch/um/drivers/hostaudio_kern.c | 12 | ||||
| -rw-r--r-- | arch/um/drivers/line.c | 13 | ||||
| -rw-r--r-- | arch/um/drivers/mcast.h | 24 | ||||
| -rw-r--r-- | arch/um/drivers/mcast_kern.c | 120 | ||||
| -rw-r--r-- | arch/um/drivers/mcast_user.c | 165 | ||||
| -rw-r--r-- | arch/um/drivers/mconsole_kern.c | 22 | ||||
| -rw-r--r-- | arch/um/drivers/mmapper_kern.c | 12 | ||||
| -rw-r--r-- | arch/um/drivers/random.c | 1 | ||||
| -rw-r--r-- | arch/um/drivers/ubd_kern.c | 13 | ||||
| -rw-r--r-- | arch/um/drivers/umcast.h | 27 | ||||
| -rw-r--r-- | arch/um/drivers/umcast_kern.c | 188 | ||||
| -rw-r--r-- | arch/um/drivers/umcast_user.c | 186 | ||||
| -rw-r--r-- | arch/um/drivers/xterm.c | 2 |
15 files changed, 441 insertions, 362 deletions
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 1d9b6ae967b0..e7582e1d248c 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | slip-objs := slip_kern.o slip_user.o | 9 | slip-objs := slip_kern.o slip_user.o |
| 10 | slirp-objs := slirp_kern.o slirp_user.o | 10 | slirp-objs := slirp_kern.o slirp_user.o |
| 11 | daemon-objs := daemon_kern.o daemon_user.o | 11 | daemon-objs := daemon_kern.o daemon_user.o |
| 12 | mcast-objs := mcast_kern.o mcast_user.o | 12 | umcast-objs := umcast_kern.o umcast_user.o |
| 13 | net-objs := net_kern.o net_user.o | 13 | net-objs := net_kern.o net_user.o |
| 14 | mconsole-objs := mconsole_kern.o mconsole_user.o | 14 | mconsole-objs := mconsole_kern.o mconsole_user.o |
| 15 | hostaudio-objs := hostaudio_kern.o | 15 | hostaudio-objs := hostaudio_kern.o |
| @@ -44,7 +44,7 @@ obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o | |||
| 44 | obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o | 44 | obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o |
| 45 | obj-$(CONFIG_UML_NET_DAEMON) += daemon.o | 45 | obj-$(CONFIG_UML_NET_DAEMON) += daemon.o |
| 46 | obj-$(CONFIG_UML_NET_VDE) += vde.o | 46 | obj-$(CONFIG_UML_NET_VDE) += vde.o |
| 47 | obj-$(CONFIG_UML_NET_MCAST) += mcast.o | 47 | obj-$(CONFIG_UML_NET_MCAST) += umcast.o |
| 48 | obj-$(CONFIG_UML_NET_PCAP) += pcap.o | 48 | obj-$(CONFIG_UML_NET_PCAP) += pcap.o |
| 49 | obj-$(CONFIG_UML_NET) += net.o | 49 | obj-$(CONFIG_UML_NET) += net.o |
| 50 | obj-$(CONFIG_MCONSOLE) += mconsole.o | 50 | obj-$(CONFIG_MCONSOLE) += mconsole.o |
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index cfcac1ff4cf2..2d0266d0254d 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | #include <linux/miscdevice.h> | 42 | #include <linux/miscdevice.h> |
| 43 | #include <linux/watchdog.h> | 43 | #include <linux/watchdog.h> |
| 44 | #include <linux/reboot.h> | 44 | #include <linux/reboot.h> |
| 45 | #include <linux/smp_lock.h> | 45 | #include <linux/mutex.h> |
| 46 | #include <linux/init.h> | 46 | #include <linux/init.h> |
| 47 | #include <linux/spinlock.h> | 47 | #include <linux/spinlock.h> |
| 48 | #include <asm/uaccess.h> | 48 | #include <asm/uaccess.h> |
| @@ -50,6 +50,7 @@ | |||
| 50 | 50 | ||
| 51 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
| 52 | 52 | ||
| 53 | static DEFINE_MUTEX(harddog_mutex); | ||
| 53 | static DEFINE_SPINLOCK(lock); | 54 | static DEFINE_SPINLOCK(lock); |
| 54 | static int timer_alive; | 55 | static int timer_alive; |
| 55 | static int harddog_in_fd = -1; | 56 | static int harddog_in_fd = -1; |
| @@ -66,7 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file) | |||
| 66 | int err = -EBUSY; | 67 | int err = -EBUSY; |
| 67 | char *sock = NULL; | 68 | char *sock = NULL; |
| 68 | 69 | ||
| 69 | lock_kernel(); | 70 | mutex_lock(&harddog_mutex); |
| 70 | spin_lock(&lock); | 71 | spin_lock(&lock); |
| 71 | if(timer_alive) | 72 | if(timer_alive) |
| 72 | goto err; | 73 | goto err; |
| @@ -83,11 +84,11 @@ static int harddog_open(struct inode *inode, struct file *file) | |||
| 83 | 84 | ||
| 84 | timer_alive = 1; | 85 | timer_alive = 1; |
| 85 | spin_unlock(&lock); | 86 | spin_unlock(&lock); |
| 86 | unlock_kernel(); | 87 | mutex_unlock(&harddog_mutex); |
| 87 | return nonseekable_open(inode, file); | 88 | return nonseekable_open(inode, file); |
| 88 | err: | 89 | err: |
| 89 | spin_unlock(&lock); | 90 | spin_unlock(&lock); |
| 90 | unlock_kernel(); | 91 | mutex_unlock(&harddog_mutex); |
| 91 | return err; | 92 | return err; |
| 92 | } | 93 | } |
| 93 | 94 | ||
| @@ -153,9 +154,9 @@ static long harddog_ioctl(struct file *file, | |||
| 153 | { | 154 | { |
| 154 | long ret; | 155 | long ret; |
| 155 | 156 | ||
| 156 | lock_kernel(); | 157 | mutex_lock(&harddog_mutex); |
| 157 | ret = harddog_ioctl_unlocked(file, cmd, arg); | 158 | ret = harddog_ioctl_unlocked(file, cmd, arg); |
| 158 | unlock_kernel(); | 159 | mutex_unlock(&harddog_mutex); |
| 159 | 160 | ||
| 160 | return ret; | 161 | return ret; |
| 161 | } | 162 | } |
| @@ -166,6 +167,7 @@ static const struct file_operations harddog_fops = { | |||
| 166 | .unlocked_ioctl = harddog_ioctl, | 167 | .unlocked_ioctl = harddog_ioctl, |
| 167 | .open = harddog_open, | 168 | .open = harddog_open, |
| 168 | .release = harddog_release, | 169 | .release = harddog_release, |
| 170 | .llseek = no_llseek, | ||
| 169 | }; | 171 | }; |
| 170 | 172 | ||
| 171 | static struct miscdevice harddog_miscdev = { | 173 | static struct miscdevice harddog_miscdev = { |
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 63c740a85b4c..f9f6a4e20590 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "linux/slab.h" | 8 | #include "linux/slab.h" |
| 9 | #include "linux/sound.h" | 9 | #include "linux/sound.h" |
| 10 | #include "linux/soundcard.h" | 10 | #include "linux/soundcard.h" |
| 11 | #include "linux/smp_lock.h" | 11 | #include "linux/mutex.h" |
| 12 | #include "asm/uaccess.h" | 12 | #include "asm/uaccess.h" |
| 13 | #include "init.h" | 13 | #include "init.h" |
| 14 | #include "os.h" | 14 | #include "os.h" |
| @@ -63,6 +63,8 @@ static int set_mixer(char *name, int *add) | |||
| 63 | __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); | 63 | __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); |
| 64 | #endif | 64 | #endif |
| 65 | 65 | ||
| 66 | static DEFINE_MUTEX(hostaudio_mutex); | ||
| 67 | |||
| 66 | /* /dev/dsp file operations */ | 68 | /* /dev/dsp file operations */ |
| 67 | 69 | ||
| 68 | static ssize_t hostaudio_read(struct file *file, char __user *buffer, | 70 | static ssize_t hostaudio_read(struct file *file, char __user *buffer, |
| @@ -198,9 +200,9 @@ static int hostaudio_open(struct inode *inode, struct file *file) | |||
| 198 | w = 1; | 200 | w = 1; |
| 199 | 201 | ||
| 200 | kparam_block_sysfs_write(dsp); | 202 | kparam_block_sysfs_write(dsp); |
| 201 | lock_kernel(); | 203 | mutex_lock(&hostaudio_mutex); |
| 202 | ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); | 204 | ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); |
| 203 | unlock_kernel(); | 205 | mutex_unlock(&hostaudio_mutex); |
| 204 | kparam_unblock_sysfs_write(dsp); | 206 | kparam_unblock_sysfs_write(dsp); |
| 205 | 207 | ||
| 206 | if (ret < 0) { | 208 | if (ret < 0) { |
| @@ -259,9 +261,9 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) | |||
| 259 | w = 1; | 261 | w = 1; |
| 260 | 262 | ||
| 261 | kparam_block_sysfs_write(mixer); | 263 | kparam_block_sysfs_write(mixer); |
| 262 | lock_kernel(); | 264 | mutex_lock(&hostaudio_mutex); |
| 263 | ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); | 265 | ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); |
| 264 | unlock_kernel(); | 266 | mutex_unlock(&hostaudio_mutex); |
| 265 | kparam_unblock_sysfs_write(mixer); | 267 | kparam_unblock_sysfs_write(mixer); |
| 266 | 268 | ||
| 267 | if (ret < 0) { | 269 | if (ret < 0) { |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 7f7338c90784..35dd0b86401a 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
| @@ -255,8 +255,8 @@ static const struct { | |||
| 255 | { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" }, | 255 | { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" }, |
| 256 | }; | 256 | }; |
| 257 | 257 | ||
| 258 | int line_ioctl(struct tty_struct *tty, struct file * file, | 258 | int line_ioctl(struct tty_struct *tty, unsigned int cmd, |
| 259 | unsigned int cmd, unsigned long arg) | 259 | unsigned long arg) |
| 260 | { | 260 | { |
| 261 | int ret; | 261 | int ret; |
| 262 | int i; | 262 | int i; |
| @@ -727,6 +727,9 @@ struct winch { | |||
| 727 | 727 | ||
| 728 | static void free_winch(struct winch *winch, int free_irq_ok) | 728 | static void free_winch(struct winch *winch, int free_irq_ok) |
| 729 | { | 729 | { |
| 730 | if (free_irq_ok) | ||
| 731 | free_irq(WINCH_IRQ, winch); | ||
| 732 | |||
| 730 | list_del(&winch->list); | 733 | list_del(&winch->list); |
| 731 | 734 | ||
| 732 | if (winch->pid != -1) | 735 | if (winch->pid != -1) |
| @@ -735,8 +738,6 @@ static void free_winch(struct winch *winch, int free_irq_ok) | |||
| 735 | os_close_file(winch->fd); | 738 | os_close_file(winch->fd); |
| 736 | if (winch->stack != 0) | 739 | if (winch->stack != 0) |
| 737 | free_stack(winch->stack, 0); | 740 | free_stack(winch->stack, 0); |
| 738 | if (free_irq_ok) | ||
| 739 | free_irq(WINCH_IRQ, winch); | ||
| 740 | kfree(winch); | 741 | kfree(winch); |
| 741 | } | 742 | } |
| 742 | 743 | ||
| @@ -820,12 +821,12 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, | |||
| 820 | 821 | ||
| 821 | static void unregister_winch(struct tty_struct *tty) | 822 | static void unregister_winch(struct tty_struct *tty) |
| 822 | { | 823 | { |
| 823 | struct list_head *ele; | 824 | struct list_head *ele, *next; |
| 824 | struct winch *winch; | 825 | struct winch *winch; |
| 825 | 826 | ||
| 826 | spin_lock(&winch_handler_lock); | 827 | spin_lock(&winch_handler_lock); |
| 827 | 828 | ||
| 828 | list_for_each(ele, &winch_handlers) { | 829 | list_for_each_safe(ele, next, &winch_handlers) { |
| 829 | winch = list_entry(ele, struct winch, list); | 830 | winch = list_entry(ele, struct winch, list); |
| 830 | if (winch->tty == tty) { | 831 | if (winch->tty == tty) { |
| 831 | free_winch(winch, 1); | 832 | free_winch(winch, 1); |
diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h deleted file mode 100644 index 6fa282e896be..000000000000 --- a/arch/um/drivers/mcast.h +++ /dev/null | |||
| @@ -1,24 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __DRIVERS_MCAST_H | ||
| 7 | #define __DRIVERS_MCAST_H | ||
| 8 | |||
| 9 | #include "net_user.h" | ||
| 10 | |||
| 11 | struct mcast_data { | ||
| 12 | char *addr; | ||
| 13 | unsigned short port; | ||
| 14 | void *mcast_addr; | ||
| 15 | int ttl; | ||
| 16 | void *dev; | ||
| 17 | }; | ||
| 18 | |||
| 19 | extern const struct net_user_info mcast_user_info; | ||
| 20 | |||
| 21 | extern int mcast_user_write(int fd, void *buf, int len, | ||
| 22 | struct mcast_data *pri); | ||
| 23 | |||
| 24 | #endif | ||
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c deleted file mode 100644 index ffc6416d5ed7..000000000000 --- a/arch/um/drivers/mcast_kern.c +++ /dev/null | |||
| @@ -1,120 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * user-mode-linux networking multicast transport | ||
| 3 | * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> | ||
| 4 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
| 5 | * | ||
| 6 | * based on the existing uml-networking code, which is | ||
| 7 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | ||
| 8 | * James Leu (jleu@mindspring.net). | ||
| 9 | * Copyright (C) 2001 by various other people who didn't put their name here. | ||
| 10 | * | ||
| 11 | * Licensed under the GPL. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include "linux/init.h" | ||
| 15 | #include <linux/netdevice.h> | ||
| 16 | #include "mcast.h" | ||
| 17 | #include "net_kern.h" | ||
| 18 | |||
| 19 | struct mcast_init { | ||
| 20 | char *addr; | ||
| 21 | int port; | ||
| 22 | int ttl; | ||
| 23 | }; | ||
| 24 | |||
| 25 | static void mcast_init(struct net_device *dev, void *data) | ||
| 26 | { | ||
| 27 | struct uml_net_private *pri; | ||
| 28 | struct mcast_data *dpri; | ||
| 29 | struct mcast_init *init = data; | ||
| 30 | |||
| 31 | pri = netdev_priv(dev); | ||
| 32 | dpri = (struct mcast_data *) pri->user; | ||
| 33 | dpri->addr = init->addr; | ||
| 34 | dpri->port = init->port; | ||
| 35 | dpri->ttl = init->ttl; | ||
| 36 | dpri->dev = dev; | ||
| 37 | |||
| 38 | printk("mcast backend multicast address: %s:%u, TTL:%u\n", | ||
| 39 | dpri->addr, dpri->port, dpri->ttl); | ||
| 40 | } | ||
| 41 | |||
| 42 | static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) | ||
| 43 | { | ||
| 44 | return net_recvfrom(fd, skb_mac_header(skb), | ||
| 45 | skb->dev->mtu + ETH_HEADER_OTHER); | ||
| 46 | } | ||
| 47 | |||
| 48 | static int mcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) | ||
| 49 | { | ||
| 50 | return mcast_user_write(fd, skb->data, skb->len, | ||
| 51 | (struct mcast_data *) &lp->user); | ||
| 52 | } | ||
| 53 | |||
| 54 | static const struct net_kern_info mcast_kern_info = { | ||
| 55 | .init = mcast_init, | ||
| 56 | .protocol = eth_protocol, | ||
| 57 | .read = mcast_read, | ||
| 58 | .write = mcast_write, | ||
| 59 | }; | ||
| 60 | |||
| 61 | static int mcast_setup(char *str, char **mac_out, void *data) | ||
| 62 | { | ||
| 63 | struct mcast_init *init = data; | ||
| 64 | char *port_str = NULL, *ttl_str = NULL, *remain; | ||
| 65 | char *last; | ||
| 66 | |||
| 67 | *init = ((struct mcast_init) | ||
| 68 | { .addr = "239.192.168.1", | ||
| 69 | .port = 1102, | ||
| 70 | .ttl = 1 }); | ||
| 71 | |||
| 72 | remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, | ||
| 73 | NULL); | ||
| 74 | if (remain != NULL) { | ||
| 75 | printk(KERN_ERR "mcast_setup - Extra garbage on " | ||
| 76 | "specification : '%s'\n", remain); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | if (port_str != NULL) { | ||
| 81 | init->port = simple_strtoul(port_str, &last, 10); | ||
| 82 | if ((*last != '\0') || (last == port_str)) { | ||
| 83 | printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", | ||
| 84 | port_str); | ||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | if (ttl_str != NULL) { | ||
| 90 | init->ttl = simple_strtoul(ttl_str, &last, 10); | ||
| 91 | if ((*last != '\0') || (last == ttl_str)) { | ||
| 92 | printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", | ||
| 93 | ttl_str); | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, | ||
| 99 | init->port, init->ttl); | ||
| 100 | |||
| 101 | return 1; | ||
| 102 | } | ||
| 103 | |||
| 104 | static struct transport mcast_transport = { | ||
| 105 | .list = LIST_HEAD_INIT(mcast_transport.list), | ||
| 106 | .name = "mcast", | ||
| 107 | .setup = mcast_setup, | ||
| 108 | .user = &mcast_user_info, | ||
| 109 | .kern = &mcast_kern_info, | ||
| 110 | .private_size = sizeof(struct mcast_data), | ||
| 111 | .setup_size = sizeof(struct mcast_init), | ||
| 112 | }; | ||
| 113 | |||
| 114 | static int register_mcast(void) | ||
| 115 | { | ||
| 116 | register_transport(&mcast_transport); | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | late_initcall(register_mcast); | ||
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c deleted file mode 100644 index ee19e91568a2..000000000000 --- a/arch/um/drivers/mcast_user.c +++ /dev/null | |||
| @@ -1,165 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * user-mode-linux networking multicast transport | ||
| 3 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
| 4 | * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> | ||
| 5 | * | ||
| 6 | * based on the existing uml-networking code, which is | ||
| 7 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | ||
| 8 | * James Leu (jleu@mindspring.net). | ||
| 9 | * Copyright (C) 2001 by various other people who didn't put their name here. | ||
| 10 | * | ||
| 11 | * Licensed under the GPL. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <unistd.h> | ||
| 16 | #include <errno.h> | ||
| 17 | #include <netinet/in.h> | ||
| 18 | #include "kern_constants.h" | ||
| 19 | #include "mcast.h" | ||
| 20 | #include "net_user.h" | ||
| 21 | #include "um_malloc.h" | ||
| 22 | #include "user.h" | ||
| 23 | |||
| 24 | static struct sockaddr_in *new_addr(char *addr, unsigned short port) | ||
| 25 | { | ||
| 26 | struct sockaddr_in *sin; | ||
| 27 | |||
| 28 | sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); | ||
| 29 | if (sin == NULL) { | ||
| 30 | printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " | ||
| 31 | "failed\n"); | ||
| 32 | return NULL; | ||
| 33 | } | ||
| 34 | sin->sin_family = AF_INET; | ||
| 35 | sin->sin_addr.s_addr = in_aton(addr); | ||
| 36 | sin->sin_port = htons(port); | ||
| 37 | return sin; | ||
| 38 | } | ||
| 39 | |||
| 40 | static int mcast_user_init(void *data, void *dev) | ||
| 41 | { | ||
| 42 | struct mcast_data *pri = data; | ||
| 43 | |||
| 44 | pri->mcast_addr = new_addr(pri->addr, pri->port); | ||
| 45 | pri->dev = dev; | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | static void mcast_remove(void *data) | ||
| 50 | { | ||
| 51 | struct mcast_data *pri = data; | ||
| 52 | |||
| 53 | kfree(pri->mcast_addr); | ||
| 54 | pri->mcast_addr = NULL; | ||
| 55 | } | ||
| 56 | |||
| 57 | static int mcast_open(void *data) | ||
| 58 | { | ||
| 59 | struct mcast_data *pri = data; | ||
| 60 | struct sockaddr_in *sin = pri->mcast_addr; | ||
| 61 | struct ip_mreq mreq; | ||
| 62 | int fd, yes = 1, err = -EINVAL; | ||
| 63 | |||
| 64 | |||
| 65 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) | ||
| 66 | goto out; | ||
| 67 | |||
| 68 | fd = socket(AF_INET, SOCK_DGRAM, 0); | ||
| 69 | |||
| 70 | if (fd < 0) { | ||
| 71 | err = -errno; | ||
| 72 | printk(UM_KERN_ERR "mcast_open : data socket failed, " | ||
| 73 | "errno = %d\n", errno); | ||
| 74 | goto out; | ||
| 75 | } | ||
| 76 | |||
| 77 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { | ||
| 78 | err = -errno; | ||
| 79 | printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, " | ||
| 80 | "errno = %d\n", errno); | ||
| 81 | goto out_close; | ||
| 82 | } | ||
| 83 | |||
| 84 | /* set ttl according to config */ | ||
| 85 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, | ||
| 86 | sizeof(pri->ttl)) < 0) { | ||
| 87 | err = -errno; | ||
| 88 | printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, " | ||
| 89 | "error = %d\n", errno); | ||
| 90 | goto out_close; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* set LOOP, so data does get fed back to local sockets */ | ||
| 94 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { | ||
| 95 | err = -errno; | ||
| 96 | printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, " | ||
| 97 | "error = %d\n", errno); | ||
| 98 | goto out_close; | ||
| 99 | } | ||
| 100 | |||
| 101 | /* bind socket to mcast address */ | ||
| 102 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { | ||
| 103 | err = -errno; | ||
| 104 | printk(UM_KERN_ERR "mcast_open : data bind failed, " | ||
| 105 | "errno = %d\n", errno); | ||
| 106 | goto out_close; | ||
| 107 | } | ||
| 108 | |||
| 109 | /* subscribe to the multicast group */ | ||
| 110 | mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; | ||
| 111 | mreq.imr_interface.s_addr = 0; | ||
| 112 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, | ||
| 113 | &mreq, sizeof(mreq)) < 0) { | ||
| 114 | err = -errno; | ||
| 115 | printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, " | ||
| 116 | "error = %d\n", errno); | ||
| 117 | printk(UM_KERN_ERR "There appears not to be a multicast-" | ||
| 118 | "capable network interface on the host.\n"); | ||
| 119 | printk(UM_KERN_ERR "eth0 should be configured in order to use " | ||
| 120 | "the multicast transport.\n"); | ||
| 121 | goto out_close; | ||
| 122 | } | ||
| 123 | |||
| 124 | return fd; | ||
| 125 | |||
| 126 | out_close: | ||
| 127 | close(fd); | ||
| 128 | out: | ||
| 129 | return err; | ||
| 130 | } | ||
| 131 | |||
| 132 | static void mcast_close(int fd, void *data) | ||
| 133 | { | ||
| 134 | struct ip_mreq mreq; | ||
| 135 | struct mcast_data *pri = data; | ||
| 136 | struct sockaddr_in *sin = pri->mcast_addr; | ||
| 137 | |||
| 138 | mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; | ||
| 139 | mreq.imr_interface.s_addr = 0; | ||
| 140 | if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, | ||
| 141 | &mreq, sizeof(mreq)) < 0) { | ||
| 142 | printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, " | ||
| 143 | "error = %d\n", errno); | ||
| 144 | } | ||
| 145 | |||
| 146 | close(fd); | ||
| 147 | } | ||
| 148 | |||
| 149 | int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) | ||
| 150 | { | ||
| 151 | struct sockaddr_in *data_addr = pri->mcast_addr; | ||
| 152 | |||
| 153 | return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); | ||
| 154 | } | ||
| 155 | |||
| 156 | const struct net_user_info mcast_user_info = { | ||
| 157 | .init = mcast_user_init, | ||
| 158 | .open = mcast_open, | ||
| 159 | .close = mcast_close, | ||
| 160 | .remove = mcast_remove, | ||
| 161 | .add_address = NULL, | ||
| 162 | .delete_address = NULL, | ||
| 163 | .mtu = ETH_MAX_PACKET, | ||
| 164 | .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, | ||
| 165 | }; | ||
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index ebc680717e59..c70e047eed72 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
| @@ -124,35 +124,18 @@ void mconsole_log(struct mc_request *req) | |||
| 124 | #if 0 | 124 | #if 0 |
| 125 | void mconsole_proc(struct mc_request *req) | 125 | void mconsole_proc(struct mc_request *req) |
| 126 | { | 126 | { |
| 127 | struct nameidata nd; | ||
| 128 | struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; | 127 | struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; |
| 129 | struct file *file; | 128 | struct file *file; |
| 130 | int n, err; | 129 | int n; |
| 131 | char *ptr = req->request.data, *buf; | 130 | char *ptr = req->request.data, *buf; |
| 132 | mm_segment_t old_fs = get_fs(); | 131 | mm_segment_t old_fs = get_fs(); |
| 133 | 132 | ||
| 134 | ptr += strlen("proc"); | 133 | ptr += strlen("proc"); |
| 135 | ptr = skip_spaces(ptr); | 134 | ptr = skip_spaces(ptr); |
| 136 | 135 | ||
| 137 | err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd); | 136 | file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); |
| 138 | if (err) { | ||
| 139 | mconsole_reply(req, "Failed to look up file", 1, 0); | ||
| 140 | goto out; | ||
| 141 | } | ||
| 142 | |||
| 143 | err = may_open(&nd.path, MAY_READ, O_RDONLY); | ||
| 144 | if (result) { | ||
| 145 | mconsole_reply(req, "Failed to open file", 1, 0); | ||
| 146 | path_put(&nd.path); | ||
| 147 | goto out; | ||
| 148 | } | ||
| 149 | |||
| 150 | file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY, | ||
| 151 | current_cred()); | ||
| 152 | err = PTR_ERR(file); | ||
| 153 | if (IS_ERR(file)) { | 137 | if (IS_ERR(file)) { |
| 154 | mconsole_reply(req, "Failed to open file", 1, 0); | 138 | mconsole_reply(req, "Failed to open file", 1, 0); |
| 155 | path_put(&nd.path); | ||
| 156 | goto out; | 139 | goto out; |
| 157 | } | 140 | } |
| 158 | 141 | ||
| @@ -843,6 +826,7 @@ static ssize_t mconsole_proc_write(struct file *file, | |||
| 843 | static const struct file_operations mconsole_proc_fops = { | 826 | static const struct file_operations mconsole_proc_fops = { |
| 844 | .owner = THIS_MODULE, | 827 | .owner = THIS_MODULE, |
| 845 | .write = mconsole_proc_write, | 828 | .write = mconsole_proc_write, |
| 829 | .llseek = noop_llseek, | ||
| 846 | }; | 830 | }; |
| 847 | 831 | ||
| 848 | static int create_proc_mconsole(void) | 832 | static int create_proc_mconsole(void) |
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 7158393b6793..c0ef803c7c70 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c | |||
| @@ -37,13 +37,7 @@ static ssize_t mmapper_write(struct file *file, const char __user *buf, | |||
| 37 | if (*ppos > mmapper_size) | 37 | if (*ppos > mmapper_size) |
| 38 | return -EINVAL; | 38 | return -EINVAL; |
| 39 | 39 | ||
| 40 | if (count > mmapper_size - *ppos) | 40 | return simple_write_to_buffer(v_buf, mmapper_size, ppos, buf, count); |
| 41 | count = mmapper_size - *ppos; | ||
| 42 | |||
| 43 | if (copy_from_user(&v_buf[*ppos], buf, count)) | ||
| 44 | return -EFAULT; | ||
| 45 | |||
| 46 | return count; | ||
| 47 | } | 41 | } |
| 48 | 42 | ||
| 49 | static long mmapper_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 43 | static long mmapper_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| @@ -93,6 +87,7 @@ static const struct file_operations mmapper_fops = { | |||
| 93 | .mmap = mmapper_mmap, | 87 | .mmap = mmapper_mmap, |
| 94 | .open = mmapper_open, | 88 | .open = mmapper_open, |
| 95 | .release = mmapper_release, | 89 | .release = mmapper_release, |
| 90 | .llseek = default_llseek, | ||
| 96 | }; | 91 | }; |
| 97 | 92 | ||
| 98 | /* | 93 | /* |
| @@ -121,7 +116,7 @@ static int __init mmapper_init(void) | |||
| 121 | if (err) { | 116 | if (err) { |
| 122 | printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", | 117 | printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", |
| 123 | err); | 118 | err); |
| 124 | return err;; | 119 | return err; |
| 125 | } | 120 | } |
| 126 | return 0; | 121 | return 0; |
| 127 | } | 122 | } |
| @@ -136,3 +131,4 @@ module_exit(mmapper_exit); | |||
| 136 | 131 | ||
| 137 | MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); | 132 | MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); |
| 138 | MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); | 133 | MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); |
| 134 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 4949044773ba..981085a93f30 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c | |||
| @@ -100,6 +100,7 @@ static const struct file_operations rng_chrdev_ops = { | |||
| 100 | .owner = THIS_MODULE, | 100 | .owner = THIS_MODULE, |
| 101 | .open = rng_dev_open, | 101 | .open = rng_dev_open, |
| 102 | .read = rng_dev_read, | 102 | .read = rng_dev_read, |
| 103 | .llseek = noop_llseek, | ||
| 103 | }; | 104 | }; |
| 104 | 105 | ||
| 105 | /* rng_init shouldn't be called more than once at boot time */ | 106 | /* rng_init shouldn't be called more than once at boot time */ |
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 9734994cba1e..620f5b70957d 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | #include "linux/mm.h" | 33 | #include "linux/mm.h" |
| 34 | #include "linux/slab.h" | 34 | #include "linux/slab.h" |
| 35 | #include "linux/vmalloc.h" | 35 | #include "linux/vmalloc.h" |
| 36 | #include "linux/smp_lock.h" | 36 | #include "linux/mutex.h" |
| 37 | #include "linux/blkpg.h" | 37 | #include "linux/blkpg.h" |
| 38 | #include "linux/genhd.h" | 38 | #include "linux/genhd.h" |
| 39 | #include "linux/spinlock.h" | 39 | #include "linux/spinlock.h" |
| @@ -100,6 +100,7 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) | |||
| 100 | #define DRIVER_NAME "uml-blkdev" | 100 | #define DRIVER_NAME "uml-blkdev" |
| 101 | 101 | ||
| 102 | static DEFINE_MUTEX(ubd_lock); | 102 | static DEFINE_MUTEX(ubd_lock); |
| 103 | static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */ | ||
| 103 | 104 | ||
| 104 | static int ubd_open(struct block_device *bdev, fmode_t mode); | 105 | static int ubd_open(struct block_device *bdev, fmode_t mode); |
| 105 | static int ubd_release(struct gendisk *disk, fmode_t mode); | 106 | static int ubd_release(struct gendisk *disk, fmode_t mode); |
| @@ -184,7 +185,7 @@ struct ubd { | |||
| 184 | .no_cow = 0, \ | 185 | .no_cow = 0, \ |
| 185 | .shared = 0, \ | 186 | .shared = 0, \ |
| 186 | .cow = DEFAULT_COW, \ | 187 | .cow = DEFAULT_COW, \ |
| 187 | .lock = SPIN_LOCK_UNLOCKED, \ | 188 | .lock = __SPIN_LOCK_UNLOCKED(ubd_devs.lock), \ |
| 188 | .request = NULL, \ | 189 | .request = NULL, \ |
| 189 | .start_sg = 0, \ | 190 | .start_sg = 0, \ |
| 190 | .end_sg = 0, \ | 191 | .end_sg = 0, \ |
| @@ -1101,7 +1102,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode) | |||
| 1101 | struct ubd *ubd_dev = disk->private_data; | 1102 | struct ubd *ubd_dev = disk->private_data; |
| 1102 | int err = 0; | 1103 | int err = 0; |
| 1103 | 1104 | ||
| 1104 | lock_kernel(); | 1105 | mutex_lock(&ubd_mutex); |
| 1105 | if(ubd_dev->count == 0){ | 1106 | if(ubd_dev->count == 0){ |
| 1106 | err = ubd_open_dev(ubd_dev); | 1107 | err = ubd_open_dev(ubd_dev); |
| 1107 | if(err){ | 1108 | if(err){ |
| @@ -1120,7 +1121,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode) | |||
| 1120 | err = -EROFS; | 1121 | err = -EROFS; |
| 1121 | }*/ | 1122 | }*/ |
| 1122 | out: | 1123 | out: |
| 1123 | unlock_kernel(); | 1124 | mutex_unlock(&ubd_mutex); |
| 1124 | return err; | 1125 | return err; |
| 1125 | } | 1126 | } |
| 1126 | 1127 | ||
| @@ -1128,10 +1129,10 @@ static int ubd_release(struct gendisk *disk, fmode_t mode) | |||
| 1128 | { | 1129 | { |
| 1129 | struct ubd *ubd_dev = disk->private_data; | 1130 | struct ubd *ubd_dev = disk->private_data; |
| 1130 | 1131 | ||
| 1131 | lock_kernel(); | 1132 | mutex_lock(&ubd_mutex); |
| 1132 | if(--ubd_dev->count == 0) | 1133 | if(--ubd_dev->count == 0) |
| 1133 | ubd_close_dev(ubd_dev); | 1134 | ubd_close_dev(ubd_dev); |
| 1134 | unlock_kernel(); | 1135 | mutex_unlock(&ubd_mutex); |
| 1135 | return 0; | 1136 | return 0; |
| 1136 | } | 1137 | } |
| 1137 | 1138 | ||
diff --git a/arch/um/drivers/umcast.h b/arch/um/drivers/umcast.h new file mode 100644 index 000000000000..6f8c0fe890fb --- /dev/null +++ b/arch/um/drivers/umcast.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __DRIVERS_UMCAST_H | ||
| 7 | #define __DRIVERS_UMCAST_H | ||
| 8 | |||
| 9 | #include "net_user.h" | ||
| 10 | |||
| 11 | struct umcast_data { | ||
| 12 | char *addr; | ||
| 13 | unsigned short lport; | ||
| 14 | unsigned short rport; | ||
| 15 | void *listen_addr; | ||
| 16 | void *remote_addr; | ||
| 17 | int ttl; | ||
| 18 | int unicast; | ||
| 19 | void *dev; | ||
| 20 | }; | ||
| 21 | |||
| 22 | extern const struct net_user_info umcast_user_info; | ||
| 23 | |||
| 24 | extern int umcast_user_write(int fd, void *buf, int len, | ||
| 25 | struct umcast_data *pri); | ||
| 26 | |||
| 27 | #endif | ||
diff --git a/arch/um/drivers/umcast_kern.c b/arch/um/drivers/umcast_kern.c new file mode 100644 index 000000000000..42dab11d2ecf --- /dev/null +++ b/arch/um/drivers/umcast_kern.c | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | /* | ||
| 2 | * user-mode-linux networking multicast transport | ||
| 3 | * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> | ||
| 4 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
| 5 | * | ||
| 6 | * based on the existing uml-networking code, which is | ||
| 7 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | ||
| 8 | * James Leu (jleu@mindspring.net). | ||
| 9 | * Copyright (C) 2001 by various other people who didn't put their name here. | ||
| 10 | * | ||
| 11 | * Licensed under the GPL. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include "linux/init.h" | ||
| 15 | #include <linux/netdevice.h> | ||
| 16 | #include "umcast.h" | ||
| 17 | #include "net_kern.h" | ||
| 18 | |||
| 19 | struct umcast_init { | ||
| 20 | char *addr; | ||
| 21 | int lport; | ||
| 22 | int rport; | ||
| 23 | int ttl; | ||
| 24 | bool unicast; | ||
| 25 | }; | ||
| 26 | |||
| 27 | static void umcast_init(struct net_device *dev, void *data) | ||
| 28 | { | ||
| 29 | struct uml_net_private *pri; | ||
| 30 | struct umcast_data *dpri; | ||
| 31 | struct umcast_init *init = data; | ||
| 32 | |||
| 33 | pri = netdev_priv(dev); | ||
| 34 | dpri = (struct umcast_data *) pri->user; | ||
| 35 | dpri->addr = init->addr; | ||
| 36 | dpri->lport = init->lport; | ||
| 37 | dpri->rport = init->rport; | ||
| 38 | dpri->unicast = init->unicast; | ||
| 39 | dpri->ttl = init->ttl; | ||
| 40 | dpri->dev = dev; | ||
| 41 | |||
| 42 | if (dpri->unicast) { | ||
| 43 | printk(KERN_INFO "ucast backend address: %s:%u listen port: " | ||
| 44 | "%u\n", dpri->addr, dpri->rport, dpri->lport); | ||
| 45 | } else { | ||
| 46 | printk(KERN_INFO "mcast backend multicast address: %s:%u, " | ||
| 47 | "TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) | ||
| 52 | { | ||
| 53 | return net_recvfrom(fd, skb_mac_header(skb), | ||
| 54 | skb->dev->mtu + ETH_HEADER_OTHER); | ||
| 55 | } | ||
| 56 | |||
| 57 | static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) | ||
| 58 | { | ||
| 59 | return umcast_user_write(fd, skb->data, skb->len, | ||
| 60 | (struct umcast_data *) &lp->user); | ||
| 61 | } | ||
| 62 | |||
| 63 | static const struct net_kern_info umcast_kern_info = { | ||
| 64 | .init = umcast_init, | ||
| 65 | .protocol = eth_protocol, | ||
| 66 | .read = umcast_read, | ||
| 67 | .write = umcast_write, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static int mcast_setup(char *str, char **mac_out, void *data) | ||
| 71 | { | ||
| 72 | struct umcast_init *init = data; | ||
| 73 | char *port_str = NULL, *ttl_str = NULL, *remain; | ||
| 74 | char *last; | ||
| 75 | |||
| 76 | *init = ((struct umcast_init) | ||
| 77 | { .addr = "239.192.168.1", | ||
| 78 | .lport = 1102, | ||
| 79 | .ttl = 1 }); | ||
| 80 | |||
| 81 | remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, | ||
| 82 | NULL); | ||
| 83 | if (remain != NULL) { | ||
| 84 | printk(KERN_ERR "mcast_setup - Extra garbage on " | ||
| 85 | "specification : '%s'\n", remain); | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (port_str != NULL) { | ||
| 90 | init->lport = simple_strtoul(port_str, &last, 10); | ||
| 91 | if ((*last != '\0') || (last == port_str)) { | ||
| 92 | printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", | ||
| 93 | port_str); | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | if (ttl_str != NULL) { | ||
| 99 | init->ttl = simple_strtoul(ttl_str, &last, 10); | ||
| 100 | if ((*last != '\0') || (last == ttl_str)) { | ||
| 101 | printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", | ||
| 102 | ttl_str); | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | init->unicast = false; | ||
| 108 | init->rport = init->lport; | ||
| 109 | |||
| 110 | printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, | ||
| 111 | init->lport, init->ttl); | ||
| 112 | |||
| 113 | return 1; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int ucast_setup(char *str, char **mac_out, void *data) | ||
| 117 | { | ||
| 118 | struct umcast_init *init = data; | ||
| 119 | char *lport_str = NULL, *rport_str = NULL, *remain; | ||
| 120 | char *last; | ||
| 121 | |||
| 122 | *init = ((struct umcast_init) | ||
| 123 | { .addr = "", | ||
| 124 | .lport = 1102, | ||
| 125 | .rport = 1102 }); | ||
| 126 | |||
| 127 | remain = split_if_spec(str, mac_out, &init->addr, | ||
| 128 | &lport_str, &rport_str, NULL); | ||
| 129 | if (remain != NULL) { | ||
| 130 | printk(KERN_ERR "ucast_setup - Extra garbage on " | ||
| 131 | "specification : '%s'\n", remain); | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | if (lport_str != NULL) { | ||
| 136 | init->lport = simple_strtoul(lport_str, &last, 10); | ||
| 137 | if ((*last != '\0') || (last == lport_str)) { | ||
| 138 | printk(KERN_ERR "ucast_setup - Bad listen port : " | ||
| 139 | "'%s'\n", lport_str); | ||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | if (rport_str != NULL) { | ||
| 145 | init->rport = simple_strtoul(rport_str, &last, 10); | ||
| 146 | if ((*last != '\0') || (last == rport_str)) { | ||
| 147 | printk(KERN_ERR "ucast_setup - Bad remote port : " | ||
| 148 | "'%s'\n", rport_str); | ||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | init->unicast = true; | ||
| 154 | |||
| 155 | printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n", | ||
| 156 | init->lport, init->addr, init->rport); | ||
| 157 | |||
| 158 | return 1; | ||
| 159 | } | ||
| 160 | |||
| 161 | static struct transport mcast_transport = { | ||
| 162 | .list = LIST_HEAD_INIT(mcast_transport.list), | ||
| 163 | .name = "mcast", | ||
| 164 | .setup = mcast_setup, | ||
| 165 | .user = &umcast_user_info, | ||
| 166 | .kern = &umcast_kern_info, | ||
| 167 | .private_size = sizeof(struct umcast_data), | ||
| 168 | .setup_size = sizeof(struct umcast_init), | ||
| 169 | }; | ||
| 170 | |||
| 171 | static struct transport ucast_transport = { | ||
| 172 | .list = LIST_HEAD_INIT(ucast_transport.list), | ||
| 173 | .name = "ucast", | ||
| 174 | .setup = ucast_setup, | ||
| 175 | .user = &umcast_user_info, | ||
| 176 | .kern = &umcast_kern_info, | ||
| 177 | .private_size = sizeof(struct umcast_data), | ||
| 178 | .setup_size = sizeof(struct umcast_init), | ||
| 179 | }; | ||
| 180 | |||
| 181 | static int register_umcast(void) | ||
| 182 | { | ||
| 183 | register_transport(&mcast_transport); | ||
| 184 | register_transport(&ucast_transport); | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | late_initcall(register_umcast); | ||
diff --git a/arch/um/drivers/umcast_user.c b/arch/um/drivers/umcast_user.c new file mode 100644 index 000000000000..59c56fd6f52a --- /dev/null +++ b/arch/um/drivers/umcast_user.c | |||
| @@ -0,0 +1,186 @@ | |||
| 1 | /* | ||
| 2 | * user-mode-linux networking multicast transport | ||
| 3 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
| 4 | * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> | ||
| 5 | * | ||
| 6 | * based on the existing uml-networking code, which is | ||
| 7 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | ||
| 8 | * James Leu (jleu@mindspring.net). | ||
| 9 | * Copyright (C) 2001 by various other people who didn't put their name here. | ||
| 10 | * | ||
| 11 | * Licensed under the GPL. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <unistd.h> | ||
| 16 | #include <errno.h> | ||
| 17 | #include <netinet/in.h> | ||
| 18 | #include "kern_constants.h" | ||
| 19 | #include "umcast.h" | ||
| 20 | #include "net_user.h" | ||
| 21 | #include "um_malloc.h" | ||
| 22 | #include "user.h" | ||
| 23 | |||
| 24 | static struct sockaddr_in *new_addr(char *addr, unsigned short port) | ||
| 25 | { | ||
| 26 | struct sockaddr_in *sin; | ||
| 27 | |||
| 28 | sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); | ||
| 29 | if (sin == NULL) { | ||
| 30 | printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " | ||
| 31 | "failed\n"); | ||
| 32 | return NULL; | ||
| 33 | } | ||
| 34 | sin->sin_family = AF_INET; | ||
| 35 | if (addr) | ||
| 36 | sin->sin_addr.s_addr = in_aton(addr); | ||
| 37 | else | ||
| 38 | sin->sin_addr.s_addr = INADDR_ANY; | ||
| 39 | sin->sin_port = htons(port); | ||
| 40 | return sin; | ||
| 41 | } | ||
| 42 | |||
| 43 | static int umcast_user_init(void *data, void *dev) | ||
| 44 | { | ||
| 45 | struct umcast_data *pri = data; | ||
| 46 | |||
| 47 | pri->remote_addr = new_addr(pri->addr, pri->rport); | ||
| 48 | if (pri->unicast) | ||
| 49 | pri->listen_addr = new_addr(NULL, pri->lport); | ||
| 50 | else | ||
| 51 | pri->listen_addr = pri->remote_addr; | ||
| 52 | pri->dev = dev; | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | static void umcast_remove(void *data) | ||
| 57 | { | ||
| 58 | struct umcast_data *pri = data; | ||
| 59 | |||
| 60 | kfree(pri->listen_addr); | ||
| 61 | if (pri->unicast) | ||
| 62 | kfree(pri->remote_addr); | ||
| 63 | pri->listen_addr = pri->remote_addr = NULL; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int umcast_open(void *data) | ||
| 67 | { | ||
| 68 | struct umcast_data *pri = data; | ||
| 69 | struct sockaddr_in *lsin = pri->listen_addr; | ||
| 70 | struct sockaddr_in *rsin = pri->remote_addr; | ||
| 71 | struct ip_mreq mreq; | ||
| 72 | int fd, yes = 1, err = -EINVAL; | ||
| 73 | |||
| 74 | |||
| 75 | if ((!pri->unicast && lsin->sin_addr.s_addr == 0) || | ||
| 76 | (rsin->sin_addr.s_addr == 0) || | ||
| 77 | (lsin->sin_port == 0) || (rsin->sin_port == 0)) | ||
| 78 | goto out; | ||
| 79 | |||
| 80 | fd = socket(AF_INET, SOCK_DGRAM, 0); | ||
| 81 | |||
| 82 | if (fd < 0) { | ||
| 83 | err = -errno; | ||
| 84 | printk(UM_KERN_ERR "umcast_open : data socket failed, " | ||
| 85 | "errno = %d\n", errno); | ||
| 86 | goto out; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { | ||
| 90 | err = -errno; | ||
| 91 | printk(UM_KERN_ERR "umcast_open: SO_REUSEADDR failed, " | ||
| 92 | "errno = %d\n", errno); | ||
| 93 | goto out_close; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (!pri->unicast) { | ||
| 97 | /* set ttl according to config */ | ||
| 98 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, | ||
| 99 | sizeof(pri->ttl)) < 0) { | ||
| 100 | err = -errno; | ||
| 101 | printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_TTL " | ||
| 102 | "failed, error = %d\n", errno); | ||
| 103 | goto out_close; | ||
| 104 | } | ||
| 105 | |||
| 106 | /* set LOOP, so data does get fed back to local sockets */ | ||
| 107 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, | ||
| 108 | &yes, sizeof(yes)) < 0) { | ||
| 109 | err = -errno; | ||
| 110 | printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_LOOP " | ||
| 111 | "failed, error = %d\n", errno); | ||
| 112 | goto out_close; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | /* bind socket to the address */ | ||
| 117 | if (bind(fd, (struct sockaddr *) lsin, sizeof(*lsin)) < 0) { | ||
| 118 | err = -errno; | ||
| 119 | printk(UM_KERN_ERR "umcast_open : data bind failed, " | ||
| 120 | "errno = %d\n", errno); | ||
| 121 | goto out_close; | ||
| 122 | } | ||
| 123 | |||
| 124 | if (!pri->unicast) { | ||
| 125 | /* subscribe to the multicast group */ | ||
| 126 | mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr; | ||
| 127 | mreq.imr_interface.s_addr = 0; | ||
| 128 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, | ||
| 129 | &mreq, sizeof(mreq)) < 0) { | ||
| 130 | err = -errno; | ||
| 131 | printk(UM_KERN_ERR "umcast_open: IP_ADD_MEMBERSHIP " | ||
| 132 | "failed, error = %d\n", errno); | ||
| 133 | printk(UM_KERN_ERR "There appears not to be a " | ||
| 134 | "multicast-capable network interface on the " | ||
| 135 | "host.\n"); | ||
| 136 | printk(UM_KERN_ERR "eth0 should be configured in order " | ||
| 137 | "to use the multicast transport.\n"); | ||
| 138 | goto out_close; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | return fd; | ||
| 143 | |||
| 144 | out_close: | ||
| 145 | close(fd); | ||
| 146 | out: | ||
| 147 | return err; | ||
| 148 | } | ||
| 149 | |||
| 150 | static void umcast_close(int fd, void *data) | ||
| 151 | { | ||
| 152 | struct umcast_data *pri = data; | ||
| 153 | |||
| 154 | if (!pri->unicast) { | ||
| 155 | struct ip_mreq mreq; | ||
| 156 | struct sockaddr_in *lsin = pri->listen_addr; | ||
| 157 | |||
| 158 | mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr; | ||
| 159 | mreq.imr_interface.s_addr = 0; | ||
| 160 | if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, | ||
| 161 | &mreq, sizeof(mreq)) < 0) { | ||
| 162 | printk(UM_KERN_ERR "umcast_close: IP_DROP_MEMBERSHIP " | ||
| 163 | "failed, error = %d\n", errno); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | close(fd); | ||
| 168 | } | ||
| 169 | |||
| 170 | int umcast_user_write(int fd, void *buf, int len, struct umcast_data *pri) | ||
| 171 | { | ||
| 172 | struct sockaddr_in *data_addr = pri->remote_addr; | ||
| 173 | |||
| 174 | return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); | ||
| 175 | } | ||
| 176 | |||
| 177 | const struct net_user_info umcast_user_info = { | ||
| 178 | .init = umcast_user_init, | ||
| 179 | .open = umcast_open, | ||
| 180 | .close = umcast_close, | ||
| 181 | .remove = umcast_remove, | ||
| 182 | .add_address = NULL, | ||
| 183 | .delete_address = NULL, | ||
| 184 | .mtu = ETH_MAX_PACKET, | ||
| 185 | .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, | ||
| 186 | }; | ||
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index da2caa5a21ef..8ac7146c237f 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c | |||
| @@ -90,7 +90,7 @@ static int xterm_open(int input, int output, int primary, void *d, | |||
| 90 | int pid, fd, new, err; | 90 | int pid, fd, new, err; |
| 91 | char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; | 91 | char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; |
| 92 | char *argv[] = { terminal_emulator, title_switch, title, exec_switch, | 92 | char *argv[] = { terminal_emulator, title_switch, title, exec_switch, |
| 93 | "/usr/lib/uml/port-helper", "-uml-socket", | 93 | OS_LIB_PATH "/uml/port-helper", "-uml-socket", |
| 94 | file, NULL }; | 94 | file, NULL }; |
| 95 | 95 | ||
| 96 | if (access(argv[4], X_OK) < 0) | 96 | if (access(argv[4], X_OK) < 0) |
