| .. | .. |
|---|
| 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 | |
|---|