.. | .. |
---|
1 | | -/* |
---|
2 | | - * L2TPv3 IP encapsulation support for IPv6 |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
| 2 | +/* L2TPv3 IP encapsulation support for IPv6 |
---|
3 | 3 | * |
---|
4 | 4 | * Copyright (c) 2012 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 | 5 | */ |
---|
11 | 6 | |
---|
12 | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
42 | 37 | u32 peer_conn_id; |
---|
43 | 38 | |
---|
44 | 39 | /* ipv6_pinfo has to be the last member of l2tp_ip6_sock, see |
---|
45 | | - inet6_sk_generic */ |
---|
| 40 | + * inet6_sk_generic |
---|
| 41 | + */ |
---|
46 | 42 | struct ipv6_pinfo inet6; |
---|
47 | 43 | }; |
---|
48 | 44 | |
---|
.. | .. |
---|
135 | 131 | struct l2tp_session *session; |
---|
136 | 132 | struct l2tp_tunnel *tunnel = NULL; |
---|
137 | 133 | struct ipv6hdr *iph; |
---|
138 | | - int length; |
---|
139 | 134 | |
---|
140 | 135 | if (!pskb_may_pull(skb, 4)) |
---|
141 | 136 | goto discard; |
---|
142 | 137 | |
---|
143 | 138 | /* Point to L2TP header */ |
---|
144 | | - optr = ptr = skb->data; |
---|
145 | | - session_id = ntohl(*((__be32 *) ptr)); |
---|
| 139 | + optr = skb->data; |
---|
| 140 | + ptr = skb->data; |
---|
| 141 | + session_id = ntohl(*((__be32 *)ptr)); |
---|
146 | 142 | ptr += 4; |
---|
147 | 143 | |
---|
148 | 144 | /* RFC3931: L2TP/IP packets have the first 4 bytes containing |
---|
.. | .. |
---|
163 | 159 | if (!tunnel) |
---|
164 | 160 | goto discard_sess; |
---|
165 | 161 | |
---|
166 | | - /* Trace packet contents, if enabled */ |
---|
167 | | - if (tunnel->debug & L2TP_MSG_DATA) { |
---|
168 | | - length = min(32u, skb->len); |
---|
169 | | - if (!pskb_may_pull(skb, length)) |
---|
170 | | - goto discard_sess; |
---|
171 | | - |
---|
172 | | - /* Point to L2TP header */ |
---|
173 | | - optr = ptr = skb->data; |
---|
174 | | - ptr += 4; |
---|
175 | | - pr_debug("%s: ip recv\n", tunnel->name); |
---|
176 | | - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); |
---|
177 | | - } |
---|
178 | | - |
---|
179 | 162 | if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) |
---|
180 | 163 | goto discard_sess; |
---|
181 | 164 | |
---|
.. | .. |
---|
192 | 175 | if ((skb->data[0] & 0xc0) != 0xc0) |
---|
193 | 176 | goto discard; |
---|
194 | 177 | |
---|
195 | | - tunnel_id = ntohl(*(__be32 *) &skb->data[4]); |
---|
| 178 | + tunnel_id = ntohl(*(__be32 *)&skb->data[4]); |
---|
196 | 179 | iph = ipv6_hdr(skb); |
---|
197 | 180 | |
---|
198 | 181 | read_lock_bh(&l2tp_ip6_lock); |
---|
.. | .. |
---|
208 | 191 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
---|
209 | 192 | goto discard_put; |
---|
210 | 193 | |
---|
211 | | - nf_reset(skb); |
---|
| 194 | + nf_reset_ct(skb); |
---|
212 | 195 | |
---|
213 | 196 | return sk_receive_skb(sk, skb, 1); |
---|
214 | 197 | |
---|
.. | .. |
---|
264 | 247 | |
---|
265 | 248 | static void l2tp_ip6_destroy_sock(struct sock *sk) |
---|
266 | 249 | { |
---|
267 | | - struct l2tp_tunnel *tunnel = sk->sk_user_data; |
---|
| 250 | + struct l2tp_tunnel *tunnel = l2tp_sk_to_tunnel(sk); |
---|
268 | 251 | |
---|
269 | 252 | lock_sock(sk); |
---|
270 | 253 | ip6_flush_pending_frames(sk); |
---|
.. | .. |
---|
272 | 255 | |
---|
273 | 256 | if (tunnel) |
---|
274 | 257 | l2tp_tunnel_delete(tunnel); |
---|
275 | | - |
---|
276 | | - inet6_destroy_sock(sk); |
---|
277 | 258 | } |
---|
278 | 259 | |
---|
279 | 260 | static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
---|
280 | 261 | { |
---|
281 | 262 | struct inet_sock *inet = inet_sk(sk); |
---|
282 | 263 | struct ipv6_pinfo *np = inet6_sk(sk); |
---|
283 | | - struct sockaddr_l2tpip6 *addr = (struct sockaddr_l2tpip6 *) uaddr; |
---|
| 264 | + struct sockaddr_l2tpip6 *addr = (struct sockaddr_l2tpip6 *)uaddr; |
---|
284 | 265 | struct net *net = sock_net(sk); |
---|
285 | 266 | __be32 v4addr = 0; |
---|
286 | 267 | int bound_dev_if; |
---|
.. | .. |
---|
379 | 360 | static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr, |
---|
380 | 361 | int addr_len) |
---|
381 | 362 | { |
---|
382 | | - struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *) uaddr; |
---|
383 | | - struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; |
---|
| 363 | + struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *)uaddr; |
---|
| 364 | + struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr; |
---|
384 | 365 | struct in6_addr *daddr; |
---|
385 | 366 | int addr_type; |
---|
386 | 367 | int rc; |
---|
.. | .. |
---|
490 | 471 | int err = 0; |
---|
491 | 472 | |
---|
492 | 473 | skb = skb_peek(&sk->sk_write_queue); |
---|
493 | | - if (skb == NULL) |
---|
| 474 | + if (!skb) |
---|
494 | 475 | goto out; |
---|
495 | 476 | |
---|
496 | 477 | transhdr = (__be32 *)skb_transport_header(skb); |
---|
.. | .. |
---|
519 | 500 | struct ipcm6_cookie ipc6; |
---|
520 | 501 | int addr_len = msg->msg_namelen; |
---|
521 | 502 | int transhdrlen = 4; /* zero session-id */ |
---|
522 | | - int ulen = len + transhdrlen; |
---|
| 503 | + int ulen; |
---|
523 | 504 | int err; |
---|
524 | 505 | |
---|
525 | 506 | /* Rough check on arithmetic overflow, |
---|
526 | | - better check is made in ip6_append_data(). |
---|
| 507 | + * better check is made in ip6_append_data(). |
---|
527 | 508 | */ |
---|
528 | | - if (len > INT_MAX) |
---|
| 509 | + if (len > INT_MAX - transhdrlen) |
---|
529 | 510 | return -EMSGSIZE; |
---|
530 | 511 | |
---|
531 | 512 | /* Mirror BSD error message compatibility */ |
---|
532 | 513 | if (msg->msg_flags & MSG_OOB) |
---|
533 | 514 | return -EOPNOTSUPP; |
---|
534 | 515 | |
---|
535 | | - /* |
---|
536 | | - * Get and verify the address. |
---|
537 | | - */ |
---|
| 516 | + /* Get and verify the address */ |
---|
538 | 517 | memset(&fl6, 0, sizeof(fl6)); |
---|
539 | 518 | |
---|
540 | 519 | fl6.flowi6_mark = sk->sk_mark; |
---|
.. | .. |
---|
552 | 531 | daddr = &lsa->l2tp_addr; |
---|
553 | 532 | if (np->sndflow) { |
---|
554 | 533 | fl6.flowlabel = lsa->l2tp_flowinfo & IPV6_FLOWINFO_MASK; |
---|
555 | | - if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
---|
| 534 | + if (fl6.flowlabel & IPV6_FLOWLABEL_MASK) { |
---|
556 | 535 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
---|
557 | | - if (flowlabel == NULL) |
---|
| 536 | + if (IS_ERR(flowlabel)) |
---|
558 | 537 | return -EINVAL; |
---|
559 | 538 | } |
---|
560 | 539 | } |
---|
561 | 540 | |
---|
562 | | - /* |
---|
563 | | - * Otherwise it will be difficult to maintain |
---|
| 541 | + /* Otherwise it will be difficult to maintain |
---|
564 | 542 | * sk->sk_dst_cache. |
---|
565 | 543 | */ |
---|
566 | 544 | if (sk->sk_state == TCP_ESTABLISHED && |
---|
.. | .. |
---|
595 | 573 | } |
---|
596 | 574 | if ((fl6.flowlabel & IPV6_FLOWLABEL_MASK) && !flowlabel) { |
---|
597 | 575 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
---|
598 | | - if (flowlabel == NULL) |
---|
| 576 | + if (IS_ERR(flowlabel)) |
---|
599 | 577 | return -EINVAL; |
---|
600 | 578 | } |
---|
601 | | - if (!(opt->opt_nflen|opt->opt_flen)) |
---|
| 579 | + if (!(opt->opt_nflen | opt->opt_flen)) |
---|
602 | 580 | opt = NULL; |
---|
603 | 581 | } |
---|
604 | 582 | |
---|
.. | .. |
---|
626 | 604 | else if (!fl6.flowi6_oif) |
---|
627 | 605 | fl6.flowi6_oif = np->ucast_oif; |
---|
628 | 606 | |
---|
629 | | - security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
---|
| 607 | + security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6)); |
---|
630 | 608 | |
---|
631 | 609 | if (ipc6.tclass < 0) |
---|
632 | 610 | ipc6.tclass = np->tclass; |
---|
.. | .. |
---|
650 | 628 | |
---|
651 | 629 | back_from_confirm: |
---|
652 | 630 | lock_sock(sk); |
---|
| 631 | + ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0; |
---|
653 | 632 | err = ip6_append_data(sk, ip_generic_getfrag, msg, |
---|
654 | 633 | ulen, transhdrlen, &ipc6, |
---|
655 | 634 | &fl6, (struct rt6_info *)dst, |
---|
.. | .. |
---|
749 | 728 | .hash = l2tp_ip6_hash, |
---|
750 | 729 | .unhash = l2tp_ip6_unhash, |
---|
751 | 730 | .obj_size = sizeof(struct l2tp_ip6_sock), |
---|
752 | | -#ifdef CONFIG_COMPAT |
---|
753 | | - .compat_setsockopt = compat_ipv6_setsockopt, |
---|
754 | | - .compat_getsockopt = compat_ipv6_getsockopt, |
---|
755 | | -#endif |
---|
756 | 731 | }; |
---|
757 | 732 | |
---|
758 | 733 | static const struct proto_ops l2tp_ip6_ops = { |
---|
.. | .. |
---|
766 | 741 | .getname = l2tp_ip6_getname, |
---|
767 | 742 | .poll = datagram_poll, |
---|
768 | 743 | .ioctl = inet6_ioctl, |
---|
| 744 | + .gettstamp = sock_gettstamp, |
---|
769 | 745 | .listen = sock_no_listen, |
---|
770 | 746 | .shutdown = inet_shutdown, |
---|
771 | 747 | .setsockopt = sock_common_setsockopt, |
---|
.. | .. |
---|
775 | 751 | .mmap = sock_no_mmap, |
---|
776 | 752 | .sendpage = sock_no_sendpage, |
---|
777 | 753 | #ifdef CONFIG_COMPAT |
---|
778 | | - .compat_setsockopt = compat_sock_common_setsockopt, |
---|
779 | | - .compat_getsockopt = compat_sock_common_getsockopt, |
---|
| 754 | + .compat_ioctl = inet6_compat_ioctl, |
---|
780 | 755 | #endif |
---|
781 | 756 | }; |
---|
782 | 757 | |
---|