diff options
Diffstat (limited to 'arch/um/drivers')
-rw-r--r-- | arch/um/drivers/Makefile | 4 | ||||
-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/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 |
8 files changed, 404 insertions, 312 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/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/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) |