Blame view

net/l2tp/l2tp_ip6.c 19.8 KB
a32e0eec7   Chris Elston   l2tp: introduce L...
1
2
3
4
5
6
7
8
9
10
  /*
   * L2TPv3 IP encapsulation support for IPv6
   *
   * Copyright (c) 2012 Katalix Systems Ltd
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   */
a4ca44fa5   Joe Perches   net: l2tp: Standa...
11
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
a32e0eec7   Chris Elston   l2tp: introduce L...
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  #include <linux/icmp.h>
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/random.h>
  #include <linux/socket.h>
  #include <linux/l2tp.h>
  #include <linux/in.h>
  #include <linux/in6.h>
  #include <net/sock.h>
  #include <net/ip.h>
  #include <net/icmp.h>
  #include <net/udp.h>
  #include <net/inet_common.h>
  #include <net/inet_hashtables.h>
496611d7b   Craig Gallek   inet: create IPv6...
26
  #include <net/inet6_hashtables.h>
a32e0eec7   Chris Elston   l2tp: introduce L...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  #include <net/tcp_states.h>
  #include <net/protocol.h>
  #include <net/xfrm.h>
  
  #include <net/transp_v6.h>
  #include <net/addrconf.h>
  #include <net/ip6_route.h>
  
  #include "l2tp_core.h"
  
  struct l2tp_ip6_sock {
  	/* inet_sock has to be the first member of l2tp_ip6_sock */
  	struct inet_sock	inet;
  
  	u32			conn_id;
  	u32			peer_conn_id;
  
  	/* ipv6_pinfo has to be the last member of l2tp_ip6_sock, see
  	   inet6_sk_generic */
  	struct ipv6_pinfo	inet6;
  };
  
  static DEFINE_RWLOCK(l2tp_ip6_lock);
  static struct hlist_head l2tp_ip6_table;
  static struct hlist_head l2tp_ip6_bind_table;
  
  static inline struct l2tp_ip6_sock *l2tp_ip6_sk(const struct sock *sk)
  {
  	return (struct l2tp_ip6_sock *)sk;
  }
bb39b0bdc   Guillaume Nault   l2tp: make __l2tp...
57
58
  static struct sock *__l2tp_ip6_bind_lookup(const struct net *net,
  					   const struct in6_addr *laddr,
a9b2dff80   Guillaume Nault   l2tp: take remote...
59
  					   const struct in6_addr *raddr,
a32e0eec7   Chris Elston   l2tp: introduce L...
60
61
  					   int dif, u32 tunnel_id)
  {
a32e0eec7   Chris Elston   l2tp: introduce L...
62
  	struct sock *sk;
b67bfe0d4   Sasha Levin   hlist: drop the n...
63
  	sk_for_each_bound(sk, &l2tp_ip6_bind_table) {
97b84fd6d   Guillaume Nault   l2tp: consider ':...
64
  		const struct in6_addr *sk_laddr = inet6_rcv_saddr(sk);
a9b2dff80   Guillaume Nault   l2tp: take remote...
65
  		const struct in6_addr *sk_raddr = &sk->sk_v6_daddr;
bb39b0bdc   Guillaume Nault   l2tp: make __l2tp...
66
  		const struct l2tp_ip6_sock *l2tp = l2tp_ip6_sk(sk);
a32e0eec7   Chris Elston   l2tp: introduce L...
67

c5fdae044   Guillaume Nault   l2tp: rework sock...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  		if (!net_eq(sock_net(sk), net))
  			continue;
  
  		if (sk->sk_bound_dev_if && dif && sk->sk_bound_dev_if != dif)
  			continue;
  
  		if (sk_laddr && !ipv6_addr_any(sk_laddr) &&
  		    !ipv6_addr_any(laddr) && !ipv6_addr_equal(sk_laddr, laddr))
  			continue;
  
  		if (!ipv6_addr_any(sk_raddr) && raddr &&
  		    !ipv6_addr_any(raddr) && !ipv6_addr_equal(sk_raddr, raddr))
  			continue;
  
  		if (l2tp->conn_id != tunnel_id)
  			continue;
  
  		goto found;
a32e0eec7   Chris Elston   l2tp: introduce L...
86
87
88
89
90
91
  	}
  
  	sk = NULL;
  found:
  	return sk;
  }
a32e0eec7   Chris Elston   l2tp: introduce L...
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  /* When processing receive frames, there are two cases to
   * consider. Data frames consist of a non-zero session-id and an
   * optional cookie. Control frames consist of a regular L2TP header
   * preceded by 32-bits of zeros.
   *
   * L2TPv3 Session Header Over IP
   *
   *  0                   1                   2                   3
   *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                           Session ID                          |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |               Cookie (optional, maximum 64 bits)...
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   *                                                                 |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   *
   * L2TPv3 Control Message Header Over IP
   *
   *  0                   1                   2                   3
   *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                      (32 bits of zeros)                       |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |T|L|x|x|S|x|x|x|x|x|x|x|  Ver  |             Length            |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                     Control Connection ID                     |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |               Ns              |               Nr              |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   *
   * All control frames are passed to userspace.
   */
  static int l2tp_ip6_recv(struct sk_buff *skb)
  {
0e6b52598   Shmulik Ladkani   net: l2tp: Make l...
127
  	struct net *net = dev_net(skb->dev);
a32e0eec7   Chris Elston   l2tp: introduce L...
128
129
130
131
132
133
  	struct sock *sk;
  	u32 session_id;
  	u32 tunnel_id;
  	unsigned char *ptr, *optr;
  	struct l2tp_session *session;
  	struct l2tp_tunnel *tunnel = NULL;
8f7dc9ae4   Guillaume Nault   l2tp: don't use l...
134
  	struct ipv6hdr *iph;
a32e0eec7   Chris Elston   l2tp: introduce L...
135
  	int length;
a32e0eec7   Chris Elston   l2tp: introduce L...
136

a32e0eec7   Chris Elston   l2tp: introduce L...
137
138
  	if (!pskb_may_pull(skb, 4))
  		goto discard;
be447f305   Haishuang Yan   ipv6: l2tp: fix a...
139
140
  	/* Point to L2TP header */
  	optr = ptr = skb->data;
a32e0eec7   Chris Elston   l2tp: introduce L...
141
142
143
144
145
146
147
148
149
150
151
152
153
  	session_id = ntohl(*((__be32 *) ptr));
  	ptr += 4;
  
  	/* RFC3931: L2TP/IP packets have the first 4 bytes containing
  	 * the session_id. If it is 0, the packet is a L2TP control
  	 * frame and the session_id value can be discarded.
  	 */
  	if (session_id == 0) {
  		__skb_pull(skb, 4);
  		goto pass_up;
  	}
  
  	/* Ok, this is a data packet. Lookup the session. */
61b9a0477   Guillaume Nault   l2tp: fix race in...
154
155
  	session = l2tp_session_get(net, NULL, session_id, true);
  	if (!session)
a32e0eec7   Chris Elston   l2tp: introduce L...
156
157
158
  		goto discard;
  
  	tunnel = session->tunnel;
61b9a0477   Guillaume Nault   l2tp: fix race in...
159
160
  	if (!tunnel)
  		goto discard_sess;
a32e0eec7   Chris Elston   l2tp: introduce L...
161
162
163
164
165
  
  	/* Trace packet contents, if enabled */
  	if (tunnel->debug & L2TP_MSG_DATA) {
  		length = min(32u, skb->len);
  		if (!pskb_may_pull(skb, length))
61b9a0477   Guillaume Nault   l2tp: fix race in...
166
  			goto discard_sess;
a32e0eec7   Chris Elston   l2tp: introduce L...
167

be447f305   Haishuang Yan   ipv6: l2tp: fix a...
168
169
170
  		/* Point to L2TP header */
  		optr = ptr = skb->data;
  		ptr += 4;
a4ca44fa5   Joe Perches   net: l2tp: Standa...
171
172
173
  		pr_debug("%s: ip recv
  ", tunnel->name);
  		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
a32e0eec7   Chris Elston   l2tp: introduce L...
174
175
176
177
  	}
  
  	l2tp_recv_common(session, skb, ptr, optr, 0, skb->len,
  			 tunnel->recv_payload_hook);
61b9a0477   Guillaume Nault   l2tp: fix race in...
178
  	l2tp_session_dec_refcount(session);
a32e0eec7   Chris Elston   l2tp: introduce L...
179
180
181
182
183
184
185
186
187
188
189
  	return 0;
  
  pass_up:
  	/* Get the tunnel_id from the L2TP header */
  	if (!pskb_may_pull(skb, 12))
  		goto discard;
  
  	if ((skb->data[0] & 0xc0) != 0xc0)
  		goto discard;
  
  	tunnel_id = ntohl(*(__be32 *) &skb->data[4]);
8f7dc9ae4   Guillaume Nault   l2tp: don't use l...
190
191
192
193
194
195
  	iph = ipv6_hdr(skb);
  
  	read_lock_bh(&l2tp_ip6_lock);
  	sk = __l2tp_ip6_bind_lookup(net, &iph->daddr, &iph->saddr,
  				    inet6_iif(skb), tunnel_id);
  	if (!sk) {
a32e0eec7   Chris Elston   l2tp: introduce L...
196
  		read_unlock_bh(&l2tp_ip6_lock);
8f7dc9ae4   Guillaume Nault   l2tp: don't use l...
197
  		goto discard;
a32e0eec7   Chris Elston   l2tp: introduce L...
198
  	}
8f7dc9ae4   Guillaume Nault   l2tp: don't use l...
199
200
  	sock_hold(sk);
  	read_unlock_bh(&l2tp_ip6_lock);
a32e0eec7   Chris Elston   l2tp: introduce L...
201

a32e0eec7   Chris Elston   l2tp: introduce L...
202
203
204
205
206
207
  	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
  		goto discard_put;
  
  	nf_reset(skb);
  
  	return sk_receive_skb(sk, skb, 1);
61b9a0477   Guillaume Nault   l2tp: fix race in...
208
209
210
211
212
  discard_sess:
  	if (session->deref)
  		session->deref(session);
  	l2tp_session_dec_refcount(session);
  	goto discard;
a32e0eec7   Chris Elston   l2tp: introduce L...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  discard_put:
  	sock_put(sk);
  
  discard:
  	kfree_skb(skb);
  	return 0;
  }
  
  static int l2tp_ip6_open(struct sock *sk)
  {
  	/* Prevent autobind. We don't have ports. */
  	inet_sk(sk)->inet_num = IPPROTO_L2TP;
  
  	write_lock_bh(&l2tp_ip6_lock);
  	sk_add_node(sk, &l2tp_ip6_table);
  	write_unlock_bh(&l2tp_ip6_lock);
  
  	return 0;
  }
  
  static void l2tp_ip6_close(struct sock *sk, long timeout)
  {
  	write_lock_bh(&l2tp_ip6_lock);
  	hlist_del_init(&sk->sk_bind_node);
  	sk_del_node_init(sk);
  	write_unlock_bh(&l2tp_ip6_lock);
  
  	sk_common_release(sk);
  }
  
  static void l2tp_ip6_destroy_sock(struct sock *sk)
  {
936063175   Tom Parkin   l2tp: close sessi...
245
  	struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk);
a32e0eec7   Chris Elston   l2tp: introduce L...
246
247
248
  	lock_sock(sk);
  	ip6_flush_pending_frames(sk);
  	release_sock(sk);
936063175   Tom Parkin   l2tp: close sessi...
249
250
251
252
  	if (tunnel) {
  		l2tp_tunnel_closeall(tunnel);
  		sock_put(sk);
  	}
a32e0eec7   Chris Elston   l2tp: introduce L...
253
254
255
256
257
258
259
260
  	inet6_destroy_sock(sk);
  }
  
  static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
  {
  	struct inet_sock *inet = inet_sk(sk);
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct sockaddr_l2tpip6 *addr = (struct sockaddr_l2tpip6 *) uaddr;
0e6b52598   Shmulik Ladkani   net: l2tp: Make l...
261
  	struct net *net = sock_net(sk);
a32e0eec7   Chris Elston   l2tp: introduce L...
262
  	__be32 v4addr = 0;
d5e3a1909   Guillaume Nault   l2tp: fix racy so...
263
  	int bound_dev_if;
a32e0eec7   Chris Elston   l2tp: introduce L...
264
265
  	int addr_type;
  	int err;
c51ce4973   James Chapman   l2tp: fix oops in...
266
267
  	if (addr->l2tp_family != AF_INET6)
  		return -EINVAL;
a32e0eec7   Chris Elston   l2tp: introduce L...
268
269
270
271
272
273
274
275
276
277
278
279
  	if (addr_len < sizeof(*addr))
  		return -EINVAL;
  
  	addr_type = ipv6_addr_type(&addr->l2tp_addr);
  
  	/* l2tp_ip6 sockets are IPv6 only */
  	if (addr_type == IPV6_ADDR_MAPPED)
  		return -EADDRNOTAVAIL;
  
  	/* L2TP is point-point, not multicast */
  	if (addr_type & IPV6_ADDR_MULTICAST)
  		return -EADDRNOTAVAIL;
a32e0eec7   Chris Elston   l2tp: introduce L...
280
281
282
  	lock_sock(sk);
  
  	err = -EINVAL;
32c231164   Guillaume Nault   l2tp: fix racy SO...
283
284
  	if (!sock_flag(sk, SOCK_ZAPPED))
  		goto out_unlock;
a32e0eec7   Chris Elston   l2tp: introduce L...
285
286
  	if (sk->sk_state != TCP_CLOSE)
  		goto out_unlock;
d5e3a1909   Guillaume Nault   l2tp: fix racy so...
287
  	bound_dev_if = sk->sk_bound_dev_if;
a32e0eec7   Chris Elston   l2tp: introduce L...
288
289
290
291
292
293
  	/* Check if the address belongs to the host. */
  	rcu_read_lock();
  	if (addr_type != IPV6_ADDR_ANY) {
  		struct net_device *dev = NULL;
  
  		if (addr_type & IPV6_ADDR_LINKLOCAL) {
d5e3a1909   Guillaume Nault   l2tp: fix racy so...
294
295
  			if (addr->l2tp_scope_id)
  				bound_dev_if = addr->l2tp_scope_id;
a32e0eec7   Chris Elston   l2tp: introduce L...
296
297
  
  			/* Binding to link-local address requires an
d5e3a1909   Guillaume Nault   l2tp: fix racy so...
298
299
300
  			 * interface.
  			 */
  			if (!bound_dev_if)
a32e0eec7   Chris Elston   l2tp: introduce L...
301
302
303
  				goto out_unlock_rcu;
  
  			err = -ENODEV;
d5e3a1909   Guillaume Nault   l2tp: fix racy so...
304
  			dev = dev_get_by_index_rcu(sock_net(sk), bound_dev_if);
a32e0eec7   Chris Elston   l2tp: introduce L...
305
306
307
308
309
310
311
312
313
314
315
316
317
  			if (!dev)
  				goto out_unlock_rcu;
  		}
  
  		/* ipv4 addr of the socket is invalid.  Only the
  		 * unspecified and mapped address have a v4 equivalent.
  		 */
  		v4addr = LOOPBACK4_IPV6;
  		err = -EADDRNOTAVAIL;
  		if (!ipv6_chk_addr(sock_net(sk), &addr->l2tp_addr, dev, 0))
  			goto out_unlock_rcu;
  	}
  	rcu_read_unlock();
d5e3a1909   Guillaume Nault   l2tp: fix racy so...
318
  	write_lock_bh(&l2tp_ip6_lock);
a9b2dff80   Guillaume Nault   l2tp: take remote...
319
  	if (__l2tp_ip6_bind_lookup(net, &addr->l2tp_addr, NULL, bound_dev_if,
d5e3a1909   Guillaume Nault   l2tp: fix racy so...
320
321
322
323
324
325
326
327
328
  				   addr->l2tp_conn_id)) {
  		write_unlock_bh(&l2tp_ip6_lock);
  		err = -EADDRINUSE;
  		goto out_unlock;
  	}
  
  	inet->inet_saddr = v4addr;
  	inet->inet_rcv_saddr = v4addr;
  	sk->sk_bound_dev_if = bound_dev_if;
efe4208f4   Eric Dumazet   ipv6: make lookup...
329
  	sk->sk_v6_rcv_saddr = addr->l2tp_addr;
a32e0eec7   Chris Elston   l2tp: introduce L...
330
331
332
  	np->saddr = addr->l2tp_addr;
  
  	l2tp_ip6_sk(sk)->conn_id = addr->l2tp_conn_id;
a32e0eec7   Chris Elston   l2tp: introduce L...
333
334
335
  	sk_add_bind_node(sk, &l2tp_ip6_bind_table);
  	sk_del_node_init(sk);
  	write_unlock_bh(&l2tp_ip6_lock);
c51ce4973   James Chapman   l2tp: fix oops in...
336
  	sock_reset_flag(sk, SOCK_ZAPPED);
a32e0eec7   Chris Elston   l2tp: introduce L...
337
338
339
340
341
342
343
  	release_sock(sk);
  	return 0;
  
  out_unlock_rcu:
  	rcu_read_unlock();
  out_unlock:
  	release_sock(sk);
a32e0eec7   Chris Elston   l2tp: introduce L...
344

a32e0eec7   Chris Elston   l2tp: introduce L...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  	return err;
  }
  
  static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr,
  			    int addr_len)
  {
  	struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *) uaddr;
  	struct sockaddr_in6	*usin = (struct sockaddr_in6 *) uaddr;
  	struct in6_addr	*daddr;
  	int	addr_type;
  	int rc;
  
  	if (addr_len < sizeof(*lsa))
  		return -EINVAL;
82b276cd2   Hannes Frederic Sowa   ipv6: protect pro...
359
360
  	if (usin->sin6_family != AF_INET6)
  		return -EINVAL;
a32e0eec7   Chris Elston   l2tp: introduce L...
361
362
363
364
365
366
367
368
369
  	addr_type = ipv6_addr_type(&usin->sin6_addr);
  	if (addr_type & IPV6_ADDR_MULTICAST)
  		return -EINVAL;
  
  	if (addr_type & IPV6_ADDR_MAPPED) {
  		daddr = &usin->sin6_addr;
  		if (ipv4_is_multicast(daddr->s6_addr32[3]))
  			return -EINVAL;
  	}
a32e0eec7   Chris Elston   l2tp: introduce L...
370
  	lock_sock(sk);
0382a25af   Guillaume Nault   l2tp: lock socket...
371
372
373
374
375
376
377
378
379
  	 /* Must bind first - autobinding does not work */
  	if (sock_flag(sk, SOCK_ZAPPED)) {
  		rc = -EINVAL;
  		goto out_sk;
  	}
  
  	rc = __ip6_datagram_connect(sk, uaddr, addr_len);
  	if (rc < 0)
  		goto out_sk;
a32e0eec7   Chris Elston   l2tp: introduce L...
380
381
382
383
384
385
  	l2tp_ip6_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
  
  	write_lock_bh(&l2tp_ip6_lock);
  	hlist_del_init(&sk->sk_bind_node);
  	sk_add_bind_node(sk, &l2tp_ip6_bind_table);
  	write_unlock_bh(&l2tp_ip6_lock);
0382a25af   Guillaume Nault   l2tp: lock socket...
386
  out_sk:
a32e0eec7   Chris Elston   l2tp: introduce L...
387
388
389
390
  	release_sock(sk);
  
  	return rc;
  }
c51ce4973   James Chapman   l2tp: fix oops in...
391
392
393
394
  static int l2tp_ip6_disconnect(struct sock *sk, int flags)
  {
  	if (sock_flag(sk, SOCK_ZAPPED))
  		return 0;
286c72dea   Eric Dumazet   udp: must lock th...
395
  	return __udp_disconnect(sk, flags);
c51ce4973   James Chapman   l2tp: fix oops in...
396
  }
a32e0eec7   Chris Elston   l2tp: introduce L...
397
398
399
400
401
402
403
404
405
406
407
  static int l2tp_ip6_getname(struct socket *sock, struct sockaddr *uaddr,
  			    int *uaddr_len, int peer)
  {
  	struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *)uaddr;
  	struct sock *sk = sock->sk;
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct l2tp_ip6_sock *lsk = l2tp_ip6_sk(sk);
  
  	lsa->l2tp_family = AF_INET6;
  	lsa->l2tp_flowinfo = 0;
  	lsa->l2tp_scope_id = 0;
04d4fbca1   Mathias Krause   l2tp: fix info le...
408
  	lsa->l2tp_unused = 0;
a32e0eec7   Chris Elston   l2tp: introduce L...
409
410
411
412
  	if (peer) {
  		if (!lsk->peer_conn_id)
  			return -ENOTCONN;
  		lsa->l2tp_conn_id = lsk->peer_conn_id;
efe4208f4   Eric Dumazet   ipv6: make lookup...
413
  		lsa->l2tp_addr = sk->sk_v6_daddr;
a32e0eec7   Chris Elston   l2tp: introduce L...
414
415
416
  		if (np->sndflow)
  			lsa->l2tp_flowinfo = np->flow_label;
  	} else {
efe4208f4   Eric Dumazet   ipv6: make lookup...
417
  		if (ipv6_addr_any(&sk->sk_v6_rcv_saddr))
a32e0eec7   Chris Elston   l2tp: introduce L...
418
419
  			lsa->l2tp_addr = np->saddr;
  		else
efe4208f4   Eric Dumazet   ipv6: make lookup...
420
  			lsa->l2tp_addr = sk->sk_v6_rcv_saddr;
a32e0eec7   Chris Elston   l2tp: introduce L...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  
  		lsa->l2tp_conn_id = lsk->conn_id;
  	}
  	if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
  		lsa->l2tp_scope_id = sk->sk_bound_dev_if;
  	*uaddr_len = sizeof(*lsa);
  	return 0;
  }
  
  static int l2tp_ip6_backlog_recv(struct sock *sk, struct sk_buff *skb)
  {
  	int rc;
  
  	/* Charge it to the socket, dropping if the queue is full. */
  	rc = sock_queue_rcv_skb(sk, skb);
  	if (rc < 0)
  		goto drop;
  
  	return 0;
  
  drop:
0e6b52598   Shmulik Ladkani   net: l2tp: Make l...
442
  	IP_INC_STATS(sock_net(sk), IPSTATS_MIB_INDISCARDS);
a32e0eec7   Chris Elston   l2tp: introduce L...
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  	kfree_skb(skb);
  	return -1;
  }
  
  static int l2tp_ip6_push_pending_frames(struct sock *sk)
  {
  	struct sk_buff *skb;
  	__be32 *transhdr = NULL;
  	int err = 0;
  
  	skb = skb_peek(&sk->sk_write_queue);
  	if (skb == NULL)
  		goto out;
  
  	transhdr = (__be32 *)skb_transport_header(skb);
  	*transhdr = 0;
  
  	err = ip6_push_pending_frames(sk);
  
  out:
  	return err;
  }
  
  /* Userspace will call sendmsg() on the tunnel socket to send L2TP
   * control frames.
   */
1b7841404   Ying Xue   net: Remove iocb ...
469
  static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
a32e0eec7   Chris Elston   l2tp: introduce L...
470
471
  {
  	struct ipv6_txoptions opt_space;
342dfc306   Steffen Hurrle   net: add build-ti...
472
  	DECLARE_SOCKADDR(struct sockaddr_l2tpip6 *, lsa, msg->msg_name);
a32e0eec7   Chris Elston   l2tp: introduce L...
473
474
  	struct in6_addr *daddr, *final_p, final;
  	struct ipv6_pinfo *np = inet6_sk(sk);
45f6fad84   Eric Dumazet   ipv6: add complet...
475
  	struct ipv6_txoptions *opt_to_free = NULL;
a32e0eec7   Chris Elston   l2tp: introduce L...
476
477
478
479
  	struct ipv6_txoptions *opt = NULL;
  	struct ip6_flowlabel *flowlabel = NULL;
  	struct dst_entry *dst = NULL;
  	struct flowi6 fl6;
ad1e46a83   Soheil Hassas Yeganeh   ipv6: process soc...
480
  	struct sockcm_cookie sockc_unused = {0};
26879da58   Wei Wang   ipv6: add new str...
481
  	struct ipcm6_cookie ipc6;
a32e0eec7   Chris Elston   l2tp: introduce L...
482
  	int addr_len = msg->msg_namelen;
a32e0eec7   Chris Elston   l2tp: introduce L...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  	int transhdrlen = 4; /* zero session-id */
  	int ulen = len + transhdrlen;
  	int err;
  
  	/* Rough check on arithmetic overflow,
  	   better check is made in ip6_append_data().
  	 */
  	if (len > INT_MAX)
  		return -EMSGSIZE;
  
  	/* Mirror BSD error message compatibility */
  	if (msg->msg_flags & MSG_OOB)
  		return -EOPNOTSUPP;
  
  	/*
  	 *	Get and verify the address.
  	 */
  	memset(&fl6, 0, sizeof(fl6));
  
  	fl6.flowi6_mark = sk->sk_mark;
e2d118a1c   Lorenzo Colitti   net: inet: Suppor...
503
  	fl6.flowi6_uid = sk->sk_uid;
a32e0eec7   Chris Elston   l2tp: introduce L...
504

26879da58   Wei Wang   ipv6: add new str...
505
506
507
  	ipc6.hlimit = -1;
  	ipc6.tclass = -1;
  	ipc6.dontfrag = -1;
a32e0eec7   Chris Elston   l2tp: introduce L...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
  	if (lsa) {
  		if (addr_len < SIN6_LEN_RFC2133)
  			return -EINVAL;
  
  		if (lsa->l2tp_family && lsa->l2tp_family != AF_INET6)
  			return -EAFNOSUPPORT;
  
  		daddr = &lsa->l2tp_addr;
  		if (np->sndflow) {
  			fl6.flowlabel = lsa->l2tp_flowinfo & IPV6_FLOWINFO_MASK;
  			if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
  				flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
  				if (flowlabel == NULL)
  					return -EINVAL;
a32e0eec7   Chris Elston   l2tp: introduce L...
522
523
524
525
526
527
528
529
  			}
  		}
  
  		/*
  		 * Otherwise it will be difficult to maintain
  		 * sk->sk_dst_cache.
  		 */
  		if (sk->sk_state == TCP_ESTABLISHED &&
efe4208f4   Eric Dumazet   ipv6: make lookup...
530
531
  		    ipv6_addr_equal(daddr, &sk->sk_v6_daddr))
  			daddr = &sk->sk_v6_daddr;
a32e0eec7   Chris Elston   l2tp: introduce L...
532
533
534
535
536
537
538
539
  
  		if (addr_len >= sizeof(struct sockaddr_in6) &&
  		    lsa->l2tp_scope_id &&
  		    ipv6_addr_type(daddr) & IPV6_ADDR_LINKLOCAL)
  			fl6.flowi6_oif = lsa->l2tp_scope_id;
  	} else {
  		if (sk->sk_state != TCP_ESTABLISHED)
  			return -EDESTADDRREQ;
efe4208f4   Eric Dumazet   ipv6: make lookup...
540
  		daddr = &sk->sk_v6_daddr;
a32e0eec7   Chris Elston   l2tp: introduce L...
541
542
543
544
545
546
547
548
549
550
  		fl6.flowlabel = np->flow_label;
  	}
  
  	if (fl6.flowi6_oif == 0)
  		fl6.flowi6_oif = sk->sk_bound_dev_if;
  
  	if (msg->msg_controllen) {
  		opt = &opt_space;
  		memset(opt, 0, sizeof(struct ipv6_txoptions));
  		opt->tot_len = sizeof(struct ipv6_txoptions);
26879da58   Wei Wang   ipv6: add new str...
551
  		ipc6.opt = opt;
a32e0eec7   Chris Elston   l2tp: introduce L...
552

26879da58   Wei Wang   ipv6: add new str...
553
554
555
  		err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, &ipc6,
  					    &sockc_unused);
  		if (err < 0) {
a32e0eec7   Chris Elston   l2tp: introduce L...
556
557
558
559
560
561
562
563
564
565
566
  			fl6_sock_release(flowlabel);
  			return err;
  		}
  		if ((fl6.flowlabel & IPV6_FLOWLABEL_MASK) && !flowlabel) {
  			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
  			if (flowlabel == NULL)
  				return -EINVAL;
  		}
  		if (!(opt->opt_nflen|opt->opt_flen))
  			opt = NULL;
  	}
45f6fad84   Eric Dumazet   ipv6: add complet...
567
568
569
570
  	if (!opt) {
  		opt = txopt_get(np);
  		opt_to_free = opt;
  	}
a32e0eec7   Chris Elston   l2tp: introduce L...
571
572
573
  	if (flowlabel)
  		opt = fl6_merge_options(&opt_space, flowlabel, opt);
  	opt = ipv6_fixup_options(&opt_space, opt);
26879da58   Wei Wang   ipv6: add new str...
574
  	ipc6.opt = opt;
a32e0eec7   Chris Elston   l2tp: introduce L...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  
  	fl6.flowi6_proto = sk->sk_protocol;
  	if (!ipv6_addr_any(daddr))
  		fl6.daddr = *daddr;
  	else
  		fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
  	if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
  		fl6.saddr = np->saddr;
  
  	final_p = fl6_update_dst(&fl6, opt, &final);
  
  	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
  		fl6.flowi6_oif = np->mcast_oif;
  	else if (!fl6.flowi6_oif)
  		fl6.flowi6_oif = np->ucast_oif;
  
  	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
38b7097b5   Hannes Frederic Sowa   ipv6: use TOS mar...
592
593
594
595
  	if (ipc6.tclass < 0)
  		ipc6.tclass = np->tclass;
  
  	fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
0e0d44ab4   Steffen Klassert   net: Remove FLOWI...
596
  	dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
a32e0eec7   Chris Elston   l2tp: introduce L...
597
598
599
600
  	if (IS_ERR(dst)) {
  		err = PTR_ERR(dst);
  		goto out;
  	}
26879da58   Wei Wang   ipv6: add new str...
601
602
  	if (ipc6.hlimit < 0)
  		ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
a32e0eec7   Chris Elston   l2tp: introduce L...
603

26879da58   Wei Wang   ipv6: add new str...
604
605
  	if (ipc6.dontfrag < 0)
  		ipc6.dontfrag = np->dontfrag;
a32e0eec7   Chris Elston   l2tp: introduce L...
606
607
608
609
610
611
  
  	if (msg->msg_flags & MSG_CONFIRM)
  		goto do_confirm;
  
  back_from_confirm:
  	lock_sock(sk);
f69e6d131   Al Viro   ip_generic_getfra...
612
  	err = ip6_append_data(sk, ip_generic_getfrag, msg,
26879da58   Wei Wang   ipv6: add new str...
613
  			      ulen, transhdrlen, &ipc6,
a32e0eec7   Chris Elston   l2tp: introduce L...
614
  			      &fl6, (struct rt6_info *)dst,
26879da58   Wei Wang   ipv6: add new str...
615
  			      msg->msg_flags, &sockc_unused);
a32e0eec7   Chris Elston   l2tp: introduce L...
616
617
618
619
620
621
622
623
624
  	if (err)
  		ip6_flush_pending_frames(sk);
  	else if (!(msg->msg_flags & MSG_MORE))
  		err = l2tp_ip6_push_pending_frames(sk);
  	release_sock(sk);
  done:
  	dst_release(dst);
  out:
  	fl6_sock_release(flowlabel);
45f6fad84   Eric Dumazet   ipv6: add complet...
625
  	txopt_put(opt_to_free);
a32e0eec7   Chris Elston   l2tp: introduce L...
626
627
628
629
  
  	return err < 0 ? err : len;
  
  do_confirm:
0dec879f6   Julian Anastasov   net: use dst_conf...
630
631
  	if (msg->msg_flags & MSG_PROBE)
  		dst_confirm_neigh(dst, &fl6.daddr);
a32e0eec7   Chris Elston   l2tp: introduce L...
632
633
634
635
636
  	if (!(msg->msg_flags & MSG_PROBE) || len)
  		goto back_from_confirm;
  	err = 0;
  	goto done;
  }
1b7841404   Ying Xue   net: Remove iocb ...
637
638
  static int l2tp_ip6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
  			    int noblock, int flags, int *addr_len)
a32e0eec7   Chris Elston   l2tp: introduce L...
639
  {
700163db3   Tom Parkin   l2tp: correctly h...
640
  	struct ipv6_pinfo *np = inet6_sk(sk);
342dfc306   Steffen Hurrle   net: add build-ti...
641
  	DECLARE_SOCKADDR(struct sockaddr_l2tpip6 *, lsa, msg->msg_name);
a32e0eec7   Chris Elston   l2tp: introduce L...
642
643
644
645
646
647
648
649
650
651
652
  	size_t copied = 0;
  	int err = -EOPNOTSUPP;
  	struct sk_buff *skb;
  
  	if (flags & MSG_OOB)
  		goto out;
  
  	if (addr_len)
  		*addr_len = sizeof(*lsa);
  
  	if (flags & MSG_ERRQUEUE)
85fbaa750   Hannes Frederic Sowa   inet: fix addr_le...
653
  		return ipv6_recv_error(sk, msg, len, addr_len);
a32e0eec7   Chris Elston   l2tp: introduce L...
654
655
656
657
658
659
660
661
662
663
  
  	skb = skb_recv_datagram(sk, flags, noblock, &err);
  	if (!skb)
  		goto out;
  
  	copied = skb->len;
  	if (len < copied) {
  		msg->msg_flags |= MSG_TRUNC;
  		copied = len;
  	}
51f3d02b9   David S. Miller   net: Add and use ...
664
  	err = skb_copy_datagram_msg(skb, 0, msg, copied);
a32e0eec7   Chris Elston   l2tp: introduce L...
665
666
667
668
669
670
671
672
673
674
675
676
  	if (err)
  		goto done;
  
  	sock_recv_timestamp(msg, sk, skb);
  
  	/* Copy the address. */
  	if (lsa) {
  		lsa->l2tp_family = AF_INET6;
  		lsa->l2tp_unused = 0;
  		lsa->l2tp_addr = ipv6_hdr(skb)->saddr;
  		lsa->l2tp_flowinfo = 0;
  		lsa->l2tp_scope_id = 0;
b860d3cc6   Mathias Krause   l2tp: fix info le...
677
  		lsa->l2tp_conn_id = 0;
a32e0eec7   Chris Elston   l2tp: introduce L...
678
  		if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
4330487ac   Duan Jiong   net: use inet6_ii...
679
  			lsa->l2tp_scope_id = inet6_iif(skb);
a32e0eec7   Chris Elston   l2tp: introduce L...
680
  	}
700163db3   Tom Parkin   l2tp: correctly h...
681
682
  	if (np->rxopt.all)
  		ip6_datagram_recv_ctl(sk, msg, skb);
a32e0eec7   Chris Elston   l2tp: introduce L...
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
  
  	if (flags & MSG_TRUNC)
  		copied = skb->len;
  done:
  	skb_free_datagram(sk, skb);
  out:
  	return err ? err : copied;
  }
  
  static struct proto l2tp_ip6_prot = {
  	.name		   = "L2TP/IPv6",
  	.owner		   = THIS_MODULE,
  	.init		   = l2tp_ip6_open,
  	.close		   = l2tp_ip6_close,
  	.bind		   = l2tp_ip6_bind,
  	.connect	   = l2tp_ip6_connect,
c51ce4973   James Chapman   l2tp: fix oops in...
699
  	.disconnect	   = l2tp_ip6_disconnect,
72fb96e7b   Eric Dumazet   l2tp: do not use ...
700
  	.ioctl		   = l2tp_ioctl,
a32e0eec7   Chris Elston   l2tp: introduce L...
701
702
703
704
705
706
  	.destroy	   = l2tp_ip6_destroy_sock,
  	.setsockopt	   = ipv6_setsockopt,
  	.getsockopt	   = ipv6_getsockopt,
  	.sendmsg	   = l2tp_ip6_sendmsg,
  	.recvmsg	   = l2tp_ip6_recvmsg,
  	.backlog_rcv	   = l2tp_ip6_backlog_recv,
496611d7b   Craig Gallek   inet: create IPv6...
707
  	.hash		   = inet6_hash,
a32e0eec7   Chris Elston   l2tp: introduce L...
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
  	.unhash		   = inet_unhash,
  	.obj_size	   = sizeof(struct l2tp_ip6_sock),
  #ifdef CONFIG_COMPAT
  	.compat_setsockopt = compat_ipv6_setsockopt,
  	.compat_getsockopt = compat_ipv6_getsockopt,
  #endif
  };
  
  static const struct proto_ops l2tp_ip6_ops = {
  	.family		   = PF_INET6,
  	.owner		   = THIS_MODULE,
  	.release	   = inet6_release,
  	.bind		   = inet6_bind,
  	.connect	   = inet_dgram_connect,
  	.socketpair	   = sock_no_socketpair,
  	.accept		   = sock_no_accept,
  	.getname	   = l2tp_ip6_getname,
  	.poll		   = datagram_poll,
  	.ioctl		   = inet6_ioctl,
  	.listen		   = sock_no_listen,
  	.shutdown	   = inet_shutdown,
  	.setsockopt	   = sock_common_setsockopt,
  	.getsockopt	   = sock_common_getsockopt,
  	.sendmsg	   = inet_sendmsg,
  	.recvmsg	   = sock_common_recvmsg,
  	.mmap		   = sock_no_mmap,
  	.sendpage	   = sock_no_sendpage,
  #ifdef CONFIG_COMPAT
  	.compat_setsockopt = compat_sock_common_setsockopt,
  	.compat_getsockopt = compat_sock_common_getsockopt,
  #endif
  };
  
  static struct inet_protosw l2tp_ip6_protosw = {
  	.type		= SOCK_DGRAM,
  	.protocol	= IPPROTO_L2TP,
  	.prot		= &l2tp_ip6_prot,
  	.ops		= &l2tp_ip6_ops,
a32e0eec7   Chris Elston   l2tp: introduce L...
746
747
748
749
750
751
752
753
754
  };
  
  static struct inet6_protocol l2tp_ip6_protocol __read_mostly = {
  	.handler	= l2tp_ip6_recv,
  };
  
  static int __init l2tp_ip6_init(void)
  {
  	int err;
a4ca44fa5   Joe Perches   net: l2tp: Standa...
755
756
  	pr_info("L2TP IP encapsulation support for IPv6 (L2TPv3)
  ");
a32e0eec7   Chris Elston   l2tp: introduce L...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
  
  	err = proto_register(&l2tp_ip6_prot, 1);
  	if (err != 0)
  		goto out;
  
  	err = inet6_add_protocol(&l2tp_ip6_protocol, IPPROTO_L2TP);
  	if (err)
  		goto out1;
  
  	inet6_register_protosw(&l2tp_ip6_protosw);
  	return 0;
  
  out1:
  	proto_unregister(&l2tp_ip6_prot);
  out:
  	return err;
  }
  
  static void __exit l2tp_ip6_exit(void)
  {
  	inet6_unregister_protosw(&l2tp_ip6_protosw);
  	inet6_del_protocol(&l2tp_ip6_protocol, IPPROTO_L2TP);
  	proto_unregister(&l2tp_ip6_prot);
  }
  
  module_init(l2tp_ip6_init);
  module_exit(l2tp_ip6_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Chris Elston <celston@katalix.com>");
  MODULE_DESCRIPTION("L2TP IP encapsulation for IPv6");
  MODULE_VERSION("1.0");
  
  /* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
   * enums
   */
  MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 2, IPPROTO_L2TP);
163c2e252   stephen hemminger   l2tp: auto load I...
794
  MODULE_ALIAS_NET_PF_PROTO(PF_INET6, IPPROTO_L2TP);