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) |