| .. | .. | 
|---|
|  | 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> | 
|---|
| .. | .. | 
|---|
| 209 | 209 | np->hop_limit	= -1; | 
|---|
| 210 | 210 | np->mcast_hops	= IPV6_DEFAULT_MCASTHOPS; | 
|---|
| 211 | 211 | np->mc_loop	= 1; | 
|---|
|  | 212 | +	np->mc_all	= 1; | 
|---|
| 212 | 213 | np->pmtudisc	= IPV6_PMTUDISC_WANT; | 
|---|
| 213 |  | -	np->repflow	= net->ipv6.sysctl.flowlabel_reflect; | 
|---|
|  | 214 | +	np->repflow	= net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ESTABLISHED; | 
|---|
| 214 | 215 | sk->sk_ipv6only	= net->ipv6.sysctl.bindv6only; | 
|---|
| 215 | 216 |  | 
|---|
| 216 | 217 | /* Init the ipv4 part of the socket since we can have sockets | 
|---|
| .. | .. | 
|---|
| 224 | 225 | inet->mc_list	= NULL; | 
|---|
| 225 | 226 | inet->rcv_tos	= 0; | 
|---|
| 226 | 227 |  | 
|---|
| 227 |  | -	if (net->ipv4.sysctl_ip_no_pmtu_disc) | 
|---|
|  | 228 | +	if (READ_ONCE(net->ipv4.sysctl_ip_no_pmtu_disc)) | 
|---|
| 228 | 229 | inet->pmtudisc = IP_PMTUDISC_DONT; | 
|---|
| 229 | 230 | else | 
|---|
| 230 | 231 | inet->pmtudisc = IP_PMTUDISC_WANT; | 
|---|
| .. | .. | 
|---|
| 274 | 275 | } | 
|---|
| 275 | 276 |  | 
|---|
| 276 | 277 | static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len, | 
|---|
| 277 |  | -			bool force_bind_address_no_port, bool with_lock) | 
|---|
|  | 278 | +			u32 flags) | 
|---|
| 278 | 279 | { | 
|---|
| 279 | 280 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *)uaddr; | 
|---|
| 280 | 281 | struct inet_sock *inet = inet_sk(sk); | 
|---|
| .. | .. | 
|---|
| 294 | 295 | return -EINVAL; | 
|---|
| 295 | 296 |  | 
|---|
| 296 | 297 | snum = ntohs(addr->sin6_port); | 
|---|
| 297 |  | -	if (snum && snum < inet_prot_sock(net) && | 
|---|
|  | 298 | +	if (snum && inet_is_local_unbindable_port(net, snum)) | 
|---|
|  | 299 | +		return -EPERM; | 
|---|
|  | 300 | +	if (snum && inet_port_requires_bind_service(net, snum) && | 
|---|
| 298 | 301 | !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) | 
|---|
| 299 | 302 | return -EACCES; | 
|---|
| 300 | 303 |  | 
|---|
| 301 |  | -	if (with_lock) | 
|---|
|  | 304 | +	if (flags & BIND_WITH_LOCK) | 
|---|
| 302 | 305 | lock_sock(sk); | 
|---|
| 303 | 306 |  | 
|---|
| 304 | 307 | /* Check these errors (active socket, double bind). */ | 
|---|
| .. | .. | 
|---|
| 401 | 404 |  | 
|---|
| 402 | 405 | /* Make sure we are allowed to bind here. */ | 
|---|
| 403 | 406 | if (snum || !(inet->bind_address_no_port || | 
|---|
| 404 |  | -		      force_bind_address_no_port)) { | 
|---|
|  | 407 | +		      (flags & BIND_FORCE_ADDRESS_NO_PORT))) { | 
|---|
| 405 | 408 | if (sk->sk_prot->get_port(sk, snum)) { | 
|---|
| 406 | 409 | sk->sk_ipv6only = saved_ipv6only; | 
|---|
| 407 | 410 | inet_reset_saddr(sk); | 
|---|
| 408 | 411 | err = -EADDRINUSE; | 
|---|
| 409 | 412 | goto out; | 
|---|
| 410 | 413 | } | 
|---|
| 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; | 
|---|
|  | 414 | +		if (!(flags & BIND_FROM_BPF)) { | 
|---|
|  | 415 | +			err = BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk); | 
|---|
|  | 416 | +			if (err) { | 
|---|
|  | 417 | +				sk->sk_ipv6only = saved_ipv6only; | 
|---|
|  | 418 | +				inet_reset_saddr(sk); | 
|---|
|  | 419 | +				goto out; | 
|---|
|  | 420 | +			} | 
|---|
| 416 | 421 | } | 
|---|
| 417 | 422 | } | 
|---|
| 418 | 423 |  | 
|---|
| .. | .. | 
|---|
| 424 | 429 | inet->inet_dport = 0; | 
|---|
| 425 | 430 | inet->inet_daddr = 0; | 
|---|
| 426 | 431 | out: | 
|---|
| 427 |  | -	if (with_lock) | 
|---|
|  | 432 | +	if (flags & BIND_WITH_LOCK) | 
|---|
| 428 | 433 | release_sock(sk); | 
|---|
| 429 | 434 | return err; | 
|---|
| 430 | 435 | out_unlock: | 
|---|
| .. | .. | 
|---|
| 452 | 457 | if (err) | 
|---|
| 453 | 458 | return err; | 
|---|
| 454 | 459 |  | 
|---|
| 455 |  | -	return __inet6_bind(sk, uaddr, addr_len, false, true); | 
|---|
|  | 460 | +	return __inet6_bind(sk, uaddr, addr_len, BIND_WITH_LOCK); | 
|---|
| 456 | 461 | } | 
|---|
| 457 | 462 | EXPORT_SYMBOL(inet6_bind); | 
|---|
| 458 | 463 |  | 
|---|
| .. | .. | 
|---|
| 482 | 487 | /* Release rx options */ | 
|---|
| 483 | 488 |  | 
|---|
| 484 | 489 | skb = xchg(&np->pktoptions, NULL); | 
|---|
| 485 |  | -	if (skb) | 
|---|
| 486 |  | -		kfree_skb(skb); | 
|---|
|  | 490 | +	kfree_skb(skb); | 
|---|
| 487 | 491 |  | 
|---|
| 488 | 492 | skb = xchg(&np->rxpmtu, NULL); | 
|---|
| 489 |  | -	if (skb) | 
|---|
| 490 |  | -		kfree_skb(skb); | 
|---|
|  | 493 | +	kfree_skb(skb); | 
|---|
| 491 | 494 |  | 
|---|
| 492 | 495 | /* Free flowlabels */ | 
|---|
| 493 | 496 | fl6_free_socklist(sk); | 
|---|
| .. | .. | 
|---|
| 505 | 508 | /* | 
|---|
| 506 | 509 | *	This does both peername and sockname. | 
|---|
| 507 | 510 | */ | 
|---|
| 508 |  | - | 
|---|
| 509 | 511 | int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | 
|---|
| 510 |  | -		 int peer) | 
|---|
|  | 512 | +		  int peer) | 
|---|
| 511 | 513 | { | 
|---|
| 512 | 514 | struct sockaddr_in6 *sin = (struct sockaddr_in6 *)uaddr; | 
|---|
| 513 | 515 | struct sock *sk = sock->sk; | 
|---|
| .. | .. | 
|---|
| 532 | 534 | sin->sin6_addr = np->saddr; | 
|---|
| 533 | 535 | else | 
|---|
| 534 | 536 | sin->sin6_addr = sk->sk_v6_rcv_saddr; | 
|---|
| 535 |  | - | 
|---|
| 536 | 537 | sin->sin6_port = inet->inet_sport; | 
|---|
| 537 | 538 | } | 
|---|
|  | 539 | +	if (cgroup_bpf_enabled) | 
|---|
|  | 540 | +		BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, | 
|---|
|  | 541 | +					    peer ? BPF_CGROUP_INET6_GETPEERNAME : | 
|---|
|  | 542 | +						   BPF_CGROUP_INET6_GETSOCKNAME, | 
|---|
|  | 543 | +					    NULL); | 
|---|
| 538 | 544 | sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr, | 
|---|
| 539 | 545 | sk->sk_bound_dev_if); | 
|---|
| 540 | 546 | return sizeof(*sin); | 
|---|
| .. | .. | 
|---|
| 543 | 549 |  | 
|---|
| 544 | 550 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 
|---|
| 545 | 551 | { | 
|---|
|  | 552 | +	void __user *argp = (void __user *)arg; | 
|---|
| 546 | 553 | struct sock *sk = sock->sk; | 
|---|
| 547 | 554 | struct net *net = sock_net(sk); | 
|---|
| 548 | 555 |  | 
|---|
| 549 | 556 | 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 | 557 | case SIOCADDRT: | 
|---|
| 557 |  | -	case SIOCDELRT: | 
|---|
|  | 558 | +	case SIOCDELRT: { | 
|---|
|  | 559 | +		struct in6_rtmsg rtmsg; | 
|---|
| 558 | 560 |  | 
|---|
| 559 |  | -		return ipv6_route_ioctl(net, cmd, (void __user *)arg); | 
|---|
| 560 |  | - | 
|---|
|  | 561 | +		if (copy_from_user(&rtmsg, argp, sizeof(rtmsg))) | 
|---|
|  | 562 | +			return -EFAULT; | 
|---|
|  | 563 | +		return ipv6_route_ioctl(net, cmd, &rtmsg); | 
|---|
|  | 564 | +	} | 
|---|
| 561 | 565 | case SIOCSIFADDR: | 
|---|
| 562 |  | -		return addrconf_add_ifaddr(net, (void __user *) arg); | 
|---|
|  | 566 | +		return addrconf_add_ifaddr(net, argp); | 
|---|
| 563 | 567 | case SIOCDIFADDR: | 
|---|
| 564 |  | -		return addrconf_del_ifaddr(net, (void __user *) arg); | 
|---|
|  | 568 | +		return addrconf_del_ifaddr(net, argp); | 
|---|
| 565 | 569 | case SIOCSIFDSTADDR: | 
|---|
| 566 |  | -		return addrconf_set_dstaddr(net, (void __user *) arg); | 
|---|
|  | 570 | +		return addrconf_set_dstaddr(net, argp); | 
|---|
| 567 | 571 | default: | 
|---|
| 568 | 572 | if (!sk->sk_prot->ioctl) | 
|---|
| 569 | 573 | return -ENOIOCTLCMD; | 
|---|
| .. | .. | 
|---|
| 573 | 577 | return 0; | 
|---|
| 574 | 578 | } | 
|---|
| 575 | 579 | EXPORT_SYMBOL(inet6_ioctl); | 
|---|
|  | 580 | + | 
|---|
|  | 581 | +#ifdef CONFIG_COMPAT | 
|---|
|  | 582 | +struct compat_in6_rtmsg { | 
|---|
|  | 583 | +	struct in6_addr		rtmsg_dst; | 
|---|
|  | 584 | +	struct in6_addr		rtmsg_src; | 
|---|
|  | 585 | +	struct in6_addr		rtmsg_gateway; | 
|---|
|  | 586 | +	u32			rtmsg_type; | 
|---|
|  | 587 | +	u16			rtmsg_dst_len; | 
|---|
|  | 588 | +	u16			rtmsg_src_len; | 
|---|
|  | 589 | +	u32			rtmsg_metric; | 
|---|
|  | 590 | +	u32			rtmsg_info; | 
|---|
|  | 591 | +	u32			rtmsg_flags; | 
|---|
|  | 592 | +	s32			rtmsg_ifindex; | 
|---|
|  | 593 | +}; | 
|---|
|  | 594 | + | 
|---|
|  | 595 | +static int inet6_compat_routing_ioctl(struct sock *sk, unsigned int cmd, | 
|---|
|  | 596 | +		struct compat_in6_rtmsg __user *ur) | 
|---|
|  | 597 | +{ | 
|---|
|  | 598 | +	struct in6_rtmsg rt; | 
|---|
|  | 599 | + | 
|---|
|  | 600 | +	if (copy_from_user(&rt.rtmsg_dst, &ur->rtmsg_dst, | 
|---|
|  | 601 | +			3 * sizeof(struct in6_addr)) || | 
|---|
|  | 602 | +	    get_user(rt.rtmsg_type, &ur->rtmsg_type) || | 
|---|
|  | 603 | +	    get_user(rt.rtmsg_dst_len, &ur->rtmsg_dst_len) || | 
|---|
|  | 604 | +	    get_user(rt.rtmsg_src_len, &ur->rtmsg_src_len) || | 
|---|
|  | 605 | +	    get_user(rt.rtmsg_metric, &ur->rtmsg_metric) || | 
|---|
|  | 606 | +	    get_user(rt.rtmsg_info, &ur->rtmsg_info) || | 
|---|
|  | 607 | +	    get_user(rt.rtmsg_flags, &ur->rtmsg_flags) || | 
|---|
|  | 608 | +	    get_user(rt.rtmsg_ifindex, &ur->rtmsg_ifindex)) | 
|---|
|  | 609 | +		return -EFAULT; | 
|---|
|  | 610 | + | 
|---|
|  | 611 | + | 
|---|
|  | 612 | +	return ipv6_route_ioctl(sock_net(sk), cmd, &rt); | 
|---|
|  | 613 | +} | 
|---|
|  | 614 | + | 
|---|
|  | 615 | +int inet6_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 
|---|
|  | 616 | +{ | 
|---|
|  | 617 | +	void __user *argp = compat_ptr(arg); | 
|---|
|  | 618 | +	struct sock *sk = sock->sk; | 
|---|
|  | 619 | + | 
|---|
|  | 620 | +	switch (cmd) { | 
|---|
|  | 621 | +	case SIOCADDRT: | 
|---|
|  | 622 | +	case SIOCDELRT: | 
|---|
|  | 623 | +		return inet6_compat_routing_ioctl(sk, cmd, argp); | 
|---|
|  | 624 | +	default: | 
|---|
|  | 625 | +		return -ENOIOCTLCMD; | 
|---|
|  | 626 | +	} | 
|---|
|  | 627 | +} | 
|---|
|  | 628 | +EXPORT_SYMBOL_GPL(inet6_compat_ioctl); | 
|---|
|  | 629 | +#endif /* CONFIG_COMPAT */ | 
|---|
|  | 630 | + | 
|---|
|  | 631 | +INDIRECT_CALLABLE_DECLARE(int udpv6_sendmsg(struct sock *, struct msghdr *, | 
|---|
|  | 632 | +					    size_t)); | 
|---|
|  | 633 | +int inet6_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) | 
|---|
|  | 634 | +{ | 
|---|
|  | 635 | +	struct sock *sk = sock->sk; | 
|---|
|  | 636 | + | 
|---|
|  | 637 | +	if (unlikely(inet_send_prepare(sk))) | 
|---|
|  | 638 | +		return -EAGAIN; | 
|---|
|  | 639 | + | 
|---|
|  | 640 | +	return INDIRECT_CALL_2(sk->sk_prot->sendmsg, tcp_sendmsg, udpv6_sendmsg, | 
|---|
|  | 641 | +			       sk, msg, size); | 
|---|
|  | 642 | +} | 
|---|
|  | 643 | + | 
|---|
|  | 644 | +INDIRECT_CALLABLE_DECLARE(int udpv6_recvmsg(struct sock *, struct msghdr *, | 
|---|
|  | 645 | +					    size_t, int, int, int *)); | 
|---|
|  | 646 | +int inet6_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | 
|---|
|  | 647 | +		  int flags) | 
|---|
|  | 648 | +{ | 
|---|
|  | 649 | +	struct sock *sk = sock->sk; | 
|---|
|  | 650 | +	int addr_len = 0; | 
|---|
|  | 651 | +	int err; | 
|---|
|  | 652 | + | 
|---|
|  | 653 | +	if (likely(!(flags & MSG_ERRQUEUE))) | 
|---|
|  | 654 | +		sock_rps_record_flow(sk); | 
|---|
|  | 655 | + | 
|---|
|  | 656 | +	err = INDIRECT_CALL_2(sk->sk_prot->recvmsg, tcp_recvmsg, udpv6_recvmsg, | 
|---|
|  | 657 | +			      sk, msg, size, flags & MSG_DONTWAIT, | 
|---|
|  | 658 | +			      flags & ~MSG_DONTWAIT, &addr_len); | 
|---|
|  | 659 | +	if (err >= 0) | 
|---|
|  | 660 | +		msg->msg_namelen = addr_len; | 
|---|
|  | 661 | +	return err; | 
|---|
|  | 662 | +} | 
|---|
| 576 | 663 |  | 
|---|
| 577 | 664 | const struct proto_ops inet6_stream_ops = { | 
|---|
| 578 | 665 | .family		   = PF_INET6, | 
|---|
| .. | .. | 
|---|
| 585 | 672 | .getname	   = inet6_getname, | 
|---|
| 586 | 673 | .poll		   = tcp_poll,			/* ok		*/ | 
|---|
| 587 | 674 | .ioctl		   = inet6_ioctl,		/* must change  */ | 
|---|
|  | 675 | +	.gettstamp	   = sock_gettstamp, | 
|---|
| 588 | 676 | .listen		   = inet_listen,		/* ok		*/ | 
|---|
| 589 | 677 | .shutdown	   = inet_shutdown,		/* ok		*/ | 
|---|
| 590 | 678 | .setsockopt	   = sock_common_setsockopt,	/* ok		*/ | 
|---|
| 591 | 679 | .getsockopt	   = sock_common_getsockopt,	/* ok		*/ | 
|---|
| 592 |  | -	.sendmsg	   = inet_sendmsg,		/* ok		*/ | 
|---|
| 593 |  | -	.recvmsg	   = inet_recvmsg,		/* ok		*/ | 
|---|
|  | 680 | +	.sendmsg	   = inet6_sendmsg,		/* retpoline's sake */ | 
|---|
|  | 681 | +	.recvmsg	   = inet6_recvmsg,		/* retpoline's sake */ | 
|---|
| 594 | 682 | #ifdef CONFIG_MMU | 
|---|
| 595 | 683 | .mmap		   = tcp_mmap, | 
|---|
| 596 | 684 | #endif | 
|---|
| .. | .. | 
|---|
| 601 | 689 | .read_sock	   = tcp_read_sock, | 
|---|
| 602 | 690 | .peek_len	   = tcp_peek_len, | 
|---|
| 603 | 691 | #ifdef CONFIG_COMPAT | 
|---|
| 604 |  | -	.compat_setsockopt = compat_sock_common_setsockopt, | 
|---|
| 605 |  | -	.compat_getsockopt = compat_sock_common_getsockopt, | 
|---|
|  | 692 | +	.compat_ioctl	   = inet6_compat_ioctl, | 
|---|
| 606 | 693 | #endif | 
|---|
| 607 | 694 | .set_rcvlowat	   = tcp_set_rcvlowat, | 
|---|
| 608 | 695 | }; | 
|---|
| .. | .. | 
|---|
| 618 | 705 | .getname	   = inet6_getname, | 
|---|
| 619 | 706 | .poll		   = udp_poll,			/* ok		*/ | 
|---|
| 620 | 707 | .ioctl		   = inet6_ioctl,		/* must change  */ | 
|---|
|  | 708 | +	.gettstamp	   = sock_gettstamp, | 
|---|
| 621 | 709 | .listen		   = sock_no_listen,		/* ok		*/ | 
|---|
| 622 | 710 | .shutdown	   = inet_shutdown,		/* ok		*/ | 
|---|
| 623 | 711 | .setsockopt	   = sock_common_setsockopt,	/* ok		*/ | 
|---|
| 624 | 712 | .getsockopt	   = sock_common_getsockopt,	/* ok		*/ | 
|---|
| 625 |  | -	.sendmsg	   = inet_sendmsg,		/* ok		*/ | 
|---|
| 626 |  | -	.recvmsg	   = inet_recvmsg,		/* ok		*/ | 
|---|
|  | 713 | +	.sendmsg	   = inet6_sendmsg,		/* retpoline's sake */ | 
|---|
|  | 714 | +	.recvmsg	   = inet6_recvmsg,		/* retpoline's sake */ | 
|---|
| 627 | 715 | .mmap		   = sock_no_mmap, | 
|---|
| 628 | 716 | .sendpage	   = sock_no_sendpage, | 
|---|
| 629 | 717 | .set_peek_off	   = sk_set_peek_off, | 
|---|
| 630 | 718 | #ifdef CONFIG_COMPAT | 
|---|
| 631 |  | -	.compat_setsockopt = compat_sock_common_setsockopt, | 
|---|
| 632 |  | -	.compat_getsockopt = compat_sock_common_getsockopt, | 
|---|
|  | 719 | +	.compat_ioctl	   = inet6_compat_ioctl, | 
|---|
| 633 | 720 | #endif | 
|---|
| 634 | 721 | }; | 
|---|
| 635 | 722 |  | 
|---|
| .. | .. | 
|---|
| 733 | 820 | fl6.fl6_dport = inet->inet_dport; | 
|---|
| 734 | 821 | fl6.fl6_sport = inet->inet_sport; | 
|---|
| 735 | 822 | fl6.flowi6_uid = sk->sk_uid; | 
|---|
| 736 |  | -		security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 
|---|
|  | 823 | +		security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6)); | 
|---|
| 737 | 824 |  | 
|---|
| 738 | 825 | rcu_read_lock(); | 
|---|
| 739 | 826 | final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), | 
|---|
| .. | .. | 
|---|
| 848 | 935 | net->ipv6.sysctl.bindv6only = 0; | 
|---|
| 849 | 936 | net->ipv6.sysctl.icmpv6_time = 1*HZ; | 
|---|
| 850 | 937 | net->ipv6.sysctl.icmpv6_echo_ignore_all = 0; | 
|---|
|  | 938 | +	net->ipv6.sysctl.icmpv6_echo_ignore_multicast = 0; | 
|---|
|  | 939 | +	net->ipv6.sysctl.icmpv6_echo_ignore_anycast = 0; | 
|---|
|  | 940 | + | 
|---|
|  | 941 | +	/* By default, rate limit error messages. | 
|---|
|  | 942 | +	 * Except for pmtu discovery, it would break it. | 
|---|
|  | 943 | +	 * proc_do_large_bitmap needs pointer to the bitmap. | 
|---|
|  | 944 | +	 */ | 
|---|
|  | 945 | +	bitmap_set(net->ipv6.sysctl.icmpv6_ratemask, 0, ICMPV6_ERRMSG_MAX + 1); | 
|---|
|  | 946 | +	bitmap_clear(net->ipv6.sysctl.icmpv6_ratemask, ICMPV6_PKT_TOOBIG, 1); | 
|---|
|  | 947 | +	net->ipv6.sysctl.icmpv6_ratemask_ptr = net->ipv6.sysctl.icmpv6_ratemask; | 
|---|
|  | 948 | + | 
|---|
| 851 | 949 | net->ipv6.sysctl.flowlabel_consistency = 1; | 
|---|
| 852 | 950 | net->ipv6.sysctl.auto_flowlabels = IP6_DEFAULT_AUTO_FLOW_LABELS; | 
|---|
| 853 | 951 | net->ipv6.sysctl.idgen_retries = 3; | 
|---|
| .. | .. | 
|---|
| 901 | 999 | .exit = inet6_net_exit, | 
|---|
| 902 | 1000 | }; | 
|---|
| 903 | 1001 |  | 
|---|
|  | 1002 | +static int ipv6_route_input(struct sk_buff *skb) | 
|---|
|  | 1003 | +{ | 
|---|
|  | 1004 | +	ip6_route_input(skb); | 
|---|
|  | 1005 | +	return skb_dst(skb)->error; | 
|---|
|  | 1006 | +} | 
|---|
|  | 1007 | + | 
|---|
| 904 | 1008 | static const struct ipv6_stub ipv6_stub_impl = { | 
|---|
| 905 | 1009 | .ipv6_sock_mc_join = ipv6_sock_mc_join, | 
|---|
| 906 | 1010 | .ipv6_sock_mc_drop = ipv6_sock_mc_drop, | 
|---|
| 907 | 1011 | .ipv6_dst_lookup_flow = ip6_dst_lookup_flow, | 
|---|
|  | 1012 | +	.ipv6_route_input  = ipv6_route_input, | 
|---|
| 908 | 1013 | .fib6_get_table	   = fib6_get_table, | 
|---|
| 909 | 1014 | .fib6_table_lookup = fib6_table_lookup, | 
|---|
| 910 | 1015 | .fib6_lookup       = fib6_lookup, | 
|---|
| 911 |  | -	.fib6_multipath_select = fib6_multipath_select, | 
|---|
|  | 1016 | +	.fib6_select_path  = fib6_select_path, | 
|---|
| 912 | 1017 | .ip6_mtu_from_fib6 = ip6_mtu_from_fib6, | 
|---|
|  | 1018 | +	.fib6_nh_init	   = fib6_nh_init, | 
|---|
|  | 1019 | +	.fib6_nh_release   = fib6_nh_release, | 
|---|
|  | 1020 | +	.fib6_update_sernum = fib6_update_sernum_stub, | 
|---|
|  | 1021 | +	.fib6_rt_update	   = fib6_rt_update, | 
|---|
|  | 1022 | +	.ip6_del_rt	   = ip6_del_rt, | 
|---|
| 913 | 1023 | .udpv6_encap_enable = udpv6_encap_enable, | 
|---|
| 914 | 1024 | .ndisc_send_na = ndisc_send_na, | 
|---|
|  | 1025 | +#if IS_ENABLED(CONFIG_XFRM) | 
|---|
|  | 1026 | +	.xfrm6_local_rxpmtu = xfrm6_local_rxpmtu, | 
|---|
|  | 1027 | +	.xfrm6_udp_encap_rcv = xfrm6_udp_encap_rcv, | 
|---|
|  | 1028 | +	.xfrm6_rcv_encap = xfrm6_rcv_encap, | 
|---|
|  | 1029 | +#endif | 
|---|
| 915 | 1030 | .nd_tbl	= &nd_tbl, | 
|---|
|  | 1031 | +	.ipv6_fragment = ip6_fragment, | 
|---|
| 916 | 1032 | }; | 
|---|
| 917 | 1033 |  | 
|---|
| 918 | 1034 | static const struct ipv6_bpf_stub ipv6_bpf_stub_impl = { | 
|---|
| 919 | 1035 | .inet6_bind = __inet6_bind, | 
|---|
|  | 1036 | +	.udp6_lib_lookup = __udp6_lib_lookup, | 
|---|
| 920 | 1037 | }; | 
|---|
| 921 | 1038 |  | 
|---|
| 922 | 1039 | static int __init inet6_init(void) | 
|---|
| .. | .. | 
|---|
| 1016 | 1133 | err = ip6_flowlabel_init(); | 
|---|
| 1017 | 1134 | if (err) | 
|---|
| 1018 | 1135 | goto ip6_flowlabel_fail; | 
|---|
|  | 1136 | +	err = ipv6_anycast_init(); | 
|---|
|  | 1137 | +	if (err) | 
|---|
|  | 1138 | +		goto ipv6_anycast_fail; | 
|---|
| 1019 | 1139 | err = addrconf_init(); | 
|---|
| 1020 | 1140 | if (err) | 
|---|
| 1021 | 1141 | goto addrconf_fail; | 
|---|
| .. | .. | 
|---|
| 1062 | 1182 | if (err) | 
|---|
| 1063 | 1183 | goto seg6_fail; | 
|---|
| 1064 | 1184 |  | 
|---|
|  | 1185 | +	err = rpl_init(); | 
|---|
|  | 1186 | +	if (err) | 
|---|
|  | 1187 | +		goto rpl_fail; | 
|---|
|  | 1188 | + | 
|---|
| 1065 | 1189 | err = igmp6_late_init(); | 
|---|
| 1066 | 1190 | if (err) | 
|---|
| 1067 | 1191 | goto igmp6_late_err; | 
|---|
| .. | .. | 
|---|
| 1084 | 1208 | igmp6_late_cleanup(); | 
|---|
| 1085 | 1209 | #endif | 
|---|
| 1086 | 1210 | igmp6_late_err: | 
|---|
|  | 1211 | +	rpl_exit(); | 
|---|
|  | 1212 | +rpl_fail: | 
|---|
| 1087 | 1213 | seg6_exit(); | 
|---|
| 1088 | 1214 | seg6_fail: | 
|---|
| 1089 | 1215 | calipso_exit(); | 
|---|
| .. | .. | 
|---|
| 1106 | 1232 | ipv6_exthdrs_fail: | 
|---|
| 1107 | 1233 | addrconf_cleanup(); | 
|---|
| 1108 | 1234 | addrconf_fail: | 
|---|
|  | 1235 | +	ipv6_anycast_cleanup(); | 
|---|
|  | 1236 | +ipv6_anycast_fail: | 
|---|
| 1109 | 1237 | ip6_flowlabel_cleanup(); | 
|---|
| 1110 | 1238 | ip6_flowlabel_fail: | 
|---|
| 1111 | 1239 | ndisc_late_cleanup(); | 
|---|