Print this page
Don't create DCE for bad MTU.


 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         /*










 687          * For link local destinations matching simply on address is not
 688          * sufficient. Same link local addresses for different ILL's is
 689          * possible.
 690          */
 691         if (IN6_IS_ADDR_LINKSCOPE(&final_dst)) {
 692                 dce = dce_lookup_and_add_v6(&final_dst,
 693                     ill->ill_phyint->phyint_ifindex, ipst);
 694         } else {
 695                 dce = dce_lookup_and_add_v6(&final_dst, 0, ipst);
 696         }
 697         if (dce == NULL) {
 698                 /* Couldn't add a unique one - ENOMEM */
 699                 if (ip_debug > 2) {
 700                         /* ip1dbg */
 701                         pr_addr_dbg("icmp_inbound_too_big_v6:"
 702                             "no dce for dst %s\n", AF_INET6,
 703                             &final_dst);
 704                 }
 705                 return;
 706         }
 707 
 708         mtu = ntohl(icmp6->icmp6_mtu);
 709 
 710         mutex_enter(&dce->dce_lock);
 711         if (dce->dce_flags & DCEF_PMTU)
 712                 old_max_frag = dce->dce_pmtu;
 713         else if (IN6_IS_ADDR_MULTICAST(&final_dst))
 714                 old_max_frag = ill->ill_mc_mtu;
 715         else
 716                 old_max_frag = ill->ill_mtu;
 717 
 718         if (mtu >= IPV6_MIN_MTU) {
 719                 ip1dbg(("Received mtu from router: %d\n", mtu));
 720                 DTRACE_PROBE1(icmp6__received__mtu, uint32_t, mtu);
 721                 dce->dce_pmtu = MIN(old_max_frag, mtu);
 722                 icmp6->icmp6_mtu = htonl(dce->dce_pmtu);
 723 
 724                 /* We now have a PMTU for sure */
 725                 dce->dce_flags |= DCEF_PMTU;
 726                 dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
 727         } else {
 728                 /*
 729                  * RFC 8021 suggests to ignore messages where mtu is
 730                  * less than the IPv6 minimum.
 731                  */
 732                 ip1dbg(("Received mtu less than IPv6 "
 733                     "min mtu %d: %d\n", IPV6_MIN_MTU, mtu));
 734                 DTRACE_PROBE1(icmp6__too__small__mtu, uint32_t, mtu);
 735         }
 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 {




 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 {