1/*
2 * L2TPv3 ethernet pseudowire driver
3 *
4 * Copyright (c) 2008,2009,2010 Katalix Systems Ltd
5 *
6 *	This program is free software; you can redistribute it and/or
7 *	modify it under the terms of the GNU General Public License
8 *	as published by the Free Software Foundation; either version
9 *	2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/socket.h>
15#include <linux/hash.h>
16#include <linux/l2tp.h>
17#include <linux/in.h>
18#include <linux/etherdevice.h>
19#include <linux/spinlock.h>
20#include <net/sock.h>
21#include <net/ip.h>
22#include <net/icmp.h>
23#include <net/udp.h>
24#include <net/inet_common.h>
25#include <net/inet_hashtables.h>
26#include <net/tcp_states.h>
27#include <net/protocol.h>
28#include <net/xfrm.h>
29#include <net/net_namespace.h>
30#include <net/netns/generic.h>
31
32#include "l2tp_core.h"
33
34/* Default device name. May be overridden by name specified by user */
35#define L2TP_ETH_DEV_NAME	"l2tpeth%d"
36
37/* via netdev_priv() */
38struct l2tp_eth {
39	struct net_device	*dev;
40	struct sock		*tunnel_sock;
41	struct l2tp_session	*session;
42	struct list_head	list;
43};
44
45/* via l2tp_session_priv() */
46struct l2tp_eth_sess {
47	struct net_device	*dev;
48};
49
50/* per-net private data for this module */
51static unsigned int l2tp_eth_net_id;
52struct l2tp_eth_net {
53	struct list_head l2tp_eth_dev_list;
54	spinlock_t l2tp_eth_lock;
55};
56
57static inline struct l2tp_eth_net *l2tp_eth_pernet(struct net *net)
58{
59	return net_generic(net, l2tp_eth_net_id);
60}
61
62static int l2tp_eth_dev_init(struct net_device *dev)
63{
64	struct l2tp_eth *priv = netdev_priv(dev);
65
66	priv->dev = dev;
67	random_ether_addr(dev->dev_addr);
68	memset(&dev->broadcast[0], 0xff, 6);
69
70	return 0;
71}
72
73static void l2tp_eth_dev_uninit(struct net_device *dev)
74{
75	struct l2tp_eth *priv = netdev_priv(dev);
76	struct l2tp_eth_net *pn = l2tp_eth_pernet(dev_net(dev));
77
78	spin_lock(&pn->l2tp_eth_lock);
79	list_del_init(&priv->list);
80	spin_unlock(&pn->l2tp_eth_lock);
81	dev_put(dev);
82}
83
84static int l2tp_eth_dev_xmit(struct sk_buff *skb, struct net_device *dev)
85{
86	struct l2tp_eth *priv = netdev_priv(dev);
87	struct l2tp_session *session = priv->session;
88
89	l2tp_xmit_skb(session, skb, session->hdr_len);
90
91	dev->stats.tx_bytes += skb->len;
92	dev->stats.tx_packets++;
93
94	return 0;
95}
96
97static struct net_device_ops l2tp_eth_netdev_ops = {
98	.ndo_init		= l2tp_eth_dev_init,
99	.ndo_uninit		= l2tp_eth_dev_uninit,
100	.ndo_start_xmit		= l2tp_eth_dev_xmit,
101};
102
103static void l2tp_eth_dev_setup(struct net_device *dev)
104{
105	ether_setup(dev);
106
107	dev->netdev_ops		= &l2tp_eth_netdev_ops;
108	dev->destructor		= free_netdev;
109}
110
111static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len)
112{
113	struct l2tp_eth_sess *spriv = l2tp_session_priv(session);
114	struct net_device *dev = spriv->dev;
115
116	if (session->debug & L2TP_MSG_DATA) {
117		unsigned int length;
118		int offset;
119		u8 *ptr = skb->data;
120
121		length = min(32u, skb->len);
122		if (!pskb_may_pull(skb, length))
123			goto error;
124
125		printk(KERN_DEBUG "%s: eth recv: ", session->name);
126
127		offset = 0;
128		do {
129			printk(" %02X", ptr[offset]);
130		} while (++offset < length);
131
132		printk("\n");
133	}
134
135	if (!pskb_may_pull(skb, sizeof(ETH_HLEN)))
136		goto error;
137
138	secpath_reset(skb);
139
140	/* checksums verified by L2TP */
141	skb->ip_summed = CHECKSUM_NONE;
142
143	skb_dst_drop(skb);
144	nf_reset(skb);
145
146	if (dev_forward_skb(dev, skb) == NET_RX_SUCCESS) {
147		dev->last_rx = jiffies;
148		dev->stats.rx_packets++;
149		dev->stats.rx_bytes += data_len;
150	} else
151		dev->stats.rx_errors++;
152
153	return;
154
155error:
156	dev->stats.rx_errors++;
157	kfree_skb(skb);
158}
159
160static void l2tp_eth_delete(struct l2tp_session *session)
161{
162	struct l2tp_eth_sess *spriv;
163	struct net_device *dev;
164
165	if (session) {
166		spriv = l2tp_session_priv(session);
167		dev = spriv->dev;
168		if (dev) {
169			unregister_netdev(dev);
170			spriv->dev = NULL;
171		}
172	}
173}
174
175#if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE)
176static void l2tp_eth_show(struct seq_file *m, void *arg)
177{
178	struct l2tp_session *session = arg;
179	struct l2tp_eth_sess *spriv = l2tp_session_priv(session);
180	struct net_device *dev = spriv->dev;
181
182	seq_printf(m, "   interface %s\n", dev->name);
183}
184#endif
185
186static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg)
187{
188	struct net_device *dev;
189	char name[IFNAMSIZ];
190	struct l2tp_tunnel *tunnel;
191	struct l2tp_session *session;
192	struct l2tp_eth *priv;
193	struct l2tp_eth_sess *spriv;
194	int rc;
195	struct l2tp_eth_net *pn;
196
197	tunnel = l2tp_tunnel_find(net, tunnel_id);
198	if (!tunnel) {
199		rc = -ENODEV;
200		goto out;
201	}
202
203	session = l2tp_session_find(net, tunnel, session_id);
204	if (session) {
205		rc = -EEXIST;
206		goto out;
207	}
208
209	if (cfg->ifname) {
210		dev = dev_get_by_name(net, cfg->ifname);
211		if (dev) {
212			dev_put(dev);
213			rc = -EEXIST;
214			goto out;
215		}
216		strlcpy(name, cfg->ifname, IFNAMSIZ);
217	} else
218		strcpy(name, L2TP_ETH_DEV_NAME);
219
220	session = l2tp_session_create(sizeof(*spriv), tunnel, session_id,
221				      peer_session_id, cfg);
222	if (!session) {
223		rc = -ENOMEM;
224		goto out;
225	}
226
227	dev = alloc_netdev(sizeof(*priv), name, l2tp_eth_dev_setup);
228	if (!dev) {
229		rc = -ENOMEM;
230		goto out_del_session;
231	}
232
233	dev_net_set(dev, net);
234	if (session->mtu == 0)
235		session->mtu = dev->mtu - session->hdr_len;
236	dev->mtu = session->mtu;
237	dev->needed_headroom += session->hdr_len;
238
239	priv = netdev_priv(dev);
240	priv->dev = dev;
241	priv->session = session;
242	INIT_LIST_HEAD(&priv->list);
243
244	priv->tunnel_sock = tunnel->sock;
245	session->recv_skb = l2tp_eth_dev_recv;
246	session->session_close = l2tp_eth_delete;
247#if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE)
248	session->show = l2tp_eth_show;
249#endif
250
251	spriv = l2tp_session_priv(session);
252	spriv->dev = dev;
253
254	rc = register_netdev(dev);
255	if (rc < 0)
256		goto out_del_dev;
257
258	/* Must be done after register_netdev() */
259	strlcpy(session->ifname, dev->name, IFNAMSIZ);
260
261	dev_hold(dev);
262	pn = l2tp_eth_pernet(dev_net(dev));
263	spin_lock(&pn->l2tp_eth_lock);
264	list_add(&priv->list, &pn->l2tp_eth_dev_list);
265	spin_unlock(&pn->l2tp_eth_lock);
266
267	return 0;
268
269out_del_dev:
270	free_netdev(dev);
271out_del_session:
272	l2tp_session_delete(session);
273out:
274	return rc;
275}
276
277static __net_init int l2tp_eth_init_net(struct net *net)
278{
279	struct l2tp_eth_net *pn = net_generic(net, l2tp_eth_net_id);
280
281	INIT_LIST_HEAD(&pn->l2tp_eth_dev_list);
282	spin_lock_init(&pn->l2tp_eth_lock);
283
284	return 0;
285}
286
287static __net_initdata struct pernet_operations l2tp_eth_net_ops = {
288	.init = l2tp_eth_init_net,
289	.id   = &l2tp_eth_net_id,
290	.size = sizeof(struct l2tp_eth_net),
291};
292
293
294static const struct l2tp_nl_cmd_ops l2tp_eth_nl_cmd_ops = {
295	.session_create	= l2tp_eth_create,
296	.session_delete	= l2tp_session_delete,
297};
298
299
300static int __init l2tp_eth_init(void)
301{
302	int err = 0;
303
304	err = l2tp_nl_register_ops(L2TP_PWTYPE_ETH, &l2tp_eth_nl_cmd_ops);
305	if (err)
306		goto out;
307
308	err = register_pernet_device(&l2tp_eth_net_ops);
309	if (err)
310		goto out_unreg;
311
312	printk(KERN_INFO "L2TP ethernet pseudowire support (L2TPv3)\n");
313
314	return 0;
315
316out_unreg:
317	l2tp_nl_unregister_ops(L2TP_PWTYPE_ETH);
318out:
319	return err;
320}
321
322static void __exit l2tp_eth_exit(void)
323{
324	unregister_pernet_device(&l2tp_eth_net_ops);
325	l2tp_nl_unregister_ops(L2TP_PWTYPE_ETH);
326}
327
328module_init(l2tp_eth_init);
329module_exit(l2tp_eth_exit);
330
331MODULE_LICENSE("GPL");
332MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
333MODULE_DESCRIPTION("L2TP ethernet pseudowire driver");
334MODULE_VERSION("1.0");
335