Blame view
net/l2tp/l2tp_ip.c
15.7 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
20dcb1107 l2tp: cleanup com... |
2 |
/* L2TPv3 IP encapsulation support |
0d76751fa l2tp: Add L2TPv3 ... |
3 4 |
* * Copyright (c) 2008,2009,2010 Katalix Systems Ltd |
0d76751fa l2tp: Add L2TPv3 ... |
5 |
*/ |
a4ca44fa5 net: l2tp: Standa... |
6 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
72fb96e7b l2tp: do not use ... |
7 |
#include <asm/ioctls.h> |
0d76751fa l2tp: Add L2TPv3 ... |
8 9 10 11 12 13 14 15 16 17 18 19 |
#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 <net/sock.h> #include <net/ip.h> #include <net/icmp.h> #include <net/udp.h> #include <net/inet_common.h> |
0d76751fa l2tp: Add L2TPv3 ... |
20 21 22 23 24 25 26 27 28 |
#include <net/tcp_states.h> #include <net/protocol.h> #include <net/xfrm.h> #include "l2tp_core.h" struct l2tp_ip_sock { /* inet_sock has to be the first member of l2tp_ip_sock */ struct inet_sock inet; |
c8657fd50 l2tp: remove unus... |
29 30 |
u32 conn_id; u32 peer_conn_id; |
0d76751fa l2tp: Add L2TPv3 ... |
31 32 33 34 35 36 37 38 39 40 |
}; static DEFINE_RWLOCK(l2tp_ip_lock); static struct hlist_head l2tp_ip_table; static struct hlist_head l2tp_ip_bind_table; static inline struct l2tp_ip_sock *l2tp_ip_sk(const struct sock *sk) { return (struct l2tp_ip_sock *)sk; } |
a9b2dff80 l2tp: take remote... |
41 42 |
static struct sock *__l2tp_ip_bind_lookup(const struct net *net, __be32 laddr, __be32 raddr, int dif, u32 tunnel_id) |
0d76751fa l2tp: Add L2TPv3 ... |
43 |
{ |
0d76751fa l2tp: Add L2TPv3 ... |
44 |
struct sock *sk; |
b67bfe0d4 hlist: drop the n... |
45 |
sk_for_each_bound(sk, &l2tp_ip_bind_table) { |
bb39b0bdc l2tp: make __l2tp... |
46 47 |
const struct l2tp_ip_sock *l2tp = l2tp_ip_sk(sk); const struct inet_sock *inet = inet_sk(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
48 |
|
c5fdae044 l2tp: rework sock... |
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
if (!net_eq(sock_net(sk), net)) continue; if (sk->sk_bound_dev_if && dif && sk->sk_bound_dev_if != dif) continue; if (inet->inet_rcv_saddr && laddr && inet->inet_rcv_saddr != laddr) continue; if (inet->inet_daddr && raddr && inet->inet_daddr != raddr) continue; if (l2tp->conn_id != tunnel_id) continue; goto found; |
0d76751fa l2tp: Add L2TPv3 ... |
66 67 68 69 70 71 |
} sk = NULL; found: return sk; } |
0d76751fa l2tp: Add L2TPv3 ... |
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
/* 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_ip_recv(struct sk_buff *skb) { |
9d6ddb199 l2tp: Make ipv4 p... |
107 |
struct net *net = dev_net(skb->dev); |
0d76751fa l2tp: Add L2TPv3 ... |
108 109 110 111 112 113 |
struct sock *sk; u32 session_id; u32 tunnel_id; unsigned char *ptr, *optr; struct l2tp_session *session; struct l2tp_tunnel *tunnel = NULL; |
8f7dc9ae4 l2tp: don't use l... |
114 |
struct iphdr *iph; |
0d76751fa l2tp: Add L2TPv3 ... |
115 |
|
0d76751fa l2tp: Add L2TPv3 ... |
116 117 |
if (!pskb_may_pull(skb, 4)) goto discard; |
5745b8232 ipv4: l2tp: fix a... |
118 |
/* Point to L2TP header */ |
95075150d l2tp: avoid multi... |
119 120 |
optr = skb->data; ptr = skb->data; |
b71a61ccf l2tp: cleanup whi... |
121 |
session_id = ntohl(*((__be32 *)ptr)); |
0d76751fa l2tp: Add L2TPv3 ... |
122 123 124 125 126 127 128 129 130 131 132 133 |
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. */ |
01e28b921 l2tp: split l2tp_... |
134 |
session = l2tp_session_get(net, session_id); |
61b9a0477 l2tp: fix race in... |
135 |
if (!session) |
0d76751fa l2tp: Add L2TPv3 ... |
136 137 138 |
goto discard; tunnel = session->tunnel; |
61b9a0477 l2tp: fix race in... |
139 140 |
if (!tunnel) goto discard_sess; |
0d76751fa l2tp: Add L2TPv3 ... |
141 |
|
4522a70db l2tp: fix reading... |
142 143 |
if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) goto discard_sess; |
2b139e6b1 l2tp: remove ->re... |
144 |
l2tp_recv_common(session, skb, ptr, optr, 0, skb->len); |
61b9a0477 l2tp: fix race in... |
145 |
l2tp_session_dec_refcount(session); |
0d76751fa l2tp: Add L2TPv3 ... |
146 147 148 149 150 151 152 153 154 155 |
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; |
b71a61ccf l2tp: cleanup whi... |
156 |
tunnel_id = ntohl(*(__be32 *)&skb->data[4]); |
8f7dc9ae4 l2tp: don't use l... |
157 158 159 160 161 162 |
iph = (struct iphdr *)skb_network_header(skb); read_lock_bh(&l2tp_ip_lock); sk = __l2tp_ip_bind_lookup(net, iph->daddr, iph->saddr, inet_iif(skb), tunnel_id); if (!sk) { |
0d76751fa l2tp: Add L2TPv3 ... |
163 |
read_unlock_bh(&l2tp_ip_lock); |
8f7dc9ae4 l2tp: don't use l... |
164 |
goto discard; |
0d76751fa l2tp: Add L2TPv3 ... |
165 |
} |
8f7dc9ae4 l2tp: don't use l... |
166 167 |
sock_hold(sk); read_unlock_bh(&l2tp_ip_lock); |
0d76751fa l2tp: Add L2TPv3 ... |
168 |
|
0d76751fa l2tp: Add L2TPv3 ... |
169 170 |
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_put; |
895b5c9f2 netfilter: drop b... |
171 |
nf_reset_ct(skb); |
0d76751fa l2tp: Add L2TPv3 ... |
172 173 |
return sk_receive_skb(sk, skb, 1); |
61b9a0477 l2tp: fix race in... |
174 |
discard_sess: |
61b9a0477 l2tp: fix race in... |
175 176 |
l2tp_session_dec_refcount(session); goto discard; |
0d76751fa l2tp: Add L2TPv3 ... |
177 178 179 180 181 182 183 |
discard_put: sock_put(sk); discard: kfree_skb(skb); return 0; } |
02c71b144 l2tp: do not use ... |
184 |
static int l2tp_ip_hash(struct sock *sk) |
0d76751fa l2tp: Add L2TPv3 ... |
185 |
{ |
02c71b144 l2tp: do not use ... |
186 187 188 189 190 191 192 |
if (sk_unhashed(sk)) { write_lock_bh(&l2tp_ip_lock); sk_add_node(sk, &l2tp_ip_table); write_unlock_bh(&l2tp_ip_lock); } return 0; } |
0d76751fa l2tp: Add L2TPv3 ... |
193 |
|
02c71b144 l2tp: do not use ... |
194 195 196 197 |
static void l2tp_ip_unhash(struct sock *sk) { if (sk_unhashed(sk)) return; |
0d76751fa l2tp: Add L2TPv3 ... |
198 |
write_lock_bh(&l2tp_ip_lock); |
02c71b144 l2tp: do not use ... |
199 |
sk_del_node_init(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
200 |
write_unlock_bh(&l2tp_ip_lock); |
02c71b144 l2tp: do not use ... |
201 202 203 204 205 206 |
} static int l2tp_ip_open(struct sock *sk) { /* Prevent autobind. We don't have ports. */ inet_sk(sk)->inet_num = IPPROTO_L2TP; |
0d76751fa l2tp: Add L2TPv3 ... |
207 |
|
02c71b144 l2tp: do not use ... |
208 |
l2tp_ip_hash(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
209 210 211 212 213 214 215 |
return 0; } static void l2tp_ip_close(struct sock *sk, long timeout) { write_lock_bh(&l2tp_ip_lock); hlist_del_init(&sk->sk_bind_node); |
d1f224ae1 l2tp: fix refcoun... |
216 |
sk_del_node_init(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
217 218 219 220 221 222 |
write_unlock_bh(&l2tp_ip_lock); sk_common_release(sk); } static void l2tp_ip_destroy_sock(struct sock *sk) { |
45faeff11 l2tp: make magic ... |
223 |
struct l2tp_tunnel *tunnel = l2tp_sk_to_tunnel(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
224 225 226 227 |
struct sk_buff *skb; while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) kfree_skb(skb); |
d00fa9adc l2tp: fix races w... |
228 229 |
if (tunnel) l2tp_tunnel_delete(tunnel); |
0d76751fa l2tp: Add L2TPv3 ... |
230 231 232 233 234 |
} static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct inet_sock *inet = inet_sk(sk); |
b71a61ccf l2tp: cleanup whi... |
235 |
struct sockaddr_l2tpip *addr = (struct sockaddr_l2tpip *)uaddr; |
9d6ddb199 l2tp: Make ipv4 p... |
236 |
struct net *net = sock_net(sk); |
c51ce4973 l2tp: fix oops in... |
237 |
int ret; |
0d76751fa l2tp: Add L2TPv3 ... |
238 |
int chk_addr_ret; |
c51ce4973 l2tp: fix oops in... |
239 240 241 242 |
if (addr_len < sizeof(struct sockaddr_l2tpip)) return -EINVAL; if (addr->l2tp_family != AF_INET) return -EINVAL; |
0d76751fa l2tp: Add L2TPv3 ... |
243 |
lock_sock(sk); |
d5e3a1909 l2tp: fix racy so... |
244 245 |
ret = -EINVAL; |
32c231164 l2tp: fix racy SO... |
246 247 |
if (!sock_flag(sk, SOCK_ZAPPED)) goto out; |
8cf2f7045 l2tp: remove redu... |
248 |
if (sk->sk_state != TCP_CLOSE) |
0d76751fa l2tp: Add L2TPv3 ... |
249 |
goto out; |
9d6ddb199 l2tp: Make ipv4 p... |
250 |
chk_addr_ret = inet_addr_type(net, addr->l2tp_addr.s_addr); |
0d76751fa l2tp: Add L2TPv3 ... |
251 252 253 254 |
ret = -EADDRNOTAVAIL; if (addr->l2tp_addr.s_addr && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) goto out; |
95075150d l2tp: avoid multi... |
255 256 257 258 |
if (addr->l2tp_addr.s_addr) { inet->inet_rcv_saddr = addr->l2tp_addr.s_addr; inet->inet_saddr = addr->l2tp_addr.s_addr; } |
0d76751fa l2tp: Add L2TPv3 ... |
259 260 |
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) inet->inet_saddr = 0; /* Use device */ |
0d76751fa l2tp: Add L2TPv3 ... |
261 |
|
d5e3a1909 l2tp: fix racy so... |
262 |
write_lock_bh(&l2tp_ip_lock); |
a9b2dff80 l2tp: take remote... |
263 |
if (__l2tp_ip_bind_lookup(net, addr->l2tp_addr.s_addr, 0, |
d5e3a1909 l2tp: fix racy so... |
264 265 266 267 268 269 270 |
sk->sk_bound_dev_if, addr->l2tp_conn_id)) { write_unlock_bh(&l2tp_ip_lock); ret = -EADDRINUSE; goto out; } sk_dst_reset(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
271 |
l2tp_ip_sk(sk)->conn_id = addr->l2tp_conn_id; |
0d76751fa l2tp: Add L2TPv3 ... |
272 273 274 |
sk_add_bind_node(sk, &l2tp_ip_bind_table); sk_del_node_init(sk); write_unlock_bh(&l2tp_ip_lock); |
d5e3a1909 l2tp: fix racy so... |
275 |
|
0d76751fa l2tp: Add L2TPv3 ... |
276 |
ret = 0; |
c51ce4973 l2tp: fix oops in... |
277 |
sock_reset_flag(sk, SOCK_ZAPPED); |
0d76751fa l2tp: Add L2TPv3 ... |
278 279 280 281 |
out: release_sock(sk); return ret; |
0d76751fa l2tp: Add L2TPv3 ... |
282 283 284 285 |
} static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { |
b71a61ccf l2tp: cleanup whi... |
286 |
struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *)uaddr; |
de3c7a182 l2tp: Use ip4_dat... |
287 |
int rc; |
0d76751fa l2tp: Add L2TPv3 ... |
288 |
|
0d76751fa l2tp: Add L2TPv3 ... |
289 |
if (addr_len < sizeof(*lsa)) |
de3c7a182 l2tp: Use ip4_dat... |
290 |
return -EINVAL; |
2f16270f4 l2tp: Fix locking... |
291 |
|
0d76751fa l2tp: Add L2TPv3 ... |
292 |
if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) |
de3c7a182 l2tp: Use ip4_dat... |
293 |
return -EINVAL; |
0d76751fa l2tp: Add L2TPv3 ... |
294 |
|
de3c7a182 l2tp: Use ip4_dat... |
295 |
lock_sock(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
296 |
|
0382a25af l2tp: lock socket... |
297 298 299 300 301 302 303 304 305 |
/* Must bind first - autobinding does not work */ if (sock_flag(sk, SOCK_ZAPPED)) { rc = -EINVAL; goto out_sk; } rc = __ip4_datagram_connect(sk, uaddr, addr_len); if (rc < 0) goto out_sk; |
0d76751fa l2tp: Add L2TPv3 ... |
306 |
l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; |
0d76751fa l2tp: Add L2TPv3 ... |
307 308 309 310 |
write_lock_bh(&l2tp_ip_lock); hlist_del_init(&sk->sk_bind_node); sk_add_bind_node(sk, &l2tp_ip_bind_table); write_unlock_bh(&l2tp_ip_lock); |
0382a25af l2tp: lock socket... |
311 |
out_sk: |
2f16270f4 l2tp: Fix locking... |
312 |
release_sock(sk); |
0382a25af l2tp: lock socket... |
313 |
|
0d76751fa l2tp: Add L2TPv3 ... |
314 315 |
return rc; } |
c51ce4973 l2tp: fix oops in... |
316 317 318 319 |
static int l2tp_ip_disconnect(struct sock *sk, int flags) { if (sock_flag(sk, SOCK_ZAPPED)) return 0; |
286c72dea udp: must lock th... |
320 |
return __udp_disconnect(sk, flags); |
c51ce4973 l2tp: fix oops in... |
321 |
} |
0d76751fa l2tp: Add L2TPv3 ... |
322 |
static int l2tp_ip_getname(struct socket *sock, struct sockaddr *uaddr, |
9b2c45d47 net: make getname... |
323 |
int peer) |
0d76751fa l2tp: Add L2TPv3 ... |
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
{ struct sock *sk = sock->sk; struct inet_sock *inet = inet_sk(sk); struct l2tp_ip_sock *lsk = l2tp_ip_sk(sk); struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *)uaddr; memset(lsa, 0, sizeof(*lsa)); lsa->l2tp_family = AF_INET; if (peer) { if (!inet->inet_dport) return -ENOTCONN; lsa->l2tp_conn_id = lsk->peer_conn_id; lsa->l2tp_addr.s_addr = inet->inet_daddr; } else { __be32 addr = inet->inet_rcv_saddr; |
b71a61ccf l2tp: cleanup whi... |
339 |
|
0d76751fa l2tp: Add L2TPv3 ... |
340 341 342 343 344 |
if (!addr) addr = inet->inet_saddr; lsa->l2tp_conn_id = lsk->conn_id; lsa->l2tp_addr.s_addr = addr; } |
9b2c45d47 net: make getname... |
345 |
return sizeof(*lsa); |
0d76751fa l2tp: Add L2TPv3 ... |
346 347 348 349 350 |
} static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb) { int rc; |
0d76751fa l2tp: Add L2TPv3 ... |
351 352 353 354 355 356 357 358 |
/* 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: |
9d6ddb199 l2tp: Make ipv4 p... |
359 |
IP_INC_STATS(sock_net(sk), IPSTATS_MIB_INDISCARDS); |
0d76751fa l2tp: Add L2TPv3 ... |
360 |
kfree_skb(skb); |
51fb60eb1 l2tp: avoid use-a... |
361 |
return 0; |
0d76751fa l2tp: Add L2TPv3 ... |
362 363 364 365 366 |
} /* Userspace will call sendmsg() on the tunnel socket to send L2TP * control frames. */ |
1b7841404 net: Remove iocb ... |
367 |
static int l2tp_ip_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) |
0d76751fa l2tp: Add L2TPv3 ... |
368 369 370 |
{ struct sk_buff *skb; int rc; |
0d76751fa l2tp: Add L2TPv3 ... |
371 |
struct inet_sock *inet = inet_sk(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
372 |
struct rtable *rt = NULL; |
fdbb0f076 l2tp: Use cork fl... |
373 |
struct flowi4 *fl4; |
0d76751fa l2tp: Add L2TPv3 ... |
374 375 |
int connected = 0; __be32 daddr; |
2f16270f4 l2tp: Fix locking... |
376 377 378 |
lock_sock(sk); rc = -ENOTCONN; |
0d76751fa l2tp: Add L2TPv3 ... |
379 |
if (sock_flag(sk, SOCK_DEAD)) |
2f16270f4 l2tp: Fix locking... |
380 |
goto out; |
0d76751fa l2tp: Add L2TPv3 ... |
381 382 383 |
/* Get and verify the address. */ if (msg->msg_name) { |
342dfc306 net: add build-ti... |
384 |
DECLARE_SOCKADDR(struct sockaddr_l2tpip *, lip, msg->msg_name); |
b71a61ccf l2tp: cleanup whi... |
385 |
|
2f16270f4 l2tp: Fix locking... |
386 |
rc = -EINVAL; |
0d76751fa l2tp: Add L2TPv3 ... |
387 |
if (msg->msg_namelen < sizeof(*lip)) |
2f16270f4 l2tp: Fix locking... |
388 |
goto out; |
0d76751fa l2tp: Add L2TPv3 ... |
389 390 |
if (lip->l2tp_family != AF_INET) { |
2f16270f4 l2tp: Fix locking... |
391 |
rc = -EAFNOSUPPORT; |
0d76751fa l2tp: Add L2TPv3 ... |
392 |
if (lip->l2tp_family != AF_UNSPEC) |
2f16270f4 l2tp: Fix locking... |
393 |
goto out; |
0d76751fa l2tp: Add L2TPv3 ... |
394 395 396 397 |
} daddr = lip->l2tp_addr.s_addr; } else { |
84768edbb net: l2tp: unlock... |
398 |
rc = -EDESTADDRREQ; |
0d76751fa l2tp: Add L2TPv3 ... |
399 |
if (sk->sk_state != TCP_ESTABLISHED) |
84768edbb net: l2tp: unlock... |
400 |
goto out; |
0d76751fa l2tp: Add L2TPv3 ... |
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
daddr = inet->inet_daddr; connected = 1; } /* Allocate a socket buffer */ rc = -ENOMEM; skb = sock_wmalloc(sk, 2 + NET_SKB_PAD + sizeof(struct iphdr) + 4 + len, 0, GFP_KERNEL); if (!skb) goto error; /* Reserve space for headers, putting IP header on 4-byte boundary. */ skb_reserve(skb, 2 + NET_SKB_PAD); skb_reset_network_header(skb); skb_reserve(skb, sizeof(struct iphdr)); skb_reset_transport_header(skb); /* Insert 0 session_id */ |
b71a61ccf l2tp: cleanup whi... |
420 |
*((__be32 *)skb_put(skb, 4)) = 0; |
0d76751fa l2tp: Add L2TPv3 ... |
421 422 |
/* Copy user data into skb */ |
6ce8e9ce5 new helper: memcp... |
423 |
rc = memcpy_from_msg(skb_put(skb, len), msg, len); |
0d76751fa l2tp: Add L2TPv3 ... |
424 425 426 427 |
if (rc < 0) { kfree_skb(skb); goto error; } |
fdbb0f076 l2tp: Use cork fl... |
428 |
fl4 = &inet->cork.fl.u.ip4; |
0d76751fa l2tp: Add L2TPv3 ... |
429 |
if (connected) |
b71a61ccf l2tp: cleanup whi... |
430 |
rt = (struct rtable *)__sk_dst_check(sk, 0); |
0d76751fa l2tp: Add L2TPv3 ... |
431 |
|
081b1b1bb l2tp: fix l2tp_ip... |
432 |
rcu_read_lock(); |
0febc7b3c l2tp: cleanup com... |
433 |
if (!rt) { |
081b1b1bb l2tp: fix l2tp_ip... |
434 |
const struct ip_options_rcu *inet_opt; |
f6d8bd051 inet: add RCU pro... |
435 |
|
778865a55 l2tp: Fix inet_op... |
436 |
inet_opt = rcu_dereference(inet->inet_opt); |
f6d8bd051 inet: add RCU pro... |
437 |
|
0d76751fa l2tp: Add L2TPv3 ... |
438 |
/* Use correct destination address if we have options. */ |
f6d8bd051 inet: add RCU pro... |
439 440 |
if (inet_opt && inet_opt->opt.srr) daddr = inet_opt->opt.faddr; |
0d76751fa l2tp: Add L2TPv3 ... |
441 |
|
78fbfd8a6 ipv4: Create and ... |
442 443 444 445 |
/* If this fails, retransmit mechanism of transport layer will * keep trying until route appears or the connection times * itself out. */ |
fdbb0f076 l2tp: Use cork fl... |
446 |
rt = ip_route_output_ports(sock_net(sk), fl4, sk, |
78fbfd8a6 ipv4: Create and ... |
447 448 449 450 451 452 |
daddr, inet->inet_saddr, inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); if (IS_ERR(rt)) goto no_route; |
4399a4df9 l2tp: fix a race ... |
453 |
if (connected) { |
081b1b1bb l2tp: fix l2tp_ip... |
454 |
sk_setup_caps(sk, &rt->dst); |
4399a4df9 l2tp: fix a race ... |
455 456 457 458 |
} else { skb_dst_set(skb, &rt->dst); goto xmit; } |
0d76751fa l2tp: Add L2TPv3 ... |
459 |
} |
081b1b1bb l2tp: fix l2tp_ip... |
460 461 462 463 464 |
/* We dont need to clone dst here, it is guaranteed to not disappear. * __dev_xmit_skb() might force a refcount if needed. */ skb_dst_set_noref(skb, &rt->dst); |
0d76751fa l2tp: Add L2TPv3 ... |
465 |
|
4399a4df9 l2tp: fix a race ... |
466 |
xmit: |
0d76751fa l2tp: Add L2TPv3 ... |
467 |
/* Queue the packet to IP for output */ |
b0270e910 ipv4: add a sock ... |
468 |
rc = ip_queue_xmit(sk, skb, &inet->cork.fl); |
081b1b1bb l2tp: fix l2tp_ip... |
469 |
rcu_read_unlock(); |
0d76751fa l2tp: Add L2TPv3 ... |
470 471 |
error: |
c8657fd50 l2tp: remove unus... |
472 |
if (rc >= 0) |
0d76751fa l2tp: Add L2TPv3 ... |
473 |
rc = len; |
0d76751fa l2tp: Add L2TPv3 ... |
474 |
|
2f16270f4 l2tp: Fix locking... |
475 476 |
out: release_sock(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
477 478 479 |
return rc; no_route: |
081b1b1bb l2tp: fix l2tp_ip... |
480 |
rcu_read_unlock(); |
0d76751fa l2tp: Add L2TPv3 ... |
481 482 |
IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); kfree_skb(skb); |
2f16270f4 l2tp: Fix locking... |
483 484 |
rc = -EHOSTUNREACH; goto out; |
0d76751fa l2tp: Add L2TPv3 ... |
485 |
} |
1b7841404 net: Remove iocb ... |
486 |
static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr *msg, |
0d76751fa l2tp: Add L2TPv3 ... |
487 488 489 |
size_t len, int noblock, int flags, int *addr_len) { struct inet_sock *inet = inet_sk(sk); |
0d76751fa l2tp: Add L2TPv3 ... |
490 491 |
size_t copied = 0; int err = -EOPNOTSUPP; |
342dfc306 net: add build-ti... |
492 |
DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); |
0d76751fa l2tp: Add L2TPv3 ... |
493 494 495 496 |
struct sk_buff *skb; if (flags & MSG_OOB) goto out; |
0d76751fa l2tp: Add L2TPv3 ... |
497 498 499 500 501 502 503 504 505 |
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 net: Add and use ... |
506 |
err = skb_copy_datagram_msg(skb, 0, msg, copied); |
0d76751fa l2tp: Add L2TPv3 ... |
507 508 509 510 511 512 513 514 515 516 517 |
if (err) goto done; sock_recv_timestamp(msg, sk, skb); /* Copy the address. */ if (sin) { sin->sin_family = AF_INET; sin->sin_addr.s_addr = ip_hdr(skb)->saddr; sin->sin_port = 0; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); |
bceaa9024 inet: prevent lea... |
518 |
*addr_len = sizeof(*sin); |
0d76751fa l2tp: Add L2TPv3 ... |
519 520 521 522 523 524 525 526 |
} if (inet->cmsg_flags) ip_cmsg_recv(msg, skb); if (flags & MSG_TRUNC) copied = skb->len; done: skb_free_datagram(sk, skb); out: |
c8657fd50 l2tp: remove unus... |
527 |
return err ? err : copied; |
0d76751fa l2tp: Add L2TPv3 ... |
528 |
} |
72fb96e7b l2tp: do not use ... |
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 |
int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg) { struct sk_buff *skb; int amount; switch (cmd) { case SIOCOUTQ: amount = sk_wmem_alloc_get(sk); break; case SIOCINQ: spin_lock_bh(&sk->sk_receive_queue.lock); skb = skb_peek(&sk->sk_receive_queue); amount = skb ? skb->len : 0; spin_unlock_bh(&sk->sk_receive_queue.lock); break; default: return -ENOIOCTLCMD; } return put_user(amount, (int __user *)arg); } |
ca7885dbc l2tp: tweak expor... |
551 |
EXPORT_SYMBOL_GPL(l2tp_ioctl); |
72fb96e7b l2tp: do not use ... |
552 |
|
fc130840d l2tp: make local ... |
553 |
static struct proto l2tp_ip_prot = { |
0d76751fa l2tp: Add L2TPv3 ... |
554 555 556 557 558 559 |
.name = "L2TP/IP", .owner = THIS_MODULE, .init = l2tp_ip_open, .close = l2tp_ip_close, .bind = l2tp_ip_bind, .connect = l2tp_ip_connect, |
c51ce4973 l2tp: fix oops in... |
560 |
.disconnect = l2tp_ip_disconnect, |
72fb96e7b l2tp: do not use ... |
561 |
.ioctl = l2tp_ioctl, |
0d76751fa l2tp: Add L2TPv3 ... |
562 563 564 565 566 567 |
.destroy = l2tp_ip_destroy_sock, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, .sendmsg = l2tp_ip_sendmsg, .recvmsg = l2tp_ip_recvmsg, .backlog_rcv = l2tp_ip_backlog_recv, |
02c71b144 l2tp: do not use ... |
568 569 |
.hash = l2tp_ip_hash, .unhash = l2tp_ip_unhash, |
0d76751fa l2tp: Add L2TPv3 ... |
570 |
.obj_size = sizeof(struct l2tp_ip_sock), |
0d76751fa l2tp: Add L2TPv3 ... |
571 572 573 574 575 576 577 578 579 580 581 |
}; static const struct proto_ops l2tp_ip_ops = { .family = PF_INET, .owner = THIS_MODULE, .release = inet_release, .bind = inet_bind, .connect = inet_dgram_connect, .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = l2tp_ip_getname, |
a11e1d432 Revert changes to... |
582 |
.poll = datagram_poll, |
0d76751fa l2tp: Add L2TPv3 ... |
583 |
.ioctl = inet_ioctl, |
c7cbdbf29 net: rework SIOCG... |
584 |
.gettstamp = sock_gettstamp, |
0d76751fa l2tp: Add L2TPv3 ... |
585 586 587 588 589 590 591 592 |
.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, |
0d76751fa l2tp: Add L2TPv3 ... |
593 594 595 596 597 598 599 |
}; static struct inet_protosw l2tp_ip_protosw = { .type = SOCK_DGRAM, .protocol = IPPROTO_L2TP, .prot = &l2tp_ip_prot, .ops = &l2tp_ip_ops, |
0d76751fa l2tp: Add L2TPv3 ... |
600 601 602 603 |
}; static struct net_protocol l2tp_ip_protocol __read_mostly = { .handler = l2tp_ip_recv, |
9d6ddb199 l2tp: Make ipv4 p... |
604 |
.netns_ok = 1, |
0d76751fa l2tp: Add L2TPv3 ... |
605 606 607 608 609 |
}; static int __init l2tp_ip_init(void) { int err; |
a4ca44fa5 net: l2tp: Standa... |
610 611 |
pr_info("L2TP IP encapsulation support (L2TPv3) "); |
0d76751fa l2tp: Add L2TPv3 ... |
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 |
err = proto_register(&l2tp_ip_prot, 1); if (err != 0) goto out; err = inet_add_protocol(&l2tp_ip_protocol, IPPROTO_L2TP); if (err) goto out1; inet_register_protosw(&l2tp_ip_protosw); return 0; out1: proto_unregister(&l2tp_ip_prot); out: return err; } static void __exit l2tp_ip_exit(void) { inet_unregister_protosw(&l2tp_ip_protosw); inet_del_protocol(&l2tp_ip_protocol, IPPROTO_L2TP); proto_unregister(&l2tp_ip_prot); } module_init(l2tp_ip_init); module_exit(l2tp_ip_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); MODULE_DESCRIPTION("L2TP over IP"); MODULE_VERSION("1.0"); |
e8d34a884 l2tp: Fix modalia... |
644 |
|
e9c549998 Revert wrong fixe... |
645 |
/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like |
e8d34a884 l2tp: Fix modalia... |
646 647 648 |
* enums */ MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP); |
163c2e252 l2tp: auto load I... |
649 |
MODULE_ALIAS_NET_PF_PROTO(PF_INET, IPPROTO_L2TP); |