Commit | Line | Data |
---|---|---|
4ff4d8d3 NL |
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 | ||
37185b33 | 14 | #include <linux/init.h> |
4ff4d8d3 NL |
15 | #include <linux/netdevice.h> |
16 | #include "umcast.h" | |
37185b33 | 17 | #include <net_kern.h> |
4ff4d8d3 NL |
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); |