| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * PF_INET6 socket protocol family |
|---|
| 3 | 4 | * Linux INET6 implementation |
|---|
| .. | .. |
|---|
| 11 | 12 | * piggy, Karl Knutson : Socket protocol table |
|---|
| 12 | 13 | * Hideaki YOSHIFUJI : sin6_scope_id support |
|---|
| 13 | 14 | * Arnaldo Melo : check proc_net_create return, cleanups |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is free software; you can redistribute it and/or |
|---|
| 16 | | - * modify it under the terms of the GNU General Public License |
|---|
| 17 | | - * as published by the Free Software Foundation; either version |
|---|
| 18 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 19 | 15 | */ |
|---|
| 20 | 16 | |
|---|
| 21 | 17 | #define pr_fmt(fmt) "IPv6: " fmt |
|---|
| .. | .. |
|---|
| 56 | 52 | #include <net/transp_v6.h> |
|---|
| 57 | 53 | #include <net/ip6_route.h> |
|---|
| 58 | 54 | #include <net/addrconf.h> |
|---|
| 55 | +#include <net/ipv6_stubs.h> |
|---|
| 59 | 56 | #include <net/ndisc.h> |
|---|
| 60 | 57 | #ifdef CONFIG_IPV6_TUNNEL |
|---|
| 61 | 58 | #include <net/ip6_tunnel.h> |
|---|
| 62 | 59 | #endif |
|---|
| 63 | 60 | #include <net/calipso.h> |
|---|
| 64 | 61 | #include <net/seg6.h> |
|---|
| 62 | +#include <net/rpl.h> |
|---|
| 63 | +#include <net/compat.h> |
|---|
| 64 | +#include <net/xfrm.h> |
|---|
| 65 | 65 | |
|---|
| 66 | 66 | #include <linux/uaccess.h> |
|---|
| 67 | 67 | #include <linux/mroute6.h> |
|---|
| .. | .. |
|---|
| 106 | 106 | |
|---|
| 107 | 107 | return (struct ipv6_pinfo *)(((u8 *)sk) + offset); |
|---|
| 108 | 108 | } |
|---|
| 109 | + |
|---|
| 110 | +void inet6_sock_destruct(struct sock *sk) |
|---|
| 111 | +{ |
|---|
| 112 | + inet6_cleanup_sock(sk); |
|---|
| 113 | + inet_sock_destruct(sk); |
|---|
| 114 | +} |
|---|
| 115 | +EXPORT_SYMBOL_GPL(inet6_sock_destruct); |
|---|
| 109 | 116 | |
|---|
| 110 | 117 | static int inet6_create(struct net *net, struct socket *sock, int protocol, |
|---|
| 111 | 118 | int kern) |
|---|
| .. | .. |
|---|
| 199 | 206 | inet->hdrincl = 1; |
|---|
| 200 | 207 | } |
|---|
| 201 | 208 | |
|---|
| 202 | | - sk->sk_destruct = inet_sock_destruct; |
|---|
| 209 | + sk->sk_destruct = inet6_sock_destruct; |
|---|
| 203 | 210 | sk->sk_family = PF_INET6; |
|---|
| 204 | 211 | sk->sk_protocol = protocol; |
|---|
| 205 | 212 | |
|---|
| .. | .. |
|---|
| 209 | 216 | np->hop_limit = -1; |
|---|
| 210 | 217 | np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; |
|---|
| 211 | 218 | np->mc_loop = 1; |
|---|
| 219 | + np->mc_all = 1; |
|---|
| 212 | 220 | np->pmtudisc = IPV6_PMTUDISC_WANT; |
|---|
| 213 | | - np->repflow = net->ipv6.sysctl.flowlabel_reflect; |
|---|
| 221 | + np->repflow = net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ESTABLISHED; |
|---|
| 214 | 222 | sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; |
|---|
| 215 | 223 | |
|---|
| 216 | 224 | /* Init the ipv4 part of the socket since we can have sockets |
|---|
| .. | .. |
|---|
| 224 | 232 | inet->mc_list = NULL; |
|---|
| 225 | 233 | inet->rcv_tos = 0; |
|---|
| 226 | 234 | |
|---|
| 227 | | - if (net->ipv4.sysctl_ip_no_pmtu_disc) |
|---|
| 235 | + if (READ_ONCE(net->ipv4.sysctl_ip_no_pmtu_disc)) |
|---|
| 228 | 236 | inet->pmtudisc = IP_PMTUDISC_DONT; |
|---|
| 229 | 237 | else |
|---|
| 230 | 238 | inet->pmtudisc = IP_PMTUDISC_WANT; |
|---|
| .. | .. |
|---|
| 274 | 282 | } |
|---|
| 275 | 283 | |
|---|
| 276 | 284 | static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, |
|---|
| 277 | | - bool force_bind_address_no_port, bool with_lock) |
|---|
| 285 | + u32 flags) |
|---|
| 278 | 286 | { |
|---|
| 279 | 287 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *)uaddr; |
|---|
| 280 | 288 | struct inet_sock *inet = inet_sk(sk); |
|---|
| .. | .. |
|---|
| 294 | 302 | return -EINVAL; |
|---|
| 295 | 303 | |
|---|
| 296 | 304 | snum = ntohs(addr->sin6_port); |
|---|
| 297 | | - if (snum && snum < inet_prot_sock(net) && |
|---|
| 305 | + if (snum && inet_is_local_unbindable_port(net, snum)) |
|---|
| 306 | + return -EPERM; |
|---|
| 307 | + if (snum && inet_port_requires_bind_service(net, snum) && |
|---|
| 298 | 308 | !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) |
|---|
| 299 | 309 | return -EACCES; |
|---|
| 300 | 310 | |
|---|
| 301 | | - if (with_lock) |
|---|
| 311 | + if (flags & BIND_WITH_LOCK) |
|---|
| 302 | 312 | lock_sock(sk); |
|---|
| 303 | 313 | |
|---|
| 304 | 314 | /* Check these errors (active socket, double bind). */ |
|---|
| .. | .. |
|---|
| 401 | 411 | |
|---|
| 402 | 412 | /* Make sure we are allowed to bind here. */ |
|---|
| 403 | 413 | if (snum || !(inet->bind_address_no_port || |
|---|
| 404 | | - force_bind_address_no_port)) { |
|---|
| 414 | + (flags & BIND_FORCE_ADDRESS_NO_PORT))) { |
|---|
| 405 | 415 | if (sk->sk_prot->get_port(sk, snum)) { |
|---|
| 406 | 416 | sk->sk_ipv6only = saved_ipv6only; |
|---|
| 407 | 417 | inet_reset_saddr(sk); |
|---|
| 408 | 418 | err = -EADDRINUSE; |
|---|
| 409 | 419 | goto out; |
|---|
| 410 | 420 | } |
|---|
| 411 | | - err = BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk); |
|---|
| 412 | | - if (err) { |
|---|
| 413 | | - sk->sk_ipv6only = saved_ipv6only; |
|---|
| 414 | | - inet_reset_saddr(sk); |
|---|
| 415 | | - goto out; |
|---|
| 421 | + if (!(flags & BIND_FROM_BPF)) { |
|---|
| 422 | + err = BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk); |
|---|
| 423 | + if (err) { |
|---|
| 424 | + sk->sk_ipv6only = saved_ipv6only; |
|---|
| 425 | + inet_reset_saddr(sk); |
|---|
| 426 | + goto out; |
|---|
| 427 | + } |
|---|
| 416 | 428 | } |
|---|
| 417 | 429 | } |
|---|
| 418 | 430 | |
|---|
| .. | .. |
|---|
| 424 | 436 | inet->inet_dport = 0; |
|---|
| 425 | 437 | inet->inet_daddr = 0; |
|---|
| 426 | 438 | out: |
|---|
| 427 | | - if (with_lock) |
|---|
| 439 | + if (flags & BIND_WITH_LOCK) |
|---|
| 428 | 440 | release_sock(sk); |
|---|
| 429 | 441 | return err; |
|---|
| 430 | 442 | out_unlock: |
|---|
| .. | .. |
|---|
| 452 | 464 | if (err) |
|---|
| 453 | 465 | return err; |
|---|
| 454 | 466 | |
|---|
| 455 | | - return __inet6_bind(sk, uaddr, addr_len, false, true); |
|---|
| 467 | + return __inet6_bind(sk, uaddr, addr_len, BIND_WITH_LOCK); |
|---|
| 456 | 468 | } |
|---|
| 457 | 469 | EXPORT_SYMBOL(inet6_bind); |
|---|
| 458 | 470 | |
|---|
| .. | .. |
|---|
| 482 | 494 | /* Release rx options */ |
|---|
| 483 | 495 | |
|---|
| 484 | 496 | skb = xchg(&np->pktoptions, NULL); |
|---|
| 485 | | - if (skb) |
|---|
| 486 | | - kfree_skb(skb); |
|---|
| 497 | + kfree_skb(skb); |
|---|
| 487 | 498 | |
|---|
| 488 | 499 | skb = xchg(&np->rxpmtu, NULL); |
|---|
| 489 | | - if (skb) |
|---|
| 490 | | - kfree_skb(skb); |
|---|
| 500 | + kfree_skb(skb); |
|---|
| 491 | 501 | |
|---|
| 492 | 502 | /* Free flowlabels */ |
|---|
| 493 | 503 | fl6_free_socklist(sk); |
|---|
| .. | .. |
|---|
| 502 | 512 | } |
|---|
| 503 | 513 | EXPORT_SYMBOL_GPL(inet6_destroy_sock); |
|---|
| 504 | 514 | |
|---|
| 515 | +void inet6_cleanup_sock(struct sock *sk) |
|---|
| 516 | +{ |
|---|
| 517 | + inet6_destroy_sock(sk); |
|---|
| 518 | +} |
|---|
| 519 | +EXPORT_SYMBOL_GPL(inet6_cleanup_sock); |
|---|
| 520 | + |
|---|
| 505 | 521 | /* |
|---|
| 506 | 522 | * This does both peername and sockname. |
|---|
| 507 | 523 | */ |
|---|
| 508 | | - |
|---|
| 509 | 524 | int inet6_getname(struct socket *sock, struct sockaddr *uaddr, |
|---|
| 510 | | - int peer) |
|---|
| 525 | + int peer) |
|---|
| 511 | 526 | { |
|---|
| 512 | 527 | struct sockaddr_in6 *sin = (struct sockaddr_in6 *)uaddr; |
|---|
| 513 | 528 | struct sock *sk = sock->sk; |
|---|
| .. | .. |
|---|
| 532 | 547 | sin->sin6_addr = np->saddr; |
|---|
| 533 | 548 | else |
|---|
| 534 | 549 | sin->sin6_addr = sk->sk_v6_rcv_saddr; |
|---|
| 535 | | - |
|---|
| 536 | 550 | sin->sin6_port = inet->inet_sport; |
|---|
| 537 | 551 | } |
|---|
| 552 | + if (cgroup_bpf_enabled) |
|---|
| 553 | + BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, |
|---|
| 554 | + peer ? BPF_CGROUP_INET6_GETPEERNAME : |
|---|
| 555 | + BPF_CGROUP_INET6_GETSOCKNAME, |
|---|
| 556 | + NULL); |
|---|
| 538 | 557 | sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr, |
|---|
| 539 | 558 | sk->sk_bound_dev_if); |
|---|
| 540 | 559 | return sizeof(*sin); |
|---|
| .. | .. |
|---|
| 543 | 562 | |
|---|
| 544 | 563 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
|---|
| 545 | 564 | { |
|---|
| 565 | + void __user *argp = (void __user *)arg; |
|---|
| 546 | 566 | struct sock *sk = sock->sk; |
|---|
| 547 | 567 | struct net *net = sock_net(sk); |
|---|
| 548 | 568 | |
|---|
| 549 | 569 | switch (cmd) { |
|---|
| 550 | | - case SIOCGSTAMP: |
|---|
| 551 | | - return sock_get_timestamp(sk, (struct timeval __user *)arg); |
|---|
| 552 | | - |
|---|
| 553 | | - case SIOCGSTAMPNS: |
|---|
| 554 | | - return sock_get_timestampns(sk, (struct timespec __user *)arg); |
|---|
| 555 | | - |
|---|
| 556 | 570 | case SIOCADDRT: |
|---|
| 557 | | - case SIOCDELRT: |
|---|
| 571 | + case SIOCDELRT: { |
|---|
| 572 | + struct in6_rtmsg rtmsg; |
|---|
| 558 | 573 | |
|---|
| 559 | | - return ipv6_route_ioctl(net, cmd, (void __user *)arg); |
|---|
| 560 | | - |
|---|
| 574 | + if (copy_from_user(&rtmsg, argp, sizeof(rtmsg))) |
|---|
| 575 | + return -EFAULT; |
|---|
| 576 | + return ipv6_route_ioctl(net, cmd, &rtmsg); |
|---|
| 577 | + } |
|---|
| 561 | 578 | case SIOCSIFADDR: |
|---|
| 562 | | - return addrconf_add_ifaddr(net, (void __user *) arg); |
|---|
| 579 | + return addrconf_add_ifaddr(net, argp); |
|---|
| 563 | 580 | case SIOCDIFADDR: |
|---|
| 564 | | - return addrconf_del_ifaddr(net, (void __user *) arg); |
|---|
| 581 | + return addrconf_del_ifaddr(net, argp); |
|---|
| 565 | 582 | case SIOCSIFDSTADDR: |
|---|
| 566 | | - return addrconf_set_dstaddr(net, (void __user *) arg); |
|---|
| 583 | + return addrconf_set_dstaddr(net, argp); |
|---|
| 567 | 584 | default: |
|---|
| 568 | 585 | if (!sk->sk_prot->ioctl) |
|---|
| 569 | 586 | return -ENOIOCTLCMD; |
|---|
| .. | .. |
|---|
| 573 | 590 | return 0; |
|---|
| 574 | 591 | } |
|---|
| 575 | 592 | EXPORT_SYMBOL(inet6_ioctl); |
|---|
| 593 | + |
|---|
| 594 | +#ifdef CONFIG_COMPAT |
|---|
| 595 | +struct compat_in6_rtmsg { |
|---|
| 596 | + struct in6_addr rtmsg_dst; |
|---|
| 597 | + struct in6_addr rtmsg_src; |
|---|
| 598 | + struct in6_addr rtmsg_gateway; |
|---|
| 599 | + u32 rtmsg_type; |
|---|
| 600 | + u16 rtmsg_dst_len; |
|---|
| 601 | + u16 rtmsg_src_len; |
|---|
| 602 | + u32 rtmsg_metric; |
|---|
| 603 | + u32 rtmsg_info; |
|---|
| 604 | + u32 rtmsg_flags; |
|---|
| 605 | + s32 rtmsg_ifindex; |
|---|
| 606 | +}; |
|---|
| 607 | + |
|---|
| 608 | +static int inet6_compat_routing_ioctl(struct sock *sk, unsigned int cmd, |
|---|
| 609 | + struct compat_in6_rtmsg __user *ur) |
|---|
| 610 | +{ |
|---|
| 611 | + struct in6_rtmsg rt; |
|---|
| 612 | + |
|---|
| 613 | + if (copy_from_user(&rt.rtmsg_dst, &ur->rtmsg_dst, |
|---|
| 614 | + 3 * sizeof(struct in6_addr)) || |
|---|
| 615 | + get_user(rt.rtmsg_type, &ur->rtmsg_type) || |
|---|
| 616 | + get_user(rt.rtmsg_dst_len, &ur->rtmsg_dst_len) || |
|---|
| 617 | + get_user(rt.rtmsg_src_len, &ur->rtmsg_src_len) || |
|---|
| 618 | + get_user(rt.rtmsg_metric, &ur->rtmsg_metric) || |
|---|
| 619 | + get_user(rt.rtmsg_info, &ur->rtmsg_info) || |
|---|
| 620 | + get_user(rt.rtmsg_flags, &ur->rtmsg_flags) || |
|---|
| 621 | + get_user(rt.rtmsg_ifindex, &ur->rtmsg_ifindex)) |
|---|
| 622 | + return -EFAULT; |
|---|
| 623 | + |
|---|
| 624 | + |
|---|
| 625 | + return ipv6_route_ioctl(sock_net(sk), cmd, &rt); |
|---|
| 626 | +} |
|---|
| 627 | + |
|---|
| 628 | +int inet6_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
|---|
| 629 | +{ |
|---|
| 630 | + void __user *argp = compat_ptr(arg); |
|---|
| 631 | + struct sock *sk = sock->sk; |
|---|
| 632 | + |
|---|
| 633 | + switch (cmd) { |
|---|
| 634 | + case SIOCADDRT: |
|---|
| 635 | + case SIOCDELRT: |
|---|
| 636 | + return inet6_compat_routing_ioctl(sk, cmd, argp); |
|---|
| 637 | + default: |
|---|
| 638 | + return -ENOIOCTLCMD; |
|---|
| 639 | + } |
|---|
| 640 | +} |
|---|
| 641 | +EXPORT_SYMBOL_GPL(inet6_compat_ioctl); |
|---|
| 642 | +#endif /* CONFIG_COMPAT */ |
|---|
| 643 | + |
|---|
| 644 | +INDIRECT_CALLABLE_DECLARE(int udpv6_sendmsg(struct sock *, struct msghdr *, |
|---|
| 645 | + size_t)); |
|---|
| 646 | +int inet6_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) |
|---|
| 647 | +{ |
|---|
| 648 | + struct sock *sk = sock->sk; |
|---|
| 649 | + |
|---|
| 650 | + if (unlikely(inet_send_prepare(sk))) |
|---|
| 651 | + return -EAGAIN; |
|---|
| 652 | + |
|---|
| 653 | + return INDIRECT_CALL_2(sk->sk_prot->sendmsg, tcp_sendmsg, udpv6_sendmsg, |
|---|
| 654 | + sk, msg, size); |
|---|
| 655 | +} |
|---|
| 656 | + |
|---|
| 657 | +INDIRECT_CALLABLE_DECLARE(int udpv6_recvmsg(struct sock *, struct msghdr *, |
|---|
| 658 | + size_t, int, int, int *)); |
|---|
| 659 | +int inet6_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, |
|---|
| 660 | + int flags) |
|---|
| 661 | +{ |
|---|
| 662 | + struct sock *sk = sock->sk; |
|---|
| 663 | + int addr_len = 0; |
|---|
| 664 | + int err; |
|---|
| 665 | + |
|---|
| 666 | + if (likely(!(flags & MSG_ERRQUEUE))) |
|---|
| 667 | + sock_rps_record_flow(sk); |
|---|
| 668 | + |
|---|
| 669 | + err = INDIRECT_CALL_2(sk->sk_prot->recvmsg, tcp_recvmsg, udpv6_recvmsg, |
|---|
| 670 | + sk, msg, size, flags & MSG_DONTWAIT, |
|---|
| 671 | + flags & ~MSG_DONTWAIT, &addr_len); |
|---|
| 672 | + if (err >= 0) |
|---|
| 673 | + msg->msg_namelen = addr_len; |
|---|
| 674 | + return err; |
|---|
| 675 | +} |
|---|
| 576 | 676 | |
|---|
| 577 | 677 | const struct proto_ops inet6_stream_ops = { |
|---|
| 578 | 678 | .family = PF_INET6, |
|---|
| .. | .. |
|---|
| 585 | 685 | .getname = inet6_getname, |
|---|
| 586 | 686 | .poll = tcp_poll, /* ok */ |
|---|
| 587 | 687 | .ioctl = inet6_ioctl, /* must change */ |
|---|
| 688 | + .gettstamp = sock_gettstamp, |
|---|
| 588 | 689 | .listen = inet_listen, /* ok */ |
|---|
| 589 | 690 | .shutdown = inet_shutdown, /* ok */ |
|---|
| 590 | 691 | .setsockopt = sock_common_setsockopt, /* ok */ |
|---|
| 591 | 692 | .getsockopt = sock_common_getsockopt, /* ok */ |
|---|
| 592 | | - .sendmsg = inet_sendmsg, /* ok */ |
|---|
| 593 | | - .recvmsg = inet_recvmsg, /* ok */ |
|---|
| 693 | + .sendmsg = inet6_sendmsg, /* retpoline's sake */ |
|---|
| 694 | + .recvmsg = inet6_recvmsg, /* retpoline's sake */ |
|---|
| 594 | 695 | #ifdef CONFIG_MMU |
|---|
| 595 | 696 | .mmap = tcp_mmap, |
|---|
| 596 | 697 | #endif |
|---|
| .. | .. |
|---|
| 601 | 702 | .read_sock = tcp_read_sock, |
|---|
| 602 | 703 | .peek_len = tcp_peek_len, |
|---|
| 603 | 704 | #ifdef CONFIG_COMPAT |
|---|
| 604 | | - .compat_setsockopt = compat_sock_common_setsockopt, |
|---|
| 605 | | - .compat_getsockopt = compat_sock_common_getsockopt, |
|---|
| 705 | + .compat_ioctl = inet6_compat_ioctl, |
|---|
| 606 | 706 | #endif |
|---|
| 607 | 707 | .set_rcvlowat = tcp_set_rcvlowat, |
|---|
| 608 | 708 | }; |
|---|
| .. | .. |
|---|
| 618 | 718 | .getname = inet6_getname, |
|---|
| 619 | 719 | .poll = udp_poll, /* ok */ |
|---|
| 620 | 720 | .ioctl = inet6_ioctl, /* must change */ |
|---|
| 721 | + .gettstamp = sock_gettstamp, |
|---|
| 621 | 722 | .listen = sock_no_listen, /* ok */ |
|---|
| 622 | 723 | .shutdown = inet_shutdown, /* ok */ |
|---|
| 623 | 724 | .setsockopt = sock_common_setsockopt, /* ok */ |
|---|
| 624 | 725 | .getsockopt = sock_common_getsockopt, /* ok */ |
|---|
| 625 | | - .sendmsg = inet_sendmsg, /* ok */ |
|---|
| 626 | | - .recvmsg = inet_recvmsg, /* ok */ |
|---|
| 726 | + .sendmsg = inet6_sendmsg, /* retpoline's sake */ |
|---|
| 727 | + .recvmsg = inet6_recvmsg, /* retpoline's sake */ |
|---|
| 627 | 728 | .mmap = sock_no_mmap, |
|---|
| 628 | 729 | .sendpage = sock_no_sendpage, |
|---|
| 629 | 730 | .set_peek_off = sk_set_peek_off, |
|---|
| 630 | 731 | #ifdef CONFIG_COMPAT |
|---|
| 631 | | - .compat_setsockopt = compat_sock_common_setsockopt, |
|---|
| 632 | | - .compat_getsockopt = compat_sock_common_getsockopt, |
|---|
| 732 | + .compat_ioctl = inet6_compat_ioctl, |
|---|
| 633 | 733 | #endif |
|---|
| 634 | 734 | }; |
|---|
| 635 | 735 | |
|---|
| .. | .. |
|---|
| 733 | 833 | fl6.fl6_dport = inet->inet_dport; |
|---|
| 734 | 834 | fl6.fl6_sport = inet->inet_sport; |
|---|
| 735 | 835 | fl6.flowi6_uid = sk->sk_uid; |
|---|
| 736 | | - security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
|---|
| 836 | + security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6)); |
|---|
| 737 | 837 | |
|---|
| 738 | 838 | rcu_read_lock(); |
|---|
| 739 | 839 | final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), |
|---|
| .. | .. |
|---|
| 848 | 948 | net->ipv6.sysctl.bindv6only = 0; |
|---|
| 849 | 949 | net->ipv6.sysctl.icmpv6_time = 1*HZ; |
|---|
| 850 | 950 | net->ipv6.sysctl.icmpv6_echo_ignore_all = 0; |
|---|
| 951 | + net->ipv6.sysctl.icmpv6_echo_ignore_multicast = 0; |
|---|
| 952 | + net->ipv6.sysctl.icmpv6_echo_ignore_anycast = 0; |
|---|
| 953 | + |
|---|
| 954 | + /* By default, rate limit error messages. |
|---|
| 955 | + * Except for pmtu discovery, it would break it. |
|---|
| 956 | + * proc_do_large_bitmap needs pointer to the bitmap. |
|---|
| 957 | + */ |
|---|
| 958 | + bitmap_set(net->ipv6.sysctl.icmpv6_ratemask, 0, ICMPV6_ERRMSG_MAX + 1); |
|---|
| 959 | + bitmap_clear(net->ipv6.sysctl.icmpv6_ratemask, ICMPV6_PKT_TOOBIG, 1); |
|---|
| 960 | + net->ipv6.sysctl.icmpv6_ratemask_ptr = net->ipv6.sysctl.icmpv6_ratemask; |
|---|
| 961 | + |
|---|
| 851 | 962 | net->ipv6.sysctl.flowlabel_consistency = 1; |
|---|
| 852 | 963 | net->ipv6.sysctl.auto_flowlabels = IP6_DEFAULT_AUTO_FLOW_LABELS; |
|---|
| 853 | 964 | net->ipv6.sysctl.idgen_retries = 3; |
|---|
| .. | .. |
|---|
| 901 | 1012 | .exit = inet6_net_exit, |
|---|
| 902 | 1013 | }; |
|---|
| 903 | 1014 | |
|---|
| 1015 | +static int ipv6_route_input(struct sk_buff *skb) |
|---|
| 1016 | +{ |
|---|
| 1017 | + ip6_route_input(skb); |
|---|
| 1018 | + return skb_dst(skb)->error; |
|---|
| 1019 | +} |
|---|
| 1020 | + |
|---|
| 904 | 1021 | static const struct ipv6_stub ipv6_stub_impl = { |
|---|
| 905 | 1022 | .ipv6_sock_mc_join = ipv6_sock_mc_join, |
|---|
| 906 | 1023 | .ipv6_sock_mc_drop = ipv6_sock_mc_drop, |
|---|
| 907 | 1024 | .ipv6_dst_lookup_flow = ip6_dst_lookup_flow, |
|---|
| 1025 | + .ipv6_route_input = ipv6_route_input, |
|---|
| 908 | 1026 | .fib6_get_table = fib6_get_table, |
|---|
| 909 | 1027 | .fib6_table_lookup = fib6_table_lookup, |
|---|
| 910 | 1028 | .fib6_lookup = fib6_lookup, |
|---|
| 911 | | - .fib6_multipath_select = fib6_multipath_select, |
|---|
| 1029 | + .fib6_select_path = fib6_select_path, |
|---|
| 912 | 1030 | .ip6_mtu_from_fib6 = ip6_mtu_from_fib6, |
|---|
| 1031 | + .fib6_nh_init = fib6_nh_init, |
|---|
| 1032 | + .fib6_nh_release = fib6_nh_release, |
|---|
| 1033 | + .fib6_update_sernum = fib6_update_sernum_stub, |
|---|
| 1034 | + .fib6_rt_update = fib6_rt_update, |
|---|
| 1035 | + .ip6_del_rt = ip6_del_rt, |
|---|
| 913 | 1036 | .udpv6_encap_enable = udpv6_encap_enable, |
|---|
| 914 | 1037 | .ndisc_send_na = ndisc_send_na, |
|---|
| 1038 | +#if IS_ENABLED(CONFIG_XFRM) |
|---|
| 1039 | + .xfrm6_local_rxpmtu = xfrm6_local_rxpmtu, |
|---|
| 1040 | + .xfrm6_udp_encap_rcv = xfrm6_udp_encap_rcv, |
|---|
| 1041 | + .xfrm6_rcv_encap = xfrm6_rcv_encap, |
|---|
| 1042 | +#endif |
|---|
| 915 | 1043 | .nd_tbl = &nd_tbl, |
|---|
| 1044 | + .ipv6_fragment = ip6_fragment, |
|---|
| 916 | 1045 | }; |
|---|
| 917 | 1046 | |
|---|
| 918 | 1047 | static const struct ipv6_bpf_stub ipv6_bpf_stub_impl = { |
|---|
| 919 | 1048 | .inet6_bind = __inet6_bind, |
|---|
| 1049 | + .udp6_lib_lookup = __udp6_lib_lookup, |
|---|
| 920 | 1050 | }; |
|---|
| 921 | 1051 | |
|---|
| 922 | 1052 | static int __init inet6_init(void) |
|---|
| .. | .. |
|---|
| 1016 | 1146 | err = ip6_flowlabel_init(); |
|---|
| 1017 | 1147 | if (err) |
|---|
| 1018 | 1148 | goto ip6_flowlabel_fail; |
|---|
| 1149 | + err = ipv6_anycast_init(); |
|---|
| 1150 | + if (err) |
|---|
| 1151 | + goto ipv6_anycast_fail; |
|---|
| 1019 | 1152 | err = addrconf_init(); |
|---|
| 1020 | 1153 | if (err) |
|---|
| 1021 | 1154 | goto addrconf_fail; |
|---|
| .. | .. |
|---|
| 1062 | 1195 | if (err) |
|---|
| 1063 | 1196 | goto seg6_fail; |
|---|
| 1064 | 1197 | |
|---|
| 1198 | + err = rpl_init(); |
|---|
| 1199 | + if (err) |
|---|
| 1200 | + goto rpl_fail; |
|---|
| 1201 | + |
|---|
| 1065 | 1202 | err = igmp6_late_init(); |
|---|
| 1066 | 1203 | if (err) |
|---|
| 1067 | 1204 | goto igmp6_late_err; |
|---|
| .. | .. |
|---|
| 1084 | 1221 | igmp6_late_cleanup(); |
|---|
| 1085 | 1222 | #endif |
|---|
| 1086 | 1223 | igmp6_late_err: |
|---|
| 1224 | + rpl_exit(); |
|---|
| 1225 | +rpl_fail: |
|---|
| 1087 | 1226 | seg6_exit(); |
|---|
| 1088 | 1227 | seg6_fail: |
|---|
| 1089 | 1228 | calipso_exit(); |
|---|
| .. | .. |
|---|
| 1106 | 1245 | ipv6_exthdrs_fail: |
|---|
| 1107 | 1246 | addrconf_cleanup(); |
|---|
| 1108 | 1247 | addrconf_fail: |
|---|
| 1248 | + ipv6_anycast_cleanup(); |
|---|
| 1249 | +ipv6_anycast_fail: |
|---|
| 1109 | 1250 | ip6_flowlabel_cleanup(); |
|---|
| 1110 | 1251 | ip6_flowlabel_fail: |
|---|
| 1111 | 1252 | ndisc_late_cleanup(); |
|---|