4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 1990 Mentat Inc.
24 */
25
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #include <sys/dlpi.h>
29 #include <sys/stropts.h>
30 #include <sys/sysmacros.h>
31 #include <sys/strsun.h>
32 #include <sys/strlog.h>
33 #include <sys/strsubr.h>
34 #define _SUN_TPI_VERSION 2
35 #include <sys/tihdr.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/cmn_err.h>
39 #include <sys/debug.h>
40 #include <sys/sdt.h>
41 #include <sys/kobj.h>
42 #include <sys/zone.h>
43 #include <sys/neti.h>
665 * which generated error is in the send window.
666 *
667 * In some cases modified this MTU in the ICMP header packet; the caller
668 * should pass to the matching ULP after this returns.
669 */
670 static void
671 icmp_inbound_too_big_v6(icmp6_t *icmp6, ip_recv_attr_t *ira)
672 {
673 uint32_t mtu;
674 dce_t *dce;
675 ill_t *ill = ira->ira_ill; /* Upper ill if IPMP */
676 ip_stack_t *ipst = ill->ill_ipst;
677 int old_max_frag;
678 in6_addr_t final_dst;
679 ip6_t *ip6h; /* Inner IP header */
680
681 /* Caller has already pulled up everything. */
682 ip6h = (ip6_t *)&icmp6[1];
683 final_dst = ip_get_dst_v6(ip6h, NULL, NULL);
684
685 /*
686 * For link local destinations matching simply on address is not
687 * sufficient. Same link local addresses for different ILL's is
688 * possible.
689 */
690 if (IN6_IS_ADDR_LINKSCOPE(&final_dst)) {
691 dce = dce_lookup_and_add_v6(&final_dst,
692 ill->ill_phyint->phyint_ifindex, ipst);
693 } else {
694 dce = dce_lookup_and_add_v6(&final_dst, 0, ipst);
695 }
696 if (dce == NULL) {
697 /* Couldn't add a unique one - ENOMEM */
698 if (ip_debug > 2) {
699 /* ip1dbg */
700 pr_addr_dbg("icmp_inbound_too_big_v6:"
701 "no dce for dst %s\n", AF_INET6,
702 &final_dst);
703 }
704 return;
705 }
706
707 mtu = ntohl(icmp6->icmp6_mtu);
708
709 mutex_enter(&dce->dce_lock);
710 if (dce->dce_flags & DCEF_PMTU)
711 old_max_frag = dce->dce_pmtu;
712 else if (IN6_IS_ADDR_MULTICAST(&final_dst))
713 old_max_frag = ill->ill_mc_mtu;
714 else
715 old_max_frag = ill->ill_mtu;
716
717 if (mtu < IPV6_MIN_MTU) {
718 ip1dbg(("Received mtu less than IPv6 "
719 "min mtu %d: %d\n", IPV6_MIN_MTU, mtu));
720 mtu = IPV6_MIN_MTU;
721 /*
722 * If an mtu less than IPv6 min mtu is received,
723 * we must include a fragment header in
724 * subsequent packets.
725 */
726 dce->dce_flags |= DCEF_TOO_SMALL_PMTU;
727 } else {
728 dce->dce_flags &= ~DCEF_TOO_SMALL_PMTU;
729 }
730 ip1dbg(("Received mtu from router: %d\n", mtu));
731 dce->dce_pmtu = MIN(old_max_frag, mtu);
732
733 /* Prepare to send the new max frag size for the ULP. */
734 if (dce->dce_flags & DCEF_TOO_SMALL_PMTU) {
735 /*
736 * If we need a fragment header in every packet
737 * (above case or multirouting), make sure the
738 * ULP takes it into account when computing the
739 * payload size.
740 */
741 icmp6->icmp6_mtu = htonl(dce->dce_pmtu - sizeof (ip6_frag_t));
742 } else {
743 icmp6->icmp6_mtu = htonl(dce->dce_pmtu);
744 }
745 /* We now have a PMTU for sure */
746 dce->dce_flags |= DCEF_PMTU;
747 dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
748 mutex_exit(&dce->dce_lock);
749 /*
750 * After dropping the lock the new value is visible to everyone.
751 * Then we bump the generation number so any cached values reinspect
752 * the dce_t.
753 */
754 dce_increment_generation(dce);
755 dce_refrele(dce);
756 }
757
758 /*
759 * Fanout received ICMPv6 error packets to the transports.
760 * Assumes the IPv6 plus ICMPv6 headers have been pulled up but nothing else.
761 *
762 * The caller must have called icmp_inbound_verify_v6.
763 */
764 void
765 icmp_inbound_error_fanout_v6(mblk_t *mp, icmp6_t *icmp6, ip_recv_attr_t *ira)
766 {
767 uint16_t *up; /* Pointer to ports in ULP header */
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 1990 Mentat Inc.
24 * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/stream.h>
29 #include <sys/dlpi.h>
30 #include <sys/stropts.h>
31 #include <sys/sysmacros.h>
32 #include <sys/strsun.h>
33 #include <sys/strlog.h>
34 #include <sys/strsubr.h>
35 #define _SUN_TPI_VERSION 2
36 #include <sys/tihdr.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 #include <sys/cmn_err.h>
40 #include <sys/debug.h>
41 #include <sys/sdt.h>
42 #include <sys/kobj.h>
43 #include <sys/zone.h>
44 #include <sys/neti.h>
666 * which generated error is in the send window.
667 *
668 * In some cases modified this MTU in the ICMP header packet; the caller
669 * should pass to the matching ULP after this returns.
670 */
671 static void
672 icmp_inbound_too_big_v6(icmp6_t *icmp6, ip_recv_attr_t *ira)
673 {
674 uint32_t mtu;
675 dce_t *dce;
676 ill_t *ill = ira->ira_ill; /* Upper ill if IPMP */
677 ip_stack_t *ipst = ill->ill_ipst;
678 int old_max_frag;
679 in6_addr_t final_dst;
680 ip6_t *ip6h; /* Inner IP header */
681
682 /* Caller has already pulled up everything. */
683 ip6h = (ip6_t *)&icmp6[1];
684 final_dst = ip_get_dst_v6(ip6h, NULL, NULL);
685
686 mtu = ntohl(icmp6->icmp6_mtu);
687 if (mtu < IPV6_MIN_MTU) {
688 /*
689 * RFC 8021 suggests to ignore messages where mtu is
690 * less than the IPv6 minimum.
691 */
692 ip1dbg(("Received mtu less than IPv6 "
693 "min mtu %d: %d\n", IPV6_MIN_MTU, mtu));
694 DTRACE_PROBE1(icmp6__too__small__mtu, uint32_t, mtu);
695 return;
696 }
697
698 /*
699 * For link local destinations matching simply on address is not
700 * sufficient. Same link local addresses for different ILL's is
701 * possible.
702 */
703 if (IN6_IS_ADDR_LINKSCOPE(&final_dst)) {
704 dce = dce_lookup_and_add_v6(&final_dst,
705 ill->ill_phyint->phyint_ifindex, ipst);
706 } else {
707 dce = dce_lookup_and_add_v6(&final_dst, 0, ipst);
708 }
709 if (dce == NULL) {
710 /* Couldn't add a unique one - ENOMEM */
711 if (ip_debug > 2) {
712 /* ip1dbg */
713 pr_addr_dbg("icmp_inbound_too_big_v6:"
714 "no dce for dst %s\n", AF_INET6,
715 &final_dst);
716 }
717 return;
718 }
719
720 mutex_enter(&dce->dce_lock);
721 if (dce->dce_flags & DCEF_PMTU)
722 old_max_frag = dce->dce_pmtu;
723 else if (IN6_IS_ADDR_MULTICAST(&final_dst))
724 old_max_frag = ill->ill_mc_mtu;
725 else
726 old_max_frag = ill->ill_mtu;
727
728 ip1dbg(("Received mtu from router: %d\n", mtu));
729 DTRACE_PROBE1(icmp6__received__mtu, uint32_t, mtu);
730 dce->dce_pmtu = MIN(old_max_frag, mtu);
731 icmp6->icmp6_mtu = htonl(dce->dce_pmtu);
732
733 /* We now have a PMTU for sure */
734 dce->dce_flags |= DCEF_PMTU;
735 dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
736
737 mutex_exit(&dce->dce_lock);
738 /*
739 * After dropping the lock the new value is visible to everyone.
740 * Then we bump the generation number so any cached values reinspect
741 * the dce_t.
742 */
743 dce_increment_generation(dce);
744 dce_refrele(dce);
745 }
746
747 /*
748 * Fanout received ICMPv6 error packets to the transports.
749 * Assumes the IPv6 plus ICMPv6 headers have been pulled up but nothing else.
750 *
751 * The caller must have called icmp_inbound_verify_v6.
752 */
753 void
754 icmp_inbound_error_fanout_v6(mblk_t *mp, icmp6_t *icmp6, ip_recv_attr_t *ira)
755 {
756 uint16_t *up; /* Pointer to ports in ULP header */
|