.. | .. |
---|
| 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(); |
---|