usr/src/uts/common/inet/ip/ip6.c
changeset 741 40027a3621ac
parent 679 f2c9450b58f4
child 1145 98865ed5c2e7
equal deleted inserted replaced
740:70e4862c9a1a 741:40027a3621ac
    56 #include <sys/atomic.h>
    56 #include <sys/atomic.h>
    57 #include <sys/iphada.h>
    57 #include <sys/iphada.h>
    58 #include <sys/policy.h>
    58 #include <sys/policy.h>
    59 #include <net/if.h>
    59 #include <net/if.h>
    60 #include <net/if_arp.h>
    60 #include <net/if_arp.h>
       
    61 #include <net/if_types.h>
    61 #include <net/route.h>
    62 #include <net/route.h>
    62 #include <net/if_dl.h>
    63 #include <net/if_dl.h>
    63 #include <sys/sockio.h>
    64 #include <sys/sockio.h>
    64 #include <netinet/in.h>
    65 #include <netinet/in.h>
    65 #include <netinet/ip6.h>
    66 #include <netinet/ip6.h>
    72 #include <inet/nd.h>
    73 #include <inet/nd.h>
    73 #include <inet/arp.h>
    74 #include <inet/arp.h>
    74 #include <inet/snmpcom.h>
    75 #include <inet/snmpcom.h>
    75 
    76 
    76 #include <inet/ip.h>
    77 #include <inet/ip.h>
       
    78 #include <inet/ip_impl.h>
    77 #include <inet/ip6.h>
    79 #include <inet/ip6.h>
    78 #include <inet/ip6_asp.h>
    80 #include <inet/ip6_asp.h>
    79 #include <inet/tcp.h>
    81 #include <inet/tcp.h>
       
    82 #include <inet/tcp_impl.h>
       
    83 #include <inet/udp_impl.h>
    80 #include <inet/ipp_common.h>
    84 #include <inet/ipp_common.h>
    81 
    85 
    82 #include <inet/ip_multi.h>
    86 #include <inet/ip_multi.h>
    83 #include <inet/ip_if.h>
    87 #include <inet/ip_if.h>
    84 #include <inet/ip_ire.h>
    88 #include <inet/ip_ire.h>
   101 extern squeue_func_t ip_input_proc;
   105 extern squeue_func_t ip_input_proc;
   102 
   106 
   103 /*
   107 /*
   104  * IP statistics.
   108  * IP statistics.
   105  */
   109  */
   106 #define	IP6_STAT(x)	(ip6_statistics.x.value.ui64++)
   110 #define	IP6_STAT(x)		(ip6_statistics.x.value.ui64++)
       
   111 #define	IP6_STAT_UPDATE(x, n)	(ip6_statistics.x.value.ui64 += (n))
   107 
   112 
   108 typedef struct ip6_stat {
   113 typedef struct ip6_stat {
   109 	kstat_named_t	ip6_udp_fast_path;
   114 	kstat_named_t	ip6_udp_fast_path;
   110 	kstat_named_t	ip6_udp_slow_path;
   115 	kstat_named_t	ip6_udp_slow_path;
   111 	kstat_named_t	ip6_udp_fannorm;
   116 	kstat_named_t	ip6_udp_fannorm;
   112 	kstat_named_t	ip6_udp_fanmb;
   117 	kstat_named_t	ip6_udp_fanmb;
       
   118 	kstat_named_t   ip6_out_sw_cksum;
       
   119 	kstat_named_t   ip6_in_sw_cksum;
       
   120 	kstat_named_t	ip6_tcp_in_full_hw_cksum_err;
       
   121 	kstat_named_t	ip6_tcp_in_part_hw_cksum_err;
       
   122 	kstat_named_t	ip6_tcp_in_sw_cksum_err;
       
   123 	kstat_named_t	ip6_tcp_out_sw_cksum_bytes;
       
   124 	kstat_named_t	ip6_udp_in_full_hw_cksum_err;
       
   125 	kstat_named_t	ip6_udp_in_part_hw_cksum_err;
       
   126 	kstat_named_t	ip6_udp_in_sw_cksum_err;
       
   127 	kstat_named_t	ip6_udp_out_sw_cksum_bytes;
       
   128 	kstat_named_t	ip6_frag_mdt_pkt_out;
       
   129 	kstat_named_t	ip6_frag_mdt_discarded;
       
   130 	kstat_named_t	ip6_frag_mdt_allocfail;
       
   131 	kstat_named_t	ip6_frag_mdt_addpdescfail;
       
   132 	kstat_named_t	ip6_frag_mdt_allocd;
   113 } ip6_stat_t;
   133 } ip6_stat_t;
   114 
   134 
   115 static ip6_stat_t ip6_statistics = {
   135 static ip6_stat_t ip6_statistics = {
   116 	{ "ip6_udp_fast_path", 	KSTAT_DATA_UINT64 },
   136 	{ "ip6_udp_fast_path",			KSTAT_DATA_UINT64 },
   117 	{ "ip6_udp_slow_path", 	KSTAT_DATA_UINT64 },
   137 	{ "ip6_udp_slow_path",			KSTAT_DATA_UINT64 },
   118 	{ "ip6_udp_fannorm", 	KSTAT_DATA_UINT64 },
   138 	{ "ip6_udp_fannorm",			KSTAT_DATA_UINT64 },
   119 	{ "ip6_udp_fanmb", 	KSTAT_DATA_UINT64 },
   139 	{ "ip6_udp_fanmb",			KSTAT_DATA_UINT64 },
       
   140 	{ "ip6_out_sw_cksum",			KSTAT_DATA_UINT64 },
       
   141 	{ "ip6_in_sw_cksum",			KSTAT_DATA_UINT64 },
       
   142 	{ "ip6_tcp_in_full_hw_cksum_err",	KSTAT_DATA_UINT64 },
       
   143 	{ "ip6_tcp_in_part_hw_cksum_err",	KSTAT_DATA_UINT64 },
       
   144 	{ "ip6_tcp_in_sw_cksum_err",		KSTAT_DATA_UINT64 },
       
   145 	{ "ip6_tcp_out_sw_cksum_bytes",		KSTAT_DATA_UINT64 },
       
   146 	{ "ip6_udp_in_full_hw_cksum_err",	KSTAT_DATA_UINT64 },
       
   147 	{ "ip6_udp_in_part_hw_cksum_err",	KSTAT_DATA_UINT64 },
       
   148 	{ "ip6_udp_in_sw_cksum_err",		KSTAT_DATA_UINT64 },
       
   149 	{ "ip6_udp_out_sw_cksum_bytes",		KSTAT_DATA_UINT64 },
       
   150 	{ "ip6_frag_mdt_pkt_out",		KSTAT_DATA_UINT64 },
       
   151 	{ "ip6_frag_mdt_discarded",		KSTAT_DATA_UINT64 },
       
   152 	{ "ip6_frag_mdt_allocfail",		KSTAT_DATA_UINT64 },
       
   153 	{ "ip6_frag_mdt_addpdescfail",		KSTAT_DATA_UINT64 },
       
   154 	{ "ip6_frag_mdt_allocd",		KSTAT_DATA_UINT64 },
   120 };
   155 };
   121 
   156 
   122 static kstat_t *ip6_kstat;
   157 static kstat_t *ip6_kstat;
   123 
   158 
   124 /*
   159 /*
   219 static void	ip_fanout_udp_v6(queue_t *, mblk_t *, ip6_t *, uint32_t,
   254 static void	ip_fanout_udp_v6(queue_t *, mblk_t *, ip6_t *, uint32_t,
   220     ill_t *, ill_t *, uint_t, boolean_t, zoneid_t);
   255     ill_t *, ill_t *, uint_t, boolean_t, zoneid_t);
   221 static int	ip_process_options_v6(queue_t *, mblk_t *, ip6_t *,
   256 static int	ip_process_options_v6(queue_t *, mblk_t *, ip6_t *,
   222     uint8_t *, uint_t, uint8_t);
   257     uint8_t *, uint_t, uint8_t);
   223 static mblk_t	*ip_rput_frag_v6(queue_t *, mblk_t *, ip6_t *,
   258 static mblk_t	*ip_rput_frag_v6(queue_t *, mblk_t *, ip6_t *,
   224     ip6_frag_t *, uint_t, uint_t *);
   259     ip6_frag_t *, uint_t, uint_t *, uint32_t *, uint16_t *);
   225 static boolean_t	ip_source_routed_v6(ip6_t *, mblk_t *);
   260 static boolean_t	ip_source_routed_v6(ip6_t *, mblk_t *);
   226 static void	ip_wput_ire_v6(queue_t *, mblk_t *, ire_t *, int, int,
   261 static void	ip_wput_ire_v6(queue_t *, mblk_t *, ire_t *, int, int,
   227     conn_t *, int, int, int);
   262     conn_t *, int, int, int);
   228 static boolean_t ip_ulp_cando_pkt2big(int);
   263 static boolean_t ip_ulp_cando_pkt2big(int);
   229 
   264 
  2300 		}
  2335 		}
  2301 		if (protocol == IPPROTO_TCP)
  2336 		if (protocol == IPPROTO_TCP)
  2302 			connp->conn_recv = tcp_input;
  2337 			connp->conn_recv = tcp_input;
  2303 	}
  2338 	}
  2304 	/* Update qinfo if v4/v6 changed */
  2339 	/* Update qinfo if v4/v6 changed */
  2305 	if ((orig_pkt_isv6 != connp->conn_pkt_isv6) && !IS_TCP_CONN(connp)) {
  2340 	if ((orig_pkt_isv6 != connp->conn_pkt_isv6) &&
       
  2341 	    !(IPCL_IS_TCP(connp) || IPCL_IS_UDP(connp))) {
  2306 		if (connp->conn_pkt_isv6)
  2342 		if (connp->conn_pkt_isv6)
  2307 			ip_setqinfo(RD(q), IPV6_MINOR, B_TRUE);
  2343 			ip_setqinfo(RD(q), IPV6_MINOR, B_TRUE);
  2308 		else
  2344 		else
  2309 			ip_setqinfo(RD(q), IPV4_MINOR, B_TRUE);
  2345 			ip_setqinfo(RD(q), IPV4_MINOR, B_TRUE);
  2310 	}
  2346 	}
  2529 static void
  2565 static void
  2530 ip_bind_connected_resume_v6(ipsq_t *ipsq, queue_t *q, mblk_t *mp,
  2566 ip_bind_connected_resume_v6(ipsq_t *ipsq, queue_t *q, mblk_t *mp,
  2531     void *dummy_arg)
  2567     void *dummy_arg)
  2532 {
  2568 {
  2533 	conn_t	*connp = NULL;
  2569 	conn_t	*connp = NULL;
  2534 	tcp_t *tcp;
       
  2535 	t_scalar_t prim;
  2570 	t_scalar_t prim;
  2536 
  2571 
  2537 	ASSERT(DB_TYPE(mp) == M_PROTO || DB_TYPE(mp) == M_PCPROTO);
  2572 	ASSERT(DB_TYPE(mp) == M_PROTO || DB_TYPE(mp) == M_PCPROTO);
  2538 
  2573 
  2539 	if (CONN_Q(q))
  2574 	if (CONN_Q(q))
  2541 	ASSERT(connp != NULL);
  2576 	ASSERT(connp != NULL);
  2542 
  2577 
  2543 	prim = ((union T_primitives *)mp->b_rptr)->type;
  2578 	prim = ((union T_primitives *)mp->b_rptr)->type;
  2544 	ASSERT(prim == O_T_BIND_REQ || prim == T_BIND_REQ);
  2579 	ASSERT(prim == O_T_BIND_REQ || prim == T_BIND_REQ);
  2545 
  2580 
  2546 	tcp = connp->conn_tcp;
  2581 	if (IPCL_IS_TCP(connp)) {
  2547 	if (tcp != NULL) {
       
  2548 		/* Pass sticky_ipp for scope_id and pktinfo */
  2582 		/* Pass sticky_ipp for scope_id and pktinfo */
  2549 		mp = ip_bind_v6(q, mp, connp, &tcp->tcp_sticky_ipp);
  2583 		mp = ip_bind_v6(q, mp, connp, &connp->conn_tcp->tcp_sticky_ipp);
  2550 	} else {
  2584 	} else {
  2551 		/* For UDP and ICMP */
  2585 		/* For UDP and ICMP */
  2552 		mp = ip_bind_v6(q, mp, connp, NULL);
  2586 		mp = ip_bind_v6(q, mp, connp, NULL);
  2553 	}
  2587 	}
  2554 	if (mp != NULL) {
  2588 	if (mp != NULL) {
  2555 		if (tcp != NULL) {
  2589 		if (IPCL_IS_TCP(connp)) {
  2556 			CONN_INC_REF(connp);
  2590 			CONN_INC_REF(connp);
  2557 			squeue_fill(connp->conn_sqp, mp,
  2591 			squeue_fill(connp->conn_sqp, mp, ip_resume_tcp_bind,
  2558 			    ip_resume_tcp_bind, connp, SQTAG_TCP_RPUTOTHER);
  2592 			    connp, SQTAG_TCP_RPUTOTHER);
  2559 			return;
  2593 		} else if (IPCL_IS_UDP(connp)) {
       
  2594 			udp_resume_bind(connp, mp);
  2560 		} else {
  2595 		} else {
  2561 			qreply(q, mp);
  2596 			qreply(q, mp);
  2562 		}
  2597 			CONN_OPER_PENDING_DONE(connp);
  2563 		CONN_OPER_PENDING_DONE(connp);
  2598 		}
  2564 	}
  2599 	}
  2565 }
  2600 }
  2566 
  2601 
  2567 /*
  2602 /*
  2568  * Verify that both the source and destination addresses
  2603  * Verify that both the source and destination addresses
  2717 	 * IRE during Multidata packet transmission in tcp_multisend().
  2752 	 * IRE during Multidata packet transmission in tcp_multisend().
  2718 	 */
  2753 	 */
  2719 	if (ip_multidata_outbound && !ipsec_policy_set && dst_ire != NULL &&
  2754 	if (ip_multidata_outbound && !ipsec_policy_set && dst_ire != NULL &&
  2720 	    !(dst_ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST)) &&
  2755 	    !(dst_ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST)) &&
  2721 	    (md_ill = ire_to_ill(dst_ire), md_ill != NULL) &&
  2756 	    (md_ill = ire_to_ill(dst_ire), md_ill != NULL) &&
  2722 	    (md_ill->ill_capabilities & ILL_CAPAB_MDT)) {
  2757 	    ILL_MDT_CAPABLE(md_ill)) {
  2723 		md_dst_ire = dst_ire;
  2758 		md_dst_ire = dst_ire;
  2724 		IRE_REFHOLD(md_dst_ire);
  2759 		IRE_REFHOLD(md_dst_ire);
  2725 	}
  2760 	}
  2726 
  2761 
  2727 	if (dst_ire != NULL &&
  2762 	if (dst_ire != NULL &&
  2934 		 * The addresses have been verified. Time to insert in
  2969 		 * The addresses have been verified. Time to insert in
  2935 		 * the correct fanout list.
  2970 		 * the correct fanout list.
  2936 		 */
  2971 		 */
  2937 		error = ipcl_conn_insert_v6(connp, protocol, v6src, v6dst,
  2972 		error = ipcl_conn_insert_v6(connp, protocol, v6src, v6dst,
  2938 		    connp->conn_ports,
  2973 		    connp->conn_ports,
  2939 		    IS_TCP_CONN(connp) ? connp->conn_tcp->tcp_bound_if : 0);
  2974 		    IPCL_IS_TCP(connp) ? connp->conn_tcp->tcp_bound_if : 0);
  2940 	}
  2975 	}
  2941 	if (error == 0) {
  2976 	if (error == 0) {
  2942 		connp->conn_fully_bound = B_TRUE;
  2977 		connp->conn_fully_bound = B_TRUE;
  2943 		/*
  2978 		/*
  2944 		 * Our initial checks for MDT have passed; the IRE is not
  2979 		 * Our initial checks for MDT have passed; the IRE is not
  3409 		uint32_t ill_index;
  3444 		uint32_t ill_index;
  3410 
  3445 
  3411 		ASSERT((dp->db_struioflag & STRUIO_IP) == 0);
  3446 		ASSERT((dp->db_struioflag & STRUIO_IP) == 0);
  3412 
  3447 
  3413 		/* Initiate IPPf processing, if needed. */
  3448 		/* Initiate IPPf processing, if needed. */
  3414 		if (IPP_ENABLED(IPP_LOCAL_IN) &&
  3449 		if (IPP_ENABLED(IPP_LOCAL_IN) && (flags & IP6_NO_IPPOLICY)) {
  3415 			(flags & (IP6_NO_IPPOLICY|IP6_IN_NOCKSUM))) {
       
  3416 			ill_index = ill->ill_phyint->phyint_ifindex;
  3450 			ill_index = ill->ill_phyint->phyint_ifindex;
  3417 			ip_process(IPP_LOCAL_IN, &first_mp, ill_index);
  3451 			ip_process(IPP_LOCAL_IN, &first_mp, ill_index);
  3418 			if (first_mp == NULL) {
  3452 			if (first_mp == NULL) {
  3419 				if (connp != NULL)
  3453 				if (connp != NULL)
  3420 					CONN_DEC_REF(connp);
  3454 					CONN_DEC_REF(connp);
  3445 			} else {
  3479 			} else {
  3446 				sqp = IP_SQUEUE_GET(lbolt);
  3480 				sqp = IP_SQUEUE_GET(lbolt);
  3447 			}
  3481 			}
  3448 
  3482 
  3449 			mp->b_datap->db_struioflag |= STRUIO_EAGER;
  3483 			mp->b_datap->db_struioflag |= STRUIO_EAGER;
  3450 			mp->b_datap->db_cksumstart = (intptr_t)sqp;
  3484 			DB_CKSUMSTART(mp) = (intptr_t)sqp;
  3451 
  3485 
  3452 			/*
  3486 			/*
  3453 			 * db_cksumstuff is unused in the incoming
  3487 			 * db_cksumstuff is unused in the incoming
  3454 			 * path; Thus store the ifindex here. It will
  3488 			 * path; Thus store the ifindex here. It will
  3455 			 * be cleared in tcp_conn_create_v6().
  3489 			 * be cleared in tcp_conn_create_v6().
  3456 			 */
  3490 			 */
  3457 			mp->b_datap->db_cksumstuff =
  3491 			DB_CKSUMSTUFF(mp) =
  3458 			    (intptr_t)ill->ill_phyint->phyint_ifindex;
  3492 			    (intptr_t)ill->ill_phyint->phyint_ifindex;
  3459 			syn_present = B_TRUE;
  3493 			syn_present = B_TRUE;
  3460 		}
  3494 		}
  3461 	}
  3495 	}
  3462 
  3496 
  3585 static void
  3619 static void
  3586 ip_fanout_udp_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h, uint32_t ports,
  3620 ip_fanout_udp_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h, uint32_t ports,
  3587     ill_t *ill, ill_t *inill, uint_t flags, boolean_t mctl_present,
  3621     ill_t *ill, ill_t *inill, uint_t flags, boolean_t mctl_present,
  3588     zoneid_t zoneid)
  3622     zoneid_t zoneid)
  3589 {
  3623 {
  3590 	queue_t		*rq;
       
  3591 	uint32_t	dstport, srcport;
  3624 	uint32_t	dstport, srcport;
  3592 	in6_addr_t	dst;
  3625 	in6_addr_t	dst;
  3593 	mblk_t		*first_mp;
  3626 	mblk_t		*first_mp;
  3594 	boolean_t	secure;
  3627 	boolean_t	secure;
  3595 	conn_t		*connp;
  3628 	conn_t		*connp;
  3635 			goto notfound;
  3668 			goto notfound;
  3636 
  3669 
  3637 		/* Found a client */
  3670 		/* Found a client */
  3638 		CONN_INC_REF(connp);
  3671 		CONN_INC_REF(connp);
  3639 		mutex_exit(&connfp->connf_lock);
  3672 		mutex_exit(&connfp->connf_lock);
  3640 		rq = connp->conn_rq;
  3673 
  3641 
  3674 		if (CONN_UDP_FLOWCTLD(connp)) {
  3642 		if (!canputnext(rq)) {
       
  3643 			freemsg(first_mp);
  3675 			freemsg(first_mp);
  3644 			BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
  3676 			BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
  3645 			CONN_DEC_REF(connp);
  3677 			CONN_DEC_REF(connp);
  3646 			return;
  3678 			return;
  3647 		}
  3679 		}
  3689 			} else {
  3721 			} else {
  3690 				first_mp = mp;
  3722 				first_mp = mp;
  3691 			}
  3723 			}
  3692 		}
  3724 		}
  3693 		BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers);
  3725 		BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers);
  3694 		putnext(rq, mp);
  3726 
       
  3727 		/* Send it upstream */
       
  3728 		CONN_UDP_RECV(connp, mp);
       
  3729 
  3695 		IP6_STAT(ip6_udp_fannorm);
  3730 		IP6_STAT(ip6_udp_fannorm);
  3696 		CONN_DEC_REF(connp);
  3731 		CONN_DEC_REF(connp);
  3697 		if (mctl_present)
  3732 		if (mctl_present)
  3698 			freeb(first_mp);
  3733 			freeb(first_mp);
  3699 		return;
  3734 		return;
  3744 			break;
  3779 			break;
  3745 		}
  3780 		}
  3746 		mp1 = mctl_present ? first_mp1->b_cont : first_mp1;
  3781 		mp1 = mctl_present ? first_mp1->b_cont : first_mp1;
  3747 		CONN_INC_REF(connp);
  3782 		CONN_INC_REF(connp);
  3748 		mutex_exit(&connfp->connf_lock);
  3783 		mutex_exit(&connfp->connf_lock);
  3749 		rq = connp->conn_rq;
       
  3750 		/*
  3784 		/*
  3751 		 * For link-local always add ifindex so that transport
  3785 		 * For link-local always add ifindex so that transport
  3752 		 * can set sin6_scope_id. Avoid it for ICMP error
  3786 		 * can set sin6_scope_id. Avoid it for ICMP error
  3753 		 * fanout.
  3787 		 * fanout.
  3754 		 */
  3788 		 */
  3760 		}
  3794 		}
  3761 		if (mp1 == NULL) {
  3795 		if (mp1 == NULL) {
  3762 			BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards);
  3796 			BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards);
  3763 			goto next_one;
  3797 			goto next_one;
  3764 		}
  3798 		}
  3765 		if (!canputnext(rq)) {
  3799 		if (CONN_UDP_FLOWCTLD(connp)) {
  3766 			BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
  3800 			BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
  3767 			freemsg(mp1);
  3801 			freemsg(mp1);
  3768 			goto next_one;
  3802 			goto next_one;
  3769 		}
  3803 		}
  3770 
  3804 
  3776 		}
  3810 		}
  3777 		if (first_mp1 != NULL) {
  3811 		if (first_mp1 != NULL) {
  3778 			if (mctl_present)
  3812 			if (mctl_present)
  3779 				freeb(first_mp1);
  3813 				freeb(first_mp1);
  3780 			BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers);
  3814 			BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers);
  3781 			putnext(rq, mp1);
  3815 
       
  3816 			/* Send it upstream */
       
  3817 			CONN_UDP_RECV(connp, mp1);
  3782 		}
  3818 		}
  3783 next_one:
  3819 next_one:
  3784 		mutex_enter(&connfp->connf_lock);
  3820 		mutex_enter(&connfp->connf_lock);
  3785 		/* Follow the next pointer before releasing the conn. */
  3821 		/* Follow the next pointer before releasing the conn. */
  3786 		next_conn = connp->conn_next;
  3822 		next_conn = connp->conn_next;
  3789 		connp = next_conn;
  3825 		connp = next_conn;
  3790 	}
  3826 	}
  3791 
  3827 
  3792 	/* Last one.  Send it upstream. */
  3828 	/* Last one.  Send it upstream. */
  3793 	mutex_exit(&connfp->connf_lock);
  3829 	mutex_exit(&connfp->connf_lock);
  3794 	rq = connp->conn_rq;
       
  3795 
  3830 
  3796 	/* Initiate IPPF processing */
  3831 	/* Initiate IPPF processing */
  3797 	if (IP6_IN_IPP(flags)) {
  3832 	if (IP6_IN_IPP(flags)) {
  3798 		uint_t	ifindex;
  3833 		uint_t	ifindex;
  3799 
  3834 
  3828 			first_mp->b_cont = mp;
  3863 			first_mp->b_cont = mp;
  3829 		} else {
  3864 		} else {
  3830 			first_mp = mp;
  3865 			first_mp = mp;
  3831 		}
  3866 		}
  3832 	}
  3867 	}
  3833 	if (!canputnext(rq)) {
  3868 	if (CONN_UDP_FLOWCTLD(connp)) {
  3834 		BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
  3869 		BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
  3835 		freemsg(mp);
  3870 		freemsg(mp);
  3836 	} else {
  3871 	} else {
  3837 		if (CONN_INBOUND_POLICY_PRESENT_V6(connp) || secure) {
  3872 		if (CONN_INBOUND_POLICY_PRESENT_V6(connp) || secure) {
  3838 			first_mp = ipsec_check_inbound_policy(first_mp,
  3873 			first_mp = ipsec_check_inbound_policy(first_mp,
  3842 				CONN_DEC_REF(connp);
  3877 				CONN_DEC_REF(connp);
  3843 				return;
  3878 				return;
  3844 			}
  3879 			}
  3845 		}
  3880 		}
  3846 		BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers);
  3881 		BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers);
  3847 		putnext(rq, mp);
  3882 
       
  3883 		/* Send it upstream */
       
  3884 		CONN_UDP_RECV(connp, mp);
  3848 	}
  3885 	}
  3849 	IP6_STAT(ip6_udp_fanmb);
  3886 	IP6_STAT(ip6_udp_fanmb);
  3850 	CONN_DEC_REF(connp);
  3887 	CONN_DEC_REF(connp);
  3851 	if (mctl_present)
  3888 	if (mctl_present)
  3852 		freeb(first_mp);
  3889 		freeb(first_mp);
  6445 		 * because the ill has been cleaned up and things hanging
  6482 		 * because the ill has been cleaned up and things hanging
  6446 		 * off the ill have been freed.
  6483 		 * off the ill have been freed.
  6447 		 */
  6484 		 */
  6448 		if ((mp->b_datap->db_type != M_PCPROTO) ||
  6485 		if ((mp->b_datap->db_type != M_PCPROTO) ||
  6449 		    (dl->dl_primitive == DL_UNITDATA_IND)) {
  6486 		    (dl->dl_primitive == DL_UNITDATA_IND)) {
  6450 			ip_ioctl_freemsg(mp);
  6487 			inet_freemsg(mp);
  6451 			return;
  6488 			return;
  6452 		}
  6489 		}
  6453 	}
  6490 	}
  6454 
  6491 
  6455 	switch (mp->b_datap->db_type) {
  6492 	switch (mp->b_datap->db_type) {
  6833 	boolean_t	mctl_present;
  6870 	boolean_t	mctl_present;
  6834 	mblk_t		*first_mp;
  6871 	mblk_t		*first_mp;
  6835 	mblk_t		*first_mp1;
  6872 	mblk_t		*first_mp1;
  6836 	boolean_t	no_forward;
  6873 	boolean_t	no_forward;
  6837 	ip6_hbh_t	*hbhhdr;
  6874 	ip6_hbh_t	*hbhhdr;
  6838 	boolean_t	no_cksum = (flags & IP6_IN_NOCKSUM);
       
  6839 	boolean_t	ll_multicast = (flags & IP6_IN_LLMCAST);
  6875 	boolean_t	ll_multicast = (flags & IP6_IN_LLMCAST);
  6840 	conn_t		*connp;
  6876 	conn_t		*connp;
  6841 	int		off;
       
  6842 	ilm_t		*ilm;
  6877 	ilm_t		*ilm;
  6843 	uint32_t	ports;
  6878 	uint32_t	ports;
  6844 	uint_t		ipif_id = 0;
  6879 	uint_t		ipif_id = 0;
  6845 	zoneid_t	zoneid = GLOBAL_ZONEID;
  6880 	zoneid_t	zoneid = GLOBAL_ZONEID;
       
  6881 	uint16_t	hck_flags, reass_hck_flags;
       
  6882 	uint32_t	reass_sum;
       
  6883 	boolean_t	cksum_err;
       
  6884 	mblk_t		*mp1;
  6846 
  6885 
  6847 	EXTRACT_PKT_MP(mp, first_mp, mctl_present);
  6886 	EXTRACT_PKT_MP(mp, first_mp, mctl_present);
  6848 
  6887 
  6849 	if (hada_mp != NULL) {
  6888 	if (hada_mp != NULL) {
  6850 		/*
  6889 		/*
  6897 			return;
  6936 			return;
  6898 		}
  6937 		}
  6899 		pkt_len -= diff;
  6938 		pkt_len -= diff;
  6900 	}
  6939 	}
  6901 
  6940 
  6902 	/*
  6941 	if (ILL_HCKSUM_CAPABLE(ill) && !mctl_present && dohwcksum)
  6903 	 * XXX When zero-copy support is added, this turning off of
  6942 		hck_flags = DB_CKSUMFLAGS(mp);
  6904 	 * checksum flag  will need to be done more selectively.
  6943 	else
  6905 	 */
  6944 		hck_flags = 0;
  6906 	mp->b_datap->db_struioun.cksum.flags &= ~HCK_PARTIALCKSUM;
  6945 
       
  6946 	/* Clear checksum flags in case we need to forward */
       
  6947 	DB_CKSUMFLAGS(mp) = 0;
       
  6948 	reass_sum = reass_hck_flags = 0;
  6907 
  6949 
  6908 	nexthdr = ip6h->ip6_nxt;
  6950 	nexthdr = ip6h->ip6_nxt;
  6909 
  6951 
  6910 	prev_nexthdr_offset = (uint_t)((uchar_t *)&ip6h->ip6_nxt -
  6952 	prev_nexthdr_offset = (uint_t)((uchar_t *)&ip6h->ip6_nxt -
  6911 	    (uchar_t *)ip6h);
  6953 	    (uchar_t *)ip6h);
  7166 				return;
  7208 				return;
  7167 			}
  7209 			}
  7168 			/* TBD add site-local check at site boundary? */
  7210 			/* TBD add site-local check at site boundary? */
  7169 		} else if (ipv6_send_redirects) {
  7211 		} else if (ipv6_send_redirects) {
  7170 			in6_addr_t	*v6targ;
  7212 			in6_addr_t	*v6targ;
  7171 			mblk_t		*mp1;
       
  7172 			in6_addr_t	gw_addr_v6;
  7213 			in6_addr_t	gw_addr_v6;
  7173 			ire_t		*src_ire_v6 = NULL;
  7214 			ire_t		*src_ire_v6 = NULL;
  7174 
  7215 
  7175 			/*
  7216 			/*
  7176 			 * Don't send a redirect when forwarding a source
  7217 			 * Don't send a redirect when forwarding a source
  7311 	for (; ; ) {
  7352 	for (; ; ) {
  7312 		switch (nexthdr) {
  7353 		switch (nexthdr) {
  7313 		case IPPROTO_TCP: {
  7354 		case IPPROTO_TCP: {
  7314 			uint16_t	*up;
  7355 			uint16_t	*up;
  7315 			uint32_t	sum;
  7356 			uint32_t	sum;
  7316 			dblk_t		*dp;
       
  7317 			int		offset;
  7357 			int		offset;
  7318 
  7358 
  7319 			hdr_len = pkt_len - remlen;
  7359 			hdr_len = pkt_len - remlen;
  7320 
  7360 
  7321 			if (hada_mp != NULL) {
  7361 			if (hada_mp != NULL) {
  7334 					BUMP_MIB(ill->ill_ip6_mib,
  7374 					BUMP_MIB(ill->ill_ip6_mib,
  7335 					    ipv6InDiscards);
  7375 					    ipv6InDiscards);
  7336 					freemsg(first_mp);
  7376 					freemsg(first_mp);
  7337 					return;
  7377 					return;
  7338 				}
  7378 				}
       
  7379 				hck_flags = 0;
  7339 				ip6h = (ip6_t *)mp->b_rptr;
  7380 				ip6h = (ip6_t *)mp->b_rptr;
  7340 				whereptr = (uint8_t *)ip6h + hdr_len;
  7381 				whereptr = (uint8_t *)ip6h + hdr_len;
  7341 			}
  7382 			}
  7342 			/*
  7383 			/*
  7343 			 * Extract the offset field from the TCP header.
  7384 			 * Extract the offset field from the TCP header.
  7366 						BUMP_MIB(ill->ill_ip6_mib,
  7407 						BUMP_MIB(ill->ill_ip6_mib,
  7367 						    ipv6InDiscards);
  7408 						    ipv6InDiscards);
  7368 						freemsg(first_mp);
  7409 						freemsg(first_mp);
  7369 						return;
  7410 						return;
  7370 					}
  7411 					}
       
  7412 					hck_flags = 0;
  7371 					ip6h = (ip6_t *)mp->b_rptr;
  7413 					ip6h = (ip6_t *)mp->b_rptr;
  7372 					whereptr = (uint8_t *)ip6h + hdr_len;
  7414 					whereptr = (uint8_t *)ip6h + hdr_len;
  7373 				}
  7415 				}
  7374 			}
       
  7375 
       
  7376 			/*
       
  7377 			 * If packet is being looped back locally checksums
       
  7378 			 * aren't used
       
  7379 			 */
       
  7380 			if (no_cksum) {
       
  7381 				if (mp->b_datap->db_type == M_DATA) {
       
  7382 					/*
       
  7383 					 * M_DATA mblk, so init mblk (chain)
       
  7384 					 * for no struio().
       
  7385 					 */
       
  7386 					mblk_t  *mp1 = mp;
       
  7387 
       
  7388 					do {
       
  7389 						mp1->b_datap->db_struioflag = 0;
       
  7390 					} while ((mp1 = mp1->b_cont) != NULL);
       
  7391 				}
       
  7392 				goto tcp_fanout;
       
  7393 			}
  7416 			}
  7394 
  7417 
  7395 			up = (uint16_t *)&ip6h->ip6_src;
  7418 			up = (uint16_t *)&ip6h->ip6_src;
  7396 			/*
  7419 			/*
  7397 			 * TCP checksum calculation.  First sum up the
  7420 			 * TCP checksum calculation.  First sum up the
  7398 			 * pseudo-header fields:
  7421 			 * pseudo-header fields:
  7399 			 *  -	Source IPv6 address
  7422 			 *  -	Source IPv6 address
  7400 			 *  -	Destination IPv6 address
  7423 			 *  -	Destination IPv6 address
  7401 			 *  -	TCP payload length
  7424 			 *  -	TCP payload length
  7402 			 *  -	TCP protocol ID
  7425 			 *  -	TCP protocol ID
  7403 			 * XXX need zero-copy support here
       
  7404 			 */
  7426 			 */
  7405 			sum = htons(IPPROTO_TCP + remlen) +
  7427 			sum = htons(IPPROTO_TCP + remlen) +
  7406 			    up[0] + up[1] + up[2] + up[3] +
  7428 			    up[0] + up[1] + up[2] + up[3] +
  7407 			    up[4] + up[5] + up[6] + up[7] +
  7429 			    up[4] + up[5] + up[6] + up[7] +
  7408 			    up[8] + up[9] + up[10] + up[11] +
  7430 			    up[8] + up[9] + up[10] + up[11] +
  7409 			    up[12] + up[13] + up[14] + up[15];
  7431 			    up[12] + up[13] + up[14] + up[15];
       
  7432 
       
  7433 			/* Fold initial sum */
  7410 			sum = (sum & 0xffff) + (sum >> 16);
  7434 			sum = (sum & 0xffff) + (sum >> 16);
  7411 			dp = mp->b_datap;
  7435 
  7412 			if (dp->db_type != M_DATA || dp->db_ref > 1) {
  7436 			mp1 = mp->b_cont;
  7413 				/*
  7437 
  7414 				 * Not M_DATA mblk or its a dup, so do the
  7438 			if ((hck_flags & (HCK_FULLCKSUM|HCK_PARTIALCKSUM)) == 0)
  7415 				 * checksum now.
  7439 				IP6_STAT(ip6_in_sw_cksum);
  7416 				 */
  7440 
  7417 				sum = IP_CSUM(mp, hdr_len, sum);
  7441 			IP_CKSUM_RECV(hck_flags, sum, (uchar_t *)
  7418 				if (sum) {
  7442 			    ((uchar_t *)mp->b_rptr + DB_CKSUMSTART(mp)),
  7419 					/* checksum failed */
  7443 			    (int32_t)(whereptr - (uchar_t *)mp->b_rptr),
  7420 					ip1dbg(("ip_rput_data_v6: TCP checksum"
  7444 			    mp, mp1, cksum_err);
  7421 					    " failed %x off %d\n",
  7445 
  7422 					    sum, hdr_len));
  7446 			if (cksum_err) {
  7423 					BUMP_MIB(&ip_mib, tcpInErrs);
  7447 				BUMP_MIB(&ip_mib, tcpInErrs);
  7424 					freemsg(first_mp);
  7448 
  7425 					return;
  7449 				if (hck_flags & HCK_FULLCKSUM)
  7426 				}
  7450 					IP6_STAT(ip6_tcp_in_full_hw_cksum_err);
  7427 			} else {
  7451 				else if (hck_flags & HCK_PARTIALCKSUM)
  7428 				/*
  7452 					IP6_STAT(ip6_tcp_in_part_hw_cksum_err);
  7429 				 * M_DATA mblk and not a dup
  7453 				else
  7430 				 * compute checksum here
  7454 					IP6_STAT(ip6_tcp_in_sw_cksum_err);
  7431 				 */
  7455 
  7432 				off = (int)(whereptr - mp->b_rptr);
  7456 				freemsg(first_mp);
  7433 
  7457 				return;
  7434 				if (IP_CSUM(mp, off, sum)) {
       
  7435 					BUMP_MIB(&ip_mib, tcpInErrs);
       
  7436 					ipcsumdbg("ip_rput_data_v6 "
       
  7437 					    "swcksumerr\n", mp);
       
  7438 					freemsg(first_mp);
       
  7439 					return;
       
  7440 				}
       
  7441 			}
  7458 			}
  7442 tcp_fanout:
  7459 tcp_fanout:
  7443 			ip_fanout_tcp_v6(q, first_mp, ip6h, ill, inill,
  7460 			ip_fanout_tcp_v6(q, first_mp, ip6h, ill, inill,
  7444 			    (flags|IP_FF_SEND_ICMP|IP_FF_SYN_ADDIRE|
  7461 			    (flags|IP_FF_SEND_ICMP|IP_FF_SYN_ADDIRE|
  7445 			    IP_FF_IP6INFO), hdr_len, mctl_present, zoneid);
  7462 			    IP_FF_IP6INFO), hdr_len, mctl_present, zoneid);
  7466 				ip6h = (ip6_t *)mp->b_rptr;
  7483 				ip6h = (ip6_t *)mp->b_rptr;
  7467 				whereptr = (uint8_t *)ip6h + hdr_len;
  7484 				whereptr = (uint8_t *)ip6h + hdr_len;
  7468 			}
  7485 			}
  7469 
  7486 
  7470 			sctph = (sctp_hdr_t *)(mp->b_rptr + hdr_len);
  7487 			sctph = (sctp_hdr_t *)(mp->b_rptr + hdr_len);
  7471 			if (!no_cksum) {
  7488 			/* checksum */
  7472 				/* checksum */
  7489 			pktsum = sctph->sh_chksum;
  7473 				pktsum = sctph->sh_chksum;
  7490 			sctph->sh_chksum = 0;
  7474 				sctph->sh_chksum = 0;
  7491 			calcsum = sctp_cksum(mp, hdr_len);
  7475 				calcsum = sctp_cksum(mp, hdr_len);
  7492 			if (calcsum != pktsum) {
  7476 				if (calcsum != pktsum) {
  7493 				BUMP_MIB(&sctp_mib, sctpChecksumError);
  7477 					BUMP_MIB(&sctp_mib, sctpChecksumError);
  7494 				freemsg(mp);
  7478 					freemsg(mp);
  7495 				return;
  7479 					return;
  7496 			}
  7480 				}
  7497 			sctph->sh_chksum = pktsum;
  7481 				sctph->sh_chksum = pktsum;
       
  7482 			}
       
  7483 			ports = *(uint32_t *)(mp->b_rptr + hdr_len);
  7498 			ports = *(uint32_t *)(mp->b_rptr + hdr_len);
  7484 			if ((connp = sctp_find_conn(&ip6h->ip6_src,
  7499 			if ((connp = sctp_find_conn(&ip6h->ip6_src,
  7485 			    &ip6h->ip6_dst, ports, ipif_id, zoneid)) == NULL) {
  7500 			    &ip6h->ip6_dst, ports, ipif_id, zoneid)) == NULL) {
  7486 				ip_fanout_sctp_raw(first_mp, ill,
  7501 				ip_fanout_sctp_raw(first_mp, ill,
  7487 				    (ipha_t *)ip6h, B_FALSE, ports,
  7502 				    (ipha_t *)ip6h, B_FALSE, ports,
  7498 		case IPPROTO_UDP: {
  7513 		case IPPROTO_UDP: {
  7499 			uint16_t	*up;
  7514 			uint16_t	*up;
  7500 			uint32_t	sum;
  7515 			uint32_t	sum;
  7501 
  7516 
  7502 			hdr_len = pkt_len - remlen;
  7517 			hdr_len = pkt_len - remlen;
  7503 
       
  7504 #define	UDPH_SIZE 8
       
  7505 
  7518 
  7506 			if (hada_mp != NULL) {
  7519 			if (hada_mp != NULL) {
  7507 				ip0dbg(("udp hada drop\n"));
  7520 				ip0dbg(("udp hada drop\n"));
  7508 				goto hada_drop;
  7521 				goto hada_drop;
  7509 			}
  7522 			}
  7517 					BUMP_MIB(ill->ill_ip6_mib,
  7530 					BUMP_MIB(ill->ill_ip6_mib,
  7518 					    ipv6InDiscards);
  7531 					    ipv6InDiscards);
  7519 					freemsg(first_mp);
  7532 					freemsg(first_mp);
  7520 					return;
  7533 					return;
  7521 				}
  7534 				}
       
  7535 				hck_flags = 0;
  7522 				ip6h = (ip6_t *)mp->b_rptr;
  7536 				ip6h = (ip6_t *)mp->b_rptr;
  7523 				whereptr = (uint8_t *)ip6h + hdr_len;
  7537 				whereptr = (uint8_t *)ip6h + hdr_len;
  7524 			}
  7538 			}
  7525 #undef UDPH_SIZE
       
  7526 			/*
       
  7527 			 * If packet is being looped back locally checksums
       
  7528 			 * aren't used
       
  7529 			 */
       
  7530 			if (no_cksum)
       
  7531 				goto udp_fanout;
       
  7532 
  7539 
  7533 			/*
  7540 			/*
  7534 			 *  Before going through the regular checksum
  7541 			 *  Before going through the regular checksum
  7535 			 *  calculation, make sure the received checksum
  7542 			 *  calculation, make sure the received checksum
  7536 			 *  is non-zero. RFC 2460 says, a 0x0000 checksum
  7543 			 *  is non-zero. RFC 2460 says, a 0x0000 checksum
  7566 			    up[0] + up[1] + up[2] + up[3] +
  7573 			    up[0] + up[1] + up[2] + up[3] +
  7567 			    up[4] + up[5] + up[6] + up[7] +
  7574 			    up[4] + up[5] + up[6] + up[7] +
  7568 			    up[8] + up[9] + up[10] + up[11] +
  7575 			    up[8] + up[9] + up[10] + up[11] +
  7569 			    up[12] + up[13] + up[14] + up[15];
  7576 			    up[12] + up[13] + up[14] + up[15];
  7570 
  7577 
       
  7578 			/* Fold initial sum */
  7571 			sum = (sum & 0xffff) + (sum >> 16);
  7579 			sum = (sum & 0xffff) + (sum >> 16);
  7572 			/* Next sum in the UDP packet */
  7580 
  7573 			sum = IP_CSUM(mp, hdr_len, sum);
  7581 			if (reass_hck_flags != 0) {
  7574 			if (sum) {
  7582 				hck_flags = reass_hck_flags;
  7575 				/* UDP checksum failed */
  7583 
  7576 				ip1dbg(("ip_rput_data_v6: UDP checksum "
  7584 				IP_CKSUM_RECV_REASS(hck_flags,
  7577 				    "failed %x\n",
  7585 				    (int32_t)(whereptr - (uchar_t *)mp->b_rptr),
  7578 				    sum));
  7586 				    sum, reass_sum, cksum_err);
       
  7587 			} else {
       
  7588 				mp1 = mp->b_cont;
       
  7589 
       
  7590 				IP_CKSUM_RECV(hck_flags, sum, (uchar_t *)
       
  7591 				    ((uchar_t *)mp->b_rptr + DB_CKSUMSTART(mp)),
       
  7592 				    (int32_t)(whereptr - (uchar_t *)mp->b_rptr),
       
  7593 				    mp, mp1, cksum_err);
       
  7594 			}
       
  7595 
       
  7596 			if ((hck_flags & (HCK_FULLCKSUM|HCK_PARTIALCKSUM)) == 0)
       
  7597 				IP6_STAT(ip6_in_sw_cksum);
       
  7598 
       
  7599 			if (cksum_err) {
  7579 				BUMP_MIB(ill->ill_ip6_mib, udpInCksumErrs);
  7600 				BUMP_MIB(ill->ill_ip6_mib, udpInCksumErrs);
       
  7601 
       
  7602 				if (hck_flags & HCK_FULLCKSUM)
       
  7603 					IP6_STAT(ip6_udp_in_full_hw_cksum_err);
       
  7604 				else if (hck_flags & HCK_PARTIALCKSUM)
       
  7605 					IP6_STAT(ip6_udp_in_part_hw_cksum_err);
       
  7606 				else
       
  7607 					IP6_STAT(ip6_udp_in_sw_cksum_err);
       
  7608 
  7580 				freemsg(first_mp);
  7609 				freemsg(first_mp);
  7581 				return;
  7610 				return;
  7582 			}
  7611 			}
  7583 			goto udp_fanout;
  7612 			goto udp_fanout;
  7584 		}
  7613 		}
  7589 
  7618 
  7590 			if (hada_mp != NULL) {
  7619 			if (hada_mp != NULL) {
  7591 				ip0dbg(("icmp hada drop\n"));
  7620 				ip0dbg(("icmp hada drop\n"));
  7592 				goto hada_drop;
  7621 				goto hada_drop;
  7593 			}
  7622 			}
  7594 
       
  7595 			/*
       
  7596 			 * If packet is being looped back locally checksums
       
  7597 			 * aren't used
       
  7598 			 */
       
  7599 			if (no_cksum)
       
  7600 				goto icmp_fanout;
       
  7601 
  7623 
  7602 			up = (uint16_t *)&ip6h->ip6_src;
  7624 			up = (uint16_t *)&ip6h->ip6_src;
  7603 			sum = htons(IPPROTO_ICMPV6 + remlen) +
  7625 			sum = htons(IPPROTO_ICMPV6 + remlen) +
  7604 			    up[0] + up[1] + up[2] + up[3] +
  7626 			    up[0] + up[1] + up[2] + up[3] +
  7605 			    up[4] + up[5] + up[6] + up[7] +
  7627 			    up[4] + up[5] + up[6] + up[7] +
  7606 			    up[8] + up[9] + up[10] + up[11] +
  7628 			    up[8] + up[9] + up[10] + up[11] +
  7607 			    up[12] + up[13] + up[14] + up[15];
  7629 			    up[12] + up[13] + up[14] + up[15];
  7608 			sum = (sum & 0xffff) + (sum >> 16);
  7630 			sum = (sum & 0xffff) + (sum >> 16);
  7609 			sum = IP_CSUM(mp, hdr_len, sum);
  7631 			sum = IP_CSUM(mp, hdr_len, sum);
  7610 			if (sum) {
  7632 			if (sum != 0) {
  7611 				/* IPv6 ICMP checksum failed */
  7633 				/* IPv6 ICMP checksum failed */
  7612 				ip1dbg(("ip_rput_data_v6: ICMPv6 checksum "
  7634 				ip1dbg(("ip_rput_data_v6: ICMPv6 checksum "
  7613 				    "failed %x\n",
  7635 				    "failed %x\n",
  7614 				    sum));
  7636 				    sum));
  7615 				BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInMsgs);
  7637 				BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInMsgs);
  7793 					BUMP_MIB(ill->ill_ip6_mib,
  7815 					BUMP_MIB(ill->ill_ip6_mib,
  7794 					    ipv6InDiscards);
  7816 					    ipv6InDiscards);
  7795 					freemsg(mp);
  7817 					freemsg(mp);
  7796 					return;
  7818 					return;
  7797 				}
  7819 				}
       
  7820 				hck_flags = 0;
  7798 				ip6h = (ip6_t *)mp->b_rptr;
  7821 				ip6h = (ip6_t *)mp->b_rptr;
  7799 				whereptr = (uint8_t *)ip6h + pkt_len - remlen;
  7822 				whereptr = (uint8_t *)ip6h + pkt_len - remlen;
  7800 			}
  7823 			}
  7801 
  7824 
  7802 			fraghdr = (ip6_frag_t *)whereptr;
  7825 			fraghdr = (ip6_frag_t *)whereptr;
  7818 					freemsg(mp);
  7841 					freemsg(mp);
  7819 					return;
  7842 					return;
  7820 				}
  7843 				}
  7821 			}
  7844 			}
  7822 
  7845 
       
  7846 			/* Restore the flags */
       
  7847 			DB_CKSUMFLAGS(mp) = hck_flags;
       
  7848 
  7823 			mp = ip_rput_frag_v6(q, mp, ip6h, fraghdr,
  7849 			mp = ip_rput_frag_v6(q, mp, ip6h, fraghdr,
  7824 			    remlen - used, &prev_nexthdr_offset);
  7850 			    remlen - used, &prev_nexthdr_offset,
       
  7851 			    &reass_sum, &reass_hck_flags);
  7825 			if (mp == NULL) {
  7852 			if (mp == NULL) {
  7826 				/* Reassembly is still pending */
  7853 				/* Reassembly is still pending */
  7827 				return;
  7854 				return;
  7828 			}
  7855 			}
  7829 			/* The first mblk are the headers before the frag hdr */
  7856 			/* The first mblk are the headers before the frag hdr */
  8030 		    (flags|IP_FF_SEND_ICMP|IP_FF_IP6INFO), mctl_present,
  8057 		    (flags|IP_FF_SEND_ICMP|IP_FF_IP6INFO), mctl_present,
  8031 		    zoneid);
  8058 		    zoneid);
  8032 		return;
  8059 		return;
  8033 	}
  8060 	}
  8034 
  8061 
  8035 	if (!canputnext(connp->conn_upq)) {
  8062 	if (CONN_UDP_FLOWCTLD(connp)) {
  8036 		freemsg(first_mp);
  8063 		freemsg(first_mp);
  8037 		BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
  8064 		BUMP_MIB(ill->ill_ip6_mib, udpInOverflows);
  8038 		CONN_DEC_REF(connp);
  8065 		CONN_DEC_REF(connp);
  8039 		return;
  8066 		return;
  8040 	}
  8067 	}
  8060 	}
  8087 	}
  8061 
  8088 
  8062 	IP6_STAT(ip6_udp_fast_path);
  8089 	IP6_STAT(ip6_udp_fast_path);
  8063 	BUMP_MIB(ill->ill_ip6_mib, ipv6InReceives);
  8090 	BUMP_MIB(ill->ill_ip6_mib, ipv6InReceives);
  8064 	BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers);
  8091 	BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers);
  8065 	putnext(connp->conn_upq, mp);
  8092 
       
  8093 	/* Send it upstream */
       
  8094 	CONN_UDP_RECV(connp, mp);
  8066 
  8095 
  8067 	CONN_DEC_REF(connp);
  8096 	CONN_DEC_REF(connp);
  8068 	freemsg(hada_mp);
  8097 	freemsg(hada_mp);
  8069 	return;
  8098 	return;
  8070 
  8099 
  8084  * of the preceding header.  This is needed to patch the previous header's
  8113  * of the preceding header.  This is needed to patch the previous header's
  8085  * nexthdr field when reassembly completes.
  8114  * nexthdr field when reassembly completes.
  8086  */
  8115  */
  8087 static mblk_t *
  8116 static mblk_t *
  8088 ip_rput_frag_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h,
  8117 ip_rput_frag_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h,
  8089     ip6_frag_t *fraghdr, uint_t remlen, uint_t *prev_nexthdr_offset)
  8118     ip6_frag_t *fraghdr, uint_t remlen, uint_t *prev_nexthdr_offset,
       
  8119     uint32_t *cksum_val, uint16_t *cksum_flags)
  8090 {
  8120 {
  8091 	ill_t		*ill = (ill_t *)q->q_ptr;
  8121 	ill_t		*ill = (ill_t *)q->q_ptr;
  8092 	uint32_t	ident = ntohl(fraghdr->ip6f_ident);
  8122 	uint32_t	ident = ntohl(fraghdr->ip6f_ident);
  8093 	uint16_t	offset;
  8123 	uint16_t	offset;
  8094 	boolean_t	more_frags;
  8124 	boolean_t	more_frags;
  8105 	uint8_t		ecn_info = 0;
  8135 	uint8_t		ecn_info = 0;
  8106 	size_t		msg_len;
  8136 	size_t		msg_len;
  8107 	mblk_t		*tail_mp;
  8137 	mblk_t		*tail_mp;
  8108 	mblk_t		*t_mp;
  8138 	mblk_t		*t_mp;
  8109 	boolean_t	pruned = B_FALSE;
  8139 	boolean_t	pruned = B_FALSE;
       
  8140 	uint32_t	sum_val;
       
  8141 	uint16_t	sum_flags;
       
  8142 
       
  8143 
       
  8144 	if (cksum_val != NULL)
       
  8145 		*cksum_val = 0;
       
  8146 	if (cksum_flags != NULL)
       
  8147 		*cksum_flags = 0;
       
  8148 
       
  8149 	/*
       
  8150 	 * We utilize hardware computed checksum info only for UDP since
       
  8151 	 * IP fragmentation is a normal occurence for the protocol.  In
       
  8152 	 * addition, checksum offload support for IP fragments carrying
       
  8153 	 * UDP payload is commonly implemented across network adapters.
       
  8154 	 */
       
  8155 	ASSERT(ill != NULL);
       
  8156 	if (nexthdr == IPPROTO_UDP && dohwcksum && ILL_HCKSUM_CAPABLE(ill) &&
       
  8157 	    (DB_CKSUMFLAGS(mp) & (HCK_FULLCKSUM | HCK_PARTIALCKSUM))) {
       
  8158 		mblk_t *mp1 = mp->b_cont;
       
  8159 		int32_t len;
       
  8160 
       
  8161 		/* Record checksum information from the packet */
       
  8162 		sum_val = (uint32_t)DB_CKSUM16(mp);
       
  8163 		sum_flags = DB_CKSUMFLAGS(mp);
       
  8164 
       
  8165 		/* fragmented payload offset from beginning of mblk */
       
  8166 		offset = (uint16_t)((uchar_t *)&fraghdr[1] - mp->b_rptr);
       
  8167 
       
  8168 		if ((sum_flags & HCK_PARTIALCKSUM) &&
       
  8169 		    (mp1 == NULL || mp1->b_cont == NULL) &&
       
  8170 		    offset >= (uint16_t)DB_CKSUMSTART(mp) &&
       
  8171 		    ((len = offset - (uint16_t)DB_CKSUMSTART(mp)) & 1) == 0) {
       
  8172 			uint32_t adj;
       
  8173 			/*
       
  8174 			 * Partial checksum has been calculated by hardware
       
  8175 			 * and attached to the packet; in addition, any
       
  8176 			 * prepended extraneous data is even byte aligned.
       
  8177 			 * If any such data exists, we adjust the checksum;
       
  8178 			 * this would also handle any postpended data.
       
  8179 			 */
       
  8180 			IP_ADJCKSUM_PARTIAL(mp->b_rptr + DB_CKSUMSTART(mp),
       
  8181 			    mp, mp1, len, adj);
       
  8182 
       
  8183 			/* One's complement subtract extraneous checksum */
       
  8184 			if (adj >= sum_val)
       
  8185 				sum_val = ~(adj - sum_val) & 0xFFFF;
       
  8186 			else
       
  8187 				sum_val -= adj;
       
  8188 		}
       
  8189 	} else {
       
  8190 		sum_val = 0;
       
  8191 		sum_flags = 0;
       
  8192 	}
       
  8193 
       
  8194 	/* Clear hardware checksumming flag */
       
  8195 	DB_CKSUMFLAGS(mp) = 0;
  8110 
  8196 
  8111 	/*
  8197 	/*
  8112 	 * Note: Fragment offset in header is in 8-octet units.
  8198 	 * Note: Fragment offset in header is in 8-octet units.
  8113 	 * Clearing least significant 3 bits not only extracts
  8199 	 * Clearing least significant 3 bits not only extracts
  8114 	 * it but also gets it in units of octets.
  8200 	 * it but also gets it in units of octets.
  8157 
  8243 
  8158 	/*
  8244 	/*
  8159 	 * Drop the fragmented as early as possible, if
  8245 	 * Drop the fragmented as early as possible, if
  8160 	 * we don't have resource(s) to re-assemble.
  8246 	 * we don't have resource(s) to re-assemble.
  8161 	 */
  8247 	 */
  8162 
       
  8163 	if (ip_reass_queue_bytes == 0) {
  8248 	if (ip_reass_queue_bytes == 0) {
  8164 		freemsg(mp);
  8249 		freemsg(mp);
  8165 		return (NULL);
  8250 		return (NULL);
  8166 	}
  8251 	}
  8167 
  8252 
  8181 	 * IP ident field.  The ILL frag hash table was allocated
  8266 	 * IP ident field.  The ILL frag hash table was allocated
  8182 	 * as a timer block at the time the ILL was created.  Whenever
  8267 	 * as a timer block at the time the ILL was created.  Whenever
  8183 	 * there is anything on the reassembly queue, the timer will
  8268 	 * there is anything on the reassembly queue, the timer will
  8184 	 * be running.
  8269 	 * be running.
  8185 	 */
  8270 	 */
  8186 	msg_len = mp->b_datap->db_lim - mp->b_datap->db_base;
  8271 	msg_len = MBLKSIZE(mp);
  8187 	tail_mp = mp;
  8272 	tail_mp = mp;
  8188 	while (tail_mp->b_cont != NULL) {
  8273 	while (tail_mp->b_cont != NULL) {
  8189 		tail_mp = tail_mp->b_cont;
  8274 		tail_mp = tail_mp->b_cont;
  8190 		msg_len += tail_mp->b_datap->db_lim -
  8275 		msg_len += MBLKSIZE(tail_mp);
  8191 		    tail_mp->b_datap->db_base;
       
  8192 	}
  8276 	}
  8193 	/*
  8277 	/*
  8194 	 * If the reassembly list for this ILL will get too big
  8278 	 * If the reassembly list for this ILL will get too big
  8195 	 * prune it.
  8279 	 * prune it.
  8196 	 */
  8280 	 */
  8285 		ipf->ipf_v6dst = *v6dst_ptr;
  8369 		ipf->ipf_v6dst = *v6dst_ptr;
  8286 		/* Record reassembly start time. */
  8370 		/* Record reassembly start time. */
  8287 		ipf->ipf_timestamp = gethrestime_sec();
  8371 		ipf->ipf_timestamp = gethrestime_sec();
  8288 		/* Record ipf generation and account for frag header */
  8372 		/* Record ipf generation and account for frag header */
  8289 		ipf->ipf_gen = ill->ill_ipf_gen++;
  8373 		ipf->ipf_gen = ill->ill_ipf_gen++;
  8290 		ipf->ipf_count = mp1->b_datap->db_lim - mp1->b_datap->db_base;
  8374 		ipf->ipf_count = MBLKSIZE(mp1);
  8291 		ipf->ipf_protocol = nexthdr;
  8375 		ipf->ipf_protocol = nexthdr;
  8292 		ipf->ipf_nf_hdr_len = 0;
  8376 		ipf->ipf_nf_hdr_len = 0;
  8293 		ipf->ipf_prev_nexthdr_offset = 0;
  8377 		ipf->ipf_prev_nexthdr_offset = 0;
  8294 		ipf->ipf_last_frag_seen = B_FALSE;
  8378 		ipf->ipf_last_frag_seen = B_FALSE;
  8295 		ipf->ipf_ecn = ecn_info;
  8379 		ipf->ipf_ecn = ecn_info;
  8296 		ipf->ipf_num_dups = 0;
  8380 		ipf->ipf_num_dups = 0;
  8297 		ipfb->ipfb_frag_pkts++;
  8381 		ipfb->ipfb_frag_pkts++;
       
  8382 		ipf->ipf_checksum = 0;
       
  8383 		ipf->ipf_checksum_flags = 0;
       
  8384 
       
  8385 		/* Store checksum value in fragment header */
       
  8386 		if (sum_flags != 0) {
       
  8387 			sum_val = (sum_val & 0xFFFF) + (sum_val >> 16);
       
  8388 			sum_val = (sum_val & 0xFFFF) + (sum_val >> 16);
       
  8389 			ipf->ipf_checksum = sum_val;
       
  8390 			ipf->ipf_checksum_flags = sum_flags;
       
  8391 		}
  8298 
  8392 
  8299 		/*
  8393 		/*
  8300 		 * We handle reassembly two ways.  In the easy case,
  8394 		 * We handle reassembly two ways.  In the easy case,
  8301 		 * where all the fragments show up in order, we do
  8395 		 * where all the fragments show up in order, we do
  8302 		 * minimal bookkeeping, and just clip new pieces on
  8396 		 * minimal bookkeeping, and just clip new pieces on
  8324 			/*
  8418 			/*
  8325 			 * ipf_end == 0 means that we have given up
  8419 			 * ipf_end == 0 means that we have given up
  8326 			 * on easy reassembly.
  8420 			 * on easy reassembly.
  8327 			 */
  8421 			 */
  8328 			ipf->ipf_end = 0;
  8422 			ipf->ipf_end = 0;
       
  8423 
       
  8424 			/* Forget checksum offload from now on */
       
  8425 			ipf->ipf_checksum_flags = 0;
       
  8426 
  8329 			/*
  8427 			/*
  8330 			 * ipf_hole_cnt is set by ip_reassemble.
  8428 			 * ipf_hole_cnt is set by ip_reassemble.
  8331 			 * ipf_count is updated by ip_reassemble.
  8429 			 * ipf_count is updated by ip_reassemble.
  8332 			 * No need to check for return value here
  8430 			 * No need to check for return value here
  8333 			 * as we don't expect reassembly to complete or
  8431 			 * as we don't expect reassembly to complete or
  8344 		/* If the frag timer wasn't already going, start it. */
  8442 		/* If the frag timer wasn't already going, start it. */
  8345 		mutex_enter(&ill->ill_lock);
  8443 		mutex_enter(&ill->ill_lock);
  8346 		ill_frag_timer_start(ill);
  8444 		ill_frag_timer_start(ill);
  8347 		mutex_exit(&ill->ill_lock);
  8445 		mutex_exit(&ill->ill_lock);
  8348 		goto partial_reass_done;
  8446 		goto partial_reass_done;
       
  8447 	}
       
  8448 
       
  8449 	/*
       
  8450 	 * If the packet's flag has changed (it could be coming up
       
  8451 	 * from an interface different than the previous, therefore
       
  8452 	 * possibly different checksum capability), then forget about
       
  8453 	 * any stored checksum states.  Otherwise add the value to
       
  8454 	 * the existing one stored in the fragment header.
       
  8455 	 */
       
  8456 	if (sum_flags != 0 && sum_flags == ipf->ipf_checksum_flags) {
       
  8457 		sum_val += ipf->ipf_checksum;
       
  8458 		sum_val = (sum_val & 0xFFFF) + (sum_val >> 16);
       
  8459 		sum_val = (sum_val & 0xFFFF) + (sum_val >> 16);
       
  8460 		ipf->ipf_checksum = sum_val;
       
  8461 	} else if (ipf->ipf_checksum_flags != 0) {
       
  8462 		/* Forget checksum offload from now on */
       
  8463 		ipf->ipf_checksum_flags = 0;
  8349 	}
  8464 	}
  8350 
  8465 
  8351 	/*
  8466 	/*
  8352 	 * We have a new piece of a datagram which is already being
  8467 	 * We have a new piece of a datagram which is already being
  8353 	 * reassembled.  Update the ECN info if all IP fragments
  8468 	 * reassembled.  Update the ECN info if all IP fragments
  8441 	 * header
  8556 	 * header
  8442 	 */
  8557 	 */
  8443 	nexthdr = ipf->ipf_protocol;
  8558 	nexthdr = ipf->ipf_protocol;
  8444 	*prev_nexthdr_offset = ipf->ipf_prev_nexthdr_offset;
  8559 	*prev_nexthdr_offset = ipf->ipf_prev_nexthdr_offset;
  8445 	ipfp = ipf->ipf_ptphn;
  8560 	ipfp = ipf->ipf_ptphn;
       
  8561 
       
  8562 	/* We need to supply these to caller */
       
  8563 	if ((sum_flags = ipf->ipf_checksum_flags) != 0)
       
  8564 		sum_val = ipf->ipf_checksum;
       
  8565 	else
       
  8566 		sum_val = 0;
       
  8567 
  8446 	mp1 = ipf->ipf_mp;
  8568 	mp1 = ipf->ipf_mp;
  8447 	count = ipf->ipf_count;
  8569 	count = ipf->ipf_count;
  8448 	ipf = ipf->ipf_hash_next;
  8570 	ipf = ipf->ipf_hash_next;
  8449 	if (ipf)
  8571 	if (ipf)
  8450 		ipf->ipf_ptphn = ipfp;
  8572 		ipf->ipf_ptphn = ipfp;
  8505 	/* Restore original IP length in header. */
  8627 	/* Restore original IP length in header. */
  8506 	ip6h->ip6_plen = htons((uint16_t)(msgdsize(mp) - IPV6_HDR_LEN));
  8628 	ip6h->ip6_plen = htons((uint16_t)(msgdsize(mp) - IPV6_HDR_LEN));
  8507 	/* Record the ECN info. */
  8629 	/* Record the ECN info. */
  8508 	ip6h->ip6_vcf &= htonl(0xFFCFFFFF);
  8630 	ip6h->ip6_vcf &= htonl(0xFFCFFFFF);
  8509 	ip6h->ip6_vcf |= htonl(ecn_info << 20);
  8631 	ip6h->ip6_vcf |= htonl(ecn_info << 20);
       
  8632 
       
  8633 	/* Reassembly is successful; return checksum information if needed */
       
  8634 	if (cksum_val != NULL)
       
  8635 		*cksum_val = sum_val;
       
  8636 	if (cksum_flags != NULL)
       
  8637 		*cksum_flags = sum_flags;
  8510 
  8638 
  8511 	return (mp);
  8639 	return (mp);
  8512 }
  8640 }
  8513 
  8641 
  8514 /*
  8642 /*
  9952 	 * switch when ratio exceeds e.g. 10:1
 10080 	 * switch when ratio exceeds e.g. 10:1
  9953 	 */
 10081 	 */
  9954 	if (q->q_next == NULL) {
 10082 	if (q->q_next == NULL) {
  9955 		connp = Q_TO_CONN(q);
 10083 		connp = Q_TO_CONN(q);
  9956 
 10084 
  9957 		if (IS_TCP_CONN(connp)) {
 10085 		if (IPCL_IS_TCP(connp)) {
  9958 			/* change conn_send for the tcp_v4_connections */
 10086 			/* change conn_send for the tcp_v4_connections */
  9959 			connp->conn_send = ip_output;
 10087 			connp->conn_send = ip_output;
  9960 		} else if (connp->conn_ulp == IPPROTO_SCTP) {
 10088 		} else if (connp->conn_ulp == IPPROTO_SCTP) {
  9961 			/* The 'q' is the default SCTP queue */
 10089 			/* The 'q' is the default SCTP queue */
  9962 			connp = (conn_t *)arg;
 10090 			connp = (conn_t *)arg;
 10424 
 10552 
 10425 	if (ire->ire_stq != NULL) {
 10553 	if (ire->ire_stq != NULL) {
 10426 		uint32_t	sum;
 10554 		uint32_t	sum;
 10427 		uint_t		ill_index =  ((ill_t *)ire->ire_stq->q_ptr)->
 10555 		uint_t		ill_index =  ((ill_t *)ire->ire_stq->q_ptr)->
 10428 		    ill_phyint->phyint_ifindex;
 10556 		    ill_phyint->phyint_ifindex;
       
 10557 		queue_t		*dev_q = ire->ire_stq->q_next;
 10429 
 10558 
 10430 		/*
 10559 		/*
 10431 		 * non-NULL send-to queue - packet is to be sent
 10560 		 * non-NULL send-to queue - packet is to be sent
 10432 		 * out an interface.
 10561 		 * out an interface.
 10433 		 */
 10562 		 */
       
 10563 
       
 10564 		/* Driver is flow-controlling? */
       
 10565 		if (!IP_FLOW_CONTROLLED_ULP(nexthdr) &&
       
 10566 		    ((dev_q->q_next || dev_q->q_first) && !canput(dev_q))) {
       
 10567 			/*
       
 10568 			 * Queue packet if we have an conn to give back
       
 10569 			 * pressure.  We can't queue packets intended for
       
 10570 			 * hardware acceleration since we've tossed that
       
 10571 			 * state already.  If the packet is being fed back
       
 10572 			 * from ire_send_v6, we don't know the position in
       
 10573 			 * the queue to enqueue the packet and we discard
       
 10574 			 * the packet.
       
 10575 			 */
       
 10576 			ASSERT(mp == first_mp);
       
 10577 			if (ip_output_queue && connp != NULL &&
       
 10578 			    !mctl_present && caller != IRE_SEND) {
       
 10579 				if (caller == IP_WSRV) {
       
 10580 					connp->conn_did_putbq = 1;
       
 10581 					(void) putbq(connp->conn_wq, mp);
       
 10582 					conn_drain_insert(connp);
       
 10583 					/*
       
 10584 					 * caller == IP_WSRV implies we are
       
 10585 					 * the service thread, and the
       
 10586 					 * queue is already noenabled.
       
 10587 					 * The check for canput and
       
 10588 					 * the putbq is not atomic.
       
 10589 					 * So we need to check again.
       
 10590 					 */
       
 10591 					if (canput(dev_q))
       
 10592 						connp->conn_did_putbq = 0;
       
 10593 				} else {
       
 10594 					(void) putq(connp->conn_wq, mp);
       
 10595 				}
       
 10596 				return;
       
 10597 			}
       
 10598 			BUMP_MIB(mibptr, ipv6OutDiscards);
       
 10599 			freemsg(mp);
       
 10600 			return;
       
 10601 		}
 10434 
 10602 
 10435 		/*
 10603 		/*
 10436 		 * Look for reachability confirmations from the transport.
 10604 		 * Look for reachability confirmations from the transport.
 10437 		 */
 10605 		 */
 10438 		if (ip6h->ip6_vcf & IP_FORWARD_PROG) {
 10606 		if (ip6h->ip6_vcf & IP_FORWARD_PROG) {
 10488 			    up[4] + up[5] + up[6] + up[7] +
 10656 			    up[4] + up[5] + up[6] + up[7] +
 10489 			    up[8] + up[9] + up[10] + up[11] +
 10657 			    up[8] + up[9] + up[10] + up[11] +
 10490 			    up[12] + up[13] + up[14] + up[15];
 10658 			    up[12] + up[13] + up[14] + up[15];
 10491 			sum = (sum & 0xffff) + (sum >> 16);
 10659 			sum = (sum & 0xffff) + (sum >> 16);
 10492 			*insp = IP_CSUM(mp, hdr_length, sum);
 10660 			*insp = IP_CSUM(mp, hdr_length, sum);
       
 10661 			if (*insp == 0)
       
 10662 				*insp = 0xFFFF;
 10493 		} else if (nexthdr == IPPROTO_TCP) {
 10663 		} else if (nexthdr == IPPROTO_TCP) {
 10494 			uint16_t	*up;
 10664 			uint16_t	*up;
 10495 
 10665 
 10496 			/*
 10666 			/*
 10497 			 * Check for full IPv6 header + enough TCP header
 10667 			 * Check for full IPv6 header + enough TCP header
 10498 			 * to get at the checksum field.
 10668 			 * to get at the checksum field.
 10499 			 * XXX need hardware checksum support.
       
 10500 			 */
 10669 			 */
 10501 #define	TCP_CSUM_OFFSET	16
       
 10502 #define	TCP_CSUM_SIZE	2
       
 10503 			if ((mp->b_wptr - mp->b_rptr) <
 10670 			if ((mp->b_wptr - mp->b_rptr) <
 10504 			    (hdr_length + TCP_CSUM_OFFSET + TCP_CSUM_SIZE)) {
 10671 			    (hdr_length + TCP_CHECKSUM_OFFSET +
       
 10672 			    TCP_CHECKSUM_SIZE)) {
 10505 				if (!pullupmsg(mp, hdr_length +
 10673 				if (!pullupmsg(mp, hdr_length +
 10506 				    TCP_CSUM_OFFSET + TCP_CSUM_SIZE)) {
 10674 				    TCP_CHECKSUM_OFFSET + TCP_CHECKSUM_SIZE)) {
 10507 					ip1dbg(("ip_wput_v6: TCP hdr pullupmsg"
 10675 					ip1dbg(("ip_wput_v6: TCP hdr pullupmsg"
 10508 					    " failed\n"));
 10676 					    " failed\n"));
 10509 					BUMP_MIB(mibptr, ipv6OutDiscards);
 10677 					BUMP_MIB(mibptr, ipv6OutDiscards);
 10510 					freemsg(first_mp);
 10678 					freemsg(first_mp);
 10511 					return;
 10679 					return;
 10517 			/*
 10685 			/*
 10518 			 * Note: The TCP module has stored the length value
 10686 			 * Note: The TCP module has stored the length value
 10519 			 * into the tcp checksum field, so we don't
 10687 			 * into the tcp checksum field, so we don't
 10520 			 * need to explicitly sum it in here.
 10688 			 * need to explicitly sum it in here.
 10521 			 */
 10689 			 */
 10522 			if (hdr_length == IPV6_HDR_LEN) {
 10690 			sum = up[0] + up[1] + up[2] + up[3] +
 10523 				/* src, dst, tcp consequtive */
 10691 			    up[4] + up[5] + up[6] + up[7] +
 10524 				up = (uint16_t *)(((uchar_t *)ip6h) +
 10692 			    up[8] + up[9] + up[10] + up[11] +
 10525 				    IPV6_HDR_LEN + TCP_CSUM_OFFSET);
 10693 			    up[12] + up[13] + up[14] + up[15];
 10526 				*up = IP_CSUM(mp,
 10694 
 10527 				    IPV6_HDR_LEN - 2 * sizeof (in6_addr_t),
 10695 			/* Fold the initial sum */
 10528 				    htons(IPPROTO_TCP));
 10696 			sum = (sum & 0xffff) + (sum >> 16);
 10529 			} else {
 10697 
 10530 				sum = htons(IPPROTO_TCP) +
 10698 			up = (uint16_t *)(((uchar_t *)ip6h) +
 10531 				    up[0] + up[1] + up[2] + up[3] +
 10699 			    hdr_length + TCP_CHECKSUM_OFFSET);
 10532 				    up[4] + up[5] + up[6] + up[7] +
 10700 
 10533 				    up[8] + up[9] + up[10] + up[11] +
 10701 			IP_CKSUM_XMIT(ill, ire, mp, ip6h, up, IPPROTO_TCP,
 10534 				    up[12] + up[13] + up[14] + up[15];
 10702 			    hdr_length, ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN,
 10535 				/*
 10703 			    ire->ire_max_frag, mctl_present, sum);
 10536 				 * Fold the initial sum.
 10704 
 10537 				 */
 10705 			/* Software checksum? */
 10538 				sum = (sum & 0xffff) + (sum >> 16);
 10706 			if (DB_CKSUMFLAGS(mp) == 0) {
 10539 				up = (uint16_t *)(((uchar_t *)ip6h) +
 10707 				IP6_STAT(ip6_out_sw_cksum);
 10540 				    hdr_length + TCP_CSUM_OFFSET);
 10708 				IP6_STAT_UPDATE(ip6_tcp_out_sw_cksum_bytes,
 10541 				*up = IP_CSUM(mp, hdr_length, sum);
 10709 				    (ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN) -
 10542 			}
 10710 				    hdr_length);
 10543 #undef TCP_CSUM_OFFSET
 10711 			}
 10544 #undef TCP_CSUM_SIZE
       
 10545 
       
 10546 		} else if (nexthdr == IPPROTO_UDP) {
 10712 		} else if (nexthdr == IPPROTO_UDP) {
 10547 			uint16_t	*up;
 10713 			uint16_t	*up;
 10548 
 10714 
 10549 			/*
 10715 			/*
 10550 			 * check for full IPv6 header + enough UDP header
 10716 			 * check for full IPv6 header + enough UDP header
 10551 			 * to get at the UDP checksum field
 10717 			 * to get at the UDP checksum field
 10552 			 */
 10718 			 */
 10553 #define	UDP_CSUM_OFFSET	6
       
 10554 #define	UDP_CSUM_SIZE	2
       
 10555 			if ((mp->b_wptr - mp->b_rptr) < (hdr_length +
 10719 			if ((mp->b_wptr - mp->b_rptr) < (hdr_length +
 10556 			    UDP_CSUM_OFFSET + UDP_CSUM_SIZE)) {
 10720 			    UDP_CHECKSUM_OFFSET + UDP_CHECKSUM_SIZE)) {
 10557 				if (!pullupmsg(mp, hdr_length +
 10721 				if (!pullupmsg(mp, hdr_length +
 10558 				    UDP_CSUM_OFFSET + UDP_CSUM_SIZE)) {
 10722 				    UDP_CHECKSUM_OFFSET + UDP_CHECKSUM_SIZE)) {
 10559 					ip1dbg(("ip_wput_v6: UDP hdr pullupmsg"
 10723 					ip1dbg(("ip_wput_v6: UDP hdr pullupmsg"
 10560 					    " failed\n"));
 10724 					    " failed\n"));
 10561 					BUMP_MIB(mibptr, ipv6OutDiscards);
 10725 					BUMP_MIB(mibptr, ipv6OutDiscards);
 10562 					freemsg(first_mp);
 10726 					freemsg(first_mp);
 10563 					return;
 10727 					return;
 10568 			/*
 10732 			/*
 10569 			 * Note: The UDP module has stored the length value
 10733 			 * Note: The UDP module has stored the length value
 10570 			 * into the udp checksum field, so we don't
 10734 			 * into the udp checksum field, so we don't
 10571 			 * need to explicitly sum it in here.
 10735 			 * need to explicitly sum it in here.
 10572 			 */
 10736 			 */
 10573 			if (hdr_length == IPV6_HDR_LEN) {
 10737 			sum = up[0] + up[1] + up[2] + up[3] +
 10574 				/* src, dst, udp consequtive */
 10738 			    up[4] + up[5] + up[6] + up[7] +
 10575 				up = (uint16_t *)(((uchar_t *)ip6h) +
 10739 			    up[8] + up[9] + up[10] + up[11] +
 10576 				    IPV6_HDR_LEN + UDP_CSUM_OFFSET);
 10740 			    up[12] + up[13] + up[14] + up[15];
 10577 				*up = IP_CSUM(mp,
 10741 
 10578 				    IPV6_HDR_LEN - 2 * sizeof (in6_addr_t),
 10742 			/* Fold the initial sum */
 10579 				    htons(IPPROTO_UDP));
 10743 			sum = (sum & 0xffff) + (sum >> 16);
 10580 			} else {
 10744 
 10581 				sum = htons(IPPROTO_UDP) +
 10745 			up = (uint16_t *)(((uchar_t *)ip6h) +
 10582 				    up[0] + up[1] + up[2] + up[3] +
 10746 			    hdr_length + UDP_CHECKSUM_OFFSET);
 10583 				    up[4] + up[5] + up[6] + up[7] +
 10747 
 10584 				    up[8] + up[9] + up[10] + up[11] +
 10748 			IP_CKSUM_XMIT(ill, ire, mp, ip6h, up, IPPROTO_UDP,
 10585 				    up[12] + up[13] + up[14] + up[15];
 10749 			    hdr_length, ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN,
 10586 				sum = (sum & 0xffff) + (sum >> 16);
 10750 			    ire->ire_max_frag, mctl_present, sum);
 10587 				up = (uint16_t *)(((uchar_t *)ip6h) +
 10751 
 10588 				    hdr_length + UDP_CSUM_OFFSET);
 10752 			/* Software checksum? */
 10589 				*up = IP_CSUM(mp, hdr_length, sum);
 10753 			if (DB_CKSUMFLAGS(mp) == 0) {
 10590 			}
 10754 				IP6_STAT(ip6_out_sw_cksum);
 10591 
 10755 				IP6_STAT_UPDATE(ip6_udp_out_sw_cksum_bytes,
 10592 			/*
 10756 				    (ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN) -
 10593 			 * According to RFC 2460, UDP in IPv6 shouldn't
 10757 				    hdr_length);
 10594 			 * appear with all zero checksum on the wire and
 10758 			}
 10595 			 * should be changed to 0xffff.
       
 10596 			 */
       
 10597 			if (*up == 0)
       
 10598 				*up = 0xffff;
       
 10599 #undef UDP_CSUM_OFFSET
       
 10600 #undef UDP_CSUM_SIZE
       
 10601 		} else if (nexthdr == IPPROTO_ICMPV6) {
 10759 		} else if (nexthdr == IPPROTO_ICMPV6) {
 10602 			uint16_t	*up;
 10760 			uint16_t	*up;
 10603 			icmp6_t *icmp6;
 10761 			icmp6_t *icmp6;
 10604 
 10762 
 10605 			/* check for full IPv6+ICMPv6 header */
 10763 			/* check for full IPv6+ICMPv6 header */
 10625 			    up[4] + up[5] + up[6] + up[7] +
 10783 			    up[4] + up[5] + up[6] + up[7] +
 10626 			    up[8] + up[9] + up[10] + up[11] +
 10784 			    up[8] + up[9] + up[10] + up[11] +
 10627 			    up[12] + up[13] + up[14] + up[15];
 10785 			    up[12] + up[13] + up[14] + up[15];
 10628 			sum = (sum & 0xffff) + (sum >> 16);
 10786 			sum = (sum & 0xffff) + (sum >> 16);
 10629 			icmp6->icmp6_cksum = IP_CSUM(mp, hdr_length, sum);
 10787 			icmp6->icmp6_cksum = IP_CSUM(mp, hdr_length, sum);
       
 10788 			if (icmp6->icmp6_cksum == 0)
       
 10789 				icmp6->icmp6_cksum = 0xFFFF;
       
 10790 
 10630 			/* Update output mib stats */
 10791 			/* Update output mib stats */
 10631 			icmp_update_out_mib_v6(ill, icmp6);
 10792 			icmp_update_out_mib_v6(ill, icmp6);
 10632 		} else if (nexthdr == IPPROTO_SCTP) {
 10793 		} else if (nexthdr == IPPROTO_SCTP) {
 10633 			sctp_hdr_t *sctph;
 10794 			sctp_hdr_t *sctph;
 10634 
 10795 
 10762 		ip_wput_local_v6(RD(q), ill, ip6h, first_mp, ire, 0);
 10923 		ip_wput_local_v6(RD(q), ill, ip6h, first_mp, ire, 0);
 10763 	}
 10924 	}
 10764 }
 10925 }
 10765 
 10926 
 10766 /*
 10927 /*
       
 10928  * Outbound IPv6 fragmentation routine using MDT.
       
 10929  */
       
 10930 static void
       
 10931 ip_wput_frag_mdt_v6(mblk_t *mp, ire_t *ire, size_t max_chunk,
       
 10932     size_t unfragmentable_len, uint8_t nexthdr, uint_t prev_nexthdr_offset)
       
 10933 {
       
 10934 	ip6_t		*ip6h = (ip6_t *)mp->b_rptr;
       
 10935 	uint_t		pkts, wroff, hdr_chunk_len, pbuf_idx;
       
 10936 	mblk_t		*hdr_mp, *md_mp = NULL;
       
 10937 	int		i1;
       
 10938 	multidata_t	*mmd;
       
 10939 	unsigned char	*hdr_ptr, *pld_ptr;
       
 10940 	ip_pdescinfo_t	pdi;
       
 10941 	uint32_t	ident;
       
 10942 	size_t		len;
       
 10943 	uint16_t	offset;
       
 10944 	queue_t		*stq = ire->ire_stq;
       
 10945 	ill_t		*ill = (ill_t *)stq->q_ptr;
       
 10946 
       
 10947 	ASSERT(DB_TYPE(mp) == M_DATA);
       
 10948 	ASSERT(MBLKL(mp) > unfragmentable_len);
       
 10949 
       
 10950 	/*
       
 10951 	 * Move read ptr past unfragmentable portion, we don't want this part
       
 10952 	 * of the data in our fragments.
       
 10953 	 */
       
 10954 	mp->b_rptr += unfragmentable_len;
       
 10955 
       
 10956 	/* Calculate how many packets we will send out  */
       
 10957 	i1 = (mp->b_cont == NULL) ? MBLKL(mp) : msgsize(mp);
       
 10958 	pkts = (i1 + max_chunk - 1) / max_chunk;
       
 10959 	ASSERT(pkts > 1);
       
 10960 
       
 10961 	/* Allocate a message block which will hold all the IP Headers. */
       
 10962 	wroff = ip_wroff_extra;
       
 10963 	hdr_chunk_len = wroff + unfragmentable_len + sizeof (ip6_frag_t);
       
 10964 
       
 10965 	i1 = pkts * hdr_chunk_len;
       
 10966 	/*
       
 10967 	 * Create the header buffer, Multidata and destination address
       
 10968 	 * and SAP attribute that should be associated with it.
       
 10969 	 */
       
 10970 	if ((hdr_mp = allocb(i1, BPRI_HI)) == NULL ||
       
 10971 	    ((hdr_mp->b_wptr += i1),
       
 10972 	    (mmd = mmd_alloc(hdr_mp, &md_mp, KM_NOSLEEP)) == NULL) ||
       
 10973 	    !ip_md_addr_attr(mmd, NULL, ire->ire_nce->nce_res_mp)) {
       
 10974 		freemsg(mp);
       
 10975 		if (md_mp == NULL) {
       
 10976 			freemsg(hdr_mp);
       
 10977 		} else {
       
 10978 free_mmd:		IP6_STAT(ip6_frag_mdt_discarded);
       
 10979 			freemsg(md_mp);
       
 10980 		}
       
 10981 		IP6_STAT(ip6_frag_mdt_allocfail);
       
 10982 		BUMP_MIB(ill->ill_ip6_mib, ipv6OutFragFails);
       
 10983 		UPDATE_MIB(ill->ill_ip6_mib, ipv6OutDiscards, pkts);
       
 10984 		return;
       
 10985 	}
       
 10986 	IP6_STAT(ip6_frag_mdt_allocd);
       
 10987 
       
 10988 	/*
       
 10989 	 * Add a payload buffer to the Multidata; this operation must not
       
 10990 	 * fail, or otherwise our logic in this routine is broken.  There
       
 10991 	 * is no memory allocation done by the routine, so any returned
       
 10992 	 * failure simply tells us that we've done something wrong.
       
 10993 	 *
       
 10994 	 * A failure tells us that either we're adding the same payload
       
 10995 	 * buffer more than once, or we're trying to add more buffers than
       
 10996 	 * allowed.  None of the above cases should happen, and we panic
       
 10997 	 * because either there's horrible heap corruption, and/or
       
 10998 	 * programming mistake.
       
 10999 	 */
       
 11000 	if ((pbuf_idx = mmd_addpldbuf(mmd, mp)) < 0) {
       
 11001 		goto pbuf_panic;
       
 11002 	}
       
 11003 
       
 11004 	hdr_ptr = hdr_mp->b_rptr;
       
 11005 	pld_ptr = mp->b_rptr;
       
 11006 
       
 11007 	pdi.flags = PDESC_HBUF_REF | PDESC_PBUF_REF;
       
 11008 
       
 11009 	ident = htonl(atomic_add_32_nv(&ire->ire_ident, 1));
       
 11010 
       
 11011 	/*
       
 11012 	 * len is the total length of the fragmentable data in this
       
 11013 	 * datagram.  For each fragment sent, we will decrement len
       
 11014 	 * by the amount of fragmentable data sent in that fragment
       
 11015 	 * until len reaches zero.
       
 11016 	 */
       
 11017 	len = ntohs(ip6h->ip6_plen) - (unfragmentable_len - IPV6_HDR_LEN);
       
 11018 
       
 11019 	offset = 0;
       
 11020 	prev_nexthdr_offset += wroff;
       
 11021 
       
 11022 	while (len != 0) {
       
 11023 		size_t		mlen;
       
 11024 		ip6_t		*fip6h;
       
 11025 		ip6_frag_t	*fraghdr;
       
 11026 		int		error;
       
 11027 
       
 11028 		ASSERT((hdr_ptr + hdr_chunk_len) <= hdr_mp->b_wptr);
       
 11029 		mlen = MIN(len, max_chunk);
       
 11030 		len -= mlen;
       
 11031 
       
 11032 		fip6h = (ip6_t *)(hdr_ptr + wroff);
       
 11033 		ASSERT(OK_32PTR(fip6h));
       
 11034 		bcopy(ip6h, fip6h, unfragmentable_len);
       
 11035 		hdr_ptr[prev_nexthdr_offset] = IPPROTO_FRAGMENT;
       
 11036 
       
 11037 		fip6h->ip6_plen = htons((uint16_t)(mlen +
       
 11038 		    unfragmentable_len - IPV6_HDR_LEN + sizeof (ip6_frag_t)));
       
 11039 
       
 11040 		fraghdr = (ip6_frag_t *)((unsigned char *)fip6h +
       
 11041 		    unfragmentable_len);
       
 11042 		fraghdr->ip6f_nxt = nexthdr;
       
 11043 		fraghdr->ip6f_reserved = 0;
       
 11044 		fraghdr->ip6f_offlg = htons(offset) |
       
 11045 		    ((len != 0) ? IP6F_MORE_FRAG : 0);
       
 11046 		fraghdr->ip6f_ident = ident;
       
 11047 
       
 11048 		/*
       
 11049 		 * Record offset and size of header and data of the next packet
       
 11050 		 * in the multidata message.
       
 11051 		 */
       
 11052 		PDESC_HDR_ADD(&pdi, hdr_ptr, wroff,
       
 11053 		    unfragmentable_len + sizeof (ip6_frag_t), 0);
       
 11054 		PDESC_PLD_INIT(&pdi);
       
 11055 		i1 = MIN(mp->b_wptr - pld_ptr, mlen);
       
 11056 		ASSERT(i1 > 0);
       
 11057 		PDESC_PLD_SPAN_ADD(&pdi, pbuf_idx, pld_ptr, i1);
       
 11058 		if (i1 == mlen) {
       
 11059 			pld_ptr += mlen;
       
 11060 		} else {
       
 11061 			i1 = mlen - i1;
       
 11062 			mp = mp->b_cont;
       
 11063 			ASSERT(mp != NULL);
       
 11064 			ASSERT(MBLKL(mp) >= i1);
       
 11065 			/*
       
 11066 			 * Attach the next payload message block to the
       
 11067 			 * multidata message.
       
 11068 			 */
       
 11069 			if ((pbuf_idx = mmd_addpldbuf(mmd, mp)) < 0)
       
 11070 				goto pbuf_panic;
       
 11071 			PDESC_PLD_SPAN_ADD(&pdi, pbuf_idx, mp->b_rptr, i1);
       
 11072 			pld_ptr = mp->b_rptr + i1;
       
 11073 		}
       
 11074 
       
 11075 		if ((mmd_addpdesc(mmd, (pdescinfo_t *)&pdi, &error,
       
 11076 		    KM_NOSLEEP)) == NULL) {
       
 11077 			/*
       
 11078 			 * Any failure other than ENOMEM indicates that we
       
 11079 			 * have passed in invalid pdesc info or parameters
       
 11080 			 * to mmd_addpdesc, which must not happen.
       
 11081 			 *
       
 11082 			 * EINVAL is a result of failure on boundary checks
       
 11083 			 * against the pdesc info contents.  It should not
       
 11084 			 * happen, and we panic because either there's
       
 11085 			 * horrible heap corruption, and/or programming
       
 11086 			 * mistake.
       
 11087 			 */
       
 11088 			if (error != ENOMEM) {
       
 11089 				cmn_err(CE_PANIC, "ip_wput_frag_mdt_v6: "
       
 11090 				    "pdesc logic error detected for "
       
 11091 				    "mmd %p pinfo %p (%d)\n",
       
 11092 				    (void *)mmd, (void *)&pdi, error);
       
 11093 				/* NOTREACHED */
       
 11094 			}
       
 11095 			IP6_STAT(ip6_frag_mdt_addpdescfail);
       
 11096 			/* Free unattached payload message blocks as well */
       
 11097 			md_mp->b_cont = mp->b_cont;
       
 11098 			goto free_mmd;
       
 11099 		}
       
 11100 
       
 11101 		/* Advance fragment offset. */
       
 11102 		offset += mlen;
       
 11103 
       
 11104 		/* Advance to location for next header in the buffer. */
       
 11105 		hdr_ptr += hdr_chunk_len;
       
 11106 
       
 11107 		/* Did we reach the next payload message block? */
       
 11108 		if (pld_ptr == mp->b_wptr && mp->b_cont != NULL) {
       
 11109 			mp = mp->b_cont;
       
 11110 			/*
       
 11111 			 * Attach the next message block with payload
       
 11112 			 * data to the multidata message.
       
 11113 			 */
       
 11114 			if ((pbuf_idx = mmd_addpldbuf(mmd, mp)) < 0)
       
 11115 				goto pbuf_panic;
       
 11116 			pld_ptr = mp->b_rptr;
       
 11117 		}
       
 11118 	}
       
 11119 
       
 11120 	ASSERT(hdr_mp->b_wptr == hdr_ptr);
       
 11121 	ASSERT(mp->b_wptr == pld_ptr);
       
 11122 
       
 11123 	/* Update IP statistics */
       
 11124 	UPDATE_MIB(ill->ill_ip6_mib, ipv6OutFragCreates, pkts);
       
 11125 	BUMP_MIB(ill->ill_ip6_mib, ipv6OutFragOKs);
       
 11126 	IP6_STAT_UPDATE(ip6_frag_mdt_pkt_out, pkts);
       
 11127 
       
 11128 	ire->ire_ob_pkt_count += pkts;
       
 11129 	if (ire->ire_ipif != NULL)
       
 11130 		atomic_add_32(&ire->ire_ipif->ipif_ob_pkt_count, pkts);
       
 11131 
       
 11132 	ire->ire_last_used_time = lbolt;
       
 11133 	/* Send it down */
       
 11134 	putnext(stq, md_mp);
       
 11135 	return;
       
 11136 
       
 11137 pbuf_panic:
       
 11138 	cmn_err(CE_PANIC, "ip_wput_frag_mdt_v6: payload buffer logic "
       
 11139 	    "error for mmd %p pbuf %p (%d)", (void *)mmd, (void *)mp,
       
 11140 	    pbuf_idx);
       
 11141 	/* NOTREACHED */
       
 11142 }
       
 11143 
       
 11144 /*
 10767  * IPv6 fragmentation.  Essentially the same as IPv4 fragmentation.
 11145  * IPv6 fragmentation.  Essentially the same as IPv4 fragmentation.
 10768  * We have not optimized this in terms of number of mblks
 11146  * We have not optimized this in terms of number of mblks
 10769  * allocated. For instance, for each fragment sent we always allocate a
 11147  * allocated. For instance, for each fragment sent we always allocate a
 10770  * mblk to hold the IPv6 header and fragment header.
 11148  * mblk to hold the IPv6 header and fragment header.
 10771  *
 11149  *
 10777  * NOTE : This function does not ire_refrele the ire passed in as
 11155  * NOTE : This function does not ire_refrele the ire passed in as
 10778  * the argument.
 11156  * the argument.
 10779  */
 11157  */
 10780 void
 11158 void
 10781 ip_wput_frag_v6(mblk_t *mp, ire_t *ire, uint_t reachable, conn_t *connp,
 11159 ip_wput_frag_v6(mblk_t *mp, ire_t *ire, uint_t reachable, conn_t *connp,
 10782     boolean_t caller, int max_frag)
 11160     int caller, int max_frag)
 10783 {
 11161 {
 10784 	ip6_t		*ip6h = (ip6_t *)mp->b_rptr;
 11162 	ip6_t		*ip6h = (ip6_t *)mp->b_rptr;
 10785 	ip6_t		*fip6h;
 11163 	ip6_t		*fip6h;
 10786 	mblk_t		*hmp;
 11164 	mblk_t		*hmp;
 10787 	mblk_t		*hmp0;
 11165 	mblk_t		*hmp0;
 10847 		hdr_len = 8 * (rthdr->ip6r_len + 1);
 11225 		hdr_len = 8 * (rthdr->ip6r_len + 1);
 10848 		ptr += hdr_len;
 11226 		ptr += hdr_len;
 10849 	}
 11227 	}
 10850 	unfragmentable_len = (uint_t)(ptr - (uint8_t *)ip6h);
 11228 	unfragmentable_len = (uint_t)(ptr - (uint8_t *)ip6h);
 10851 
 11229 
       
 11230 	max_chunk = (min(max_frag, ire->ire_max_frag) - unfragmentable_len -
       
 11231 	    sizeof (ip6_frag_t)) & ~7;
       
 11232 
       
 11233 	/* Check if we can use MDT to send out the frags. */
       
 11234 	ASSERT(!IRE_IS_LOCAL(ire));
       
 11235 	if (ip_multidata_outbound && reachable == 0 &&
       
 11236 	    !(ire->ire_flags & RTF_MULTIRT) && ILL_MDT_CAPABLE(ill) &&
       
 11237 	    IP_CAN_FRAG_MDT(mp, unfragmentable_len, max_chunk)) {
       
 11238 		ip_wput_frag_mdt_v6(mp, ire, max_chunk, unfragmentable_len,
       
 11239 		    nexthdr, prev_nexthdr_offset);
       
 11240 		return;
       
 11241 	}
       
 11242 
 10852 	/*
 11243 	/*
 10853 	 * Allocate an mblk with enough room for the link-layer
 11244 	 * Allocate an mblk with enough room for the link-layer
 10854 	 * header, the unfragmentable part of the datagram, and the
 11245 	 * header, the unfragmentable part of the datagram, and the
 10855 	 * fragment header.  This (or a copy) will be used as the
 11246 	 * fragment header.  This (or a copy) will be used as the
 10856 	 * first mblk for each fragment we send.
 11247 	 * first mblk for each fragment we send.
 10873 
 11264 
 10874 	ident = atomic_add_32_nv(&ire->ire_ident, 1);
 11265 	ident = atomic_add_32_nv(&ire->ire_ident, 1);
 10875 
 11266 
 10876 	fraghdr->ip6f_nxt = nexthdr;
 11267 	fraghdr->ip6f_nxt = nexthdr;
 10877 	fraghdr->ip6f_reserved = 0;
 11268 	fraghdr->ip6f_reserved = 0;
 10878 	fraghdr->ip6f_offlg = htons(0);
 11269 	fraghdr->ip6f_offlg = 0;
 10879 	fraghdr->ip6f_ident = htonl(ident);
 11270 	fraghdr->ip6f_ident = htonl(ident);
 10880 
 11271 
 10881 	/*
 11272 	/*
 10882 	 * len is the total length of the fragmentable data in this
 11273 	 * len is the total length of the fragmentable data in this
 10883 	 * datagram.  For each fragment sent, we will decrement len
 11274 	 * datagram.  For each fragment sent, we will decrement len
 10884 	 * by the amount of fragmentable data sent in that fragment
 11275 	 * by the amount of fragmentable data sent in that fragment
 10885 	 * until len reaches zero.
 11276 	 * until len reaches zero.
 10886 	 */
 11277 	 */
 10887 	len = ntohs(ip6h->ip6_plen) - (unfragmentable_len - IPV6_HDR_LEN);
 11278 	len = ntohs(ip6h->ip6_plen) - (unfragmentable_len - IPV6_HDR_LEN);
 10888 
       
 10889 	max_chunk = (min(max_frag, ire->ire_max_frag) - unfragmentable_len -
       
 10890 	    sizeof (ip6_frag_t)) & ~7;
       
 10891 
 11279 
 10892 	/*
 11280 	/*
 10893 	 * Move read ptr past unfragmentable portion, we don't want this part
 11281 	 * Move read ptr past unfragmentable portion, we don't want this part
 10894 	 * of the data in our fragments.
 11282 	 * of the data in our fragments.
 10895 	 */
 11283 	 */
 11115 			freemsg(mp);
 11503 			freemsg(mp);
 11116 			return;
 11504 			return;
 11117 		}
 11505 		}
 11118 	}
 11506 	}
 11119 
 11507 
 11120 	if (IP_FLOW_CONTROLLED_ULP(ip6h->ip6_nxt) || canput(stq->q_next)) {
 11508 	/* Flow-control check has been done in ip_wput_ire_v6 */
       
 11509 	if (IP_FLOW_CONTROLLED_ULP(ip6h->ip6_nxt) || caller == IP_WPUT ||
       
 11510 	    caller == IP_WSRV || canput(stq->q_next)) {
 11121 		uint32_t ill_index;
 11511 		uint32_t ill_index;
 11122 
 11512 
 11123 		/*
 11513 		/*
 11124 		 * In most cases, the emission loop below is entered only
 11514 		 * In most cases, the emission loop below is entered only
 11125 		 * once. Only in the case where the ire holds the
 11515 		 * once. Only in the case where the ire holds the
 11162 				nce = ire->ire_nce;
 11552 				nce = ire->ire_nce;
 11163 				stq = ire->ire_stq;
 11553 				stq = ire->ire_stq;
 11164 				ill = ire_to_ill(ire);
 11554 				ill = ire_to_ill(ire);
 11165 			}
 11555 			}
 11166 			IRB_REFRELE(irb);
 11556 			IRB_REFRELE(irb);
 11167 		} else if (connp != NULL && IS_TCP_CONN(connp) &&
 11557 		} else if (connp != NULL && IPCL_IS_TCP(connp) &&
 11168 		    connp->conn_mdt_ok && !connp->conn_tcp->tcp_mdt &&
 11558 		    connp->conn_mdt_ok && !connp->conn_tcp->tcp_mdt &&
 11169 		    ILL_MDT_USABLE(ill)) {
 11559 		    ILL_MDT_USABLE(ill)) {
 11170 			/*
 11560 			/*
 11171 			 * This tcp connection was marked as MDT-capable, but
 11561 			 * This tcp connection was marked as MDT-capable, but
 11172 			 * it has been turned off due changes in the interface.
 11562 			 * it has been turned off due changes in the interface.
 11581 			if (caller == IP_WSRV) {
 11971 			if (caller == IP_WSRV) {
 11582 				connp->conn_did_putbq = 1;
 11972 				connp->conn_did_putbq = 1;
 11583 				(void) putbq(connp->conn_wq, mp);
 11973 				(void) putbq(connp->conn_wq, mp);
 11584 				conn_drain_insert(connp);
 11974 				conn_drain_insert(connp);
 11585 				/*
 11975 				/*
 11586 				 * called_from_wsrv implies we are
 11976 				 * caller == IP_WSRV implies we are
 11587 				 * the service thread, and the
 11977 				 * the service thread, and the
 11588 				 * queue is already noenabled.
 11978 				 * queue is already noenabled.
 11589 				 * The check for canput and
 11979 				 * The check for canput and
 11590 				 * the putbq is not atomic.
 11980 				 * the putbq is not atomic.
 11591 				 * So we need to check again.
 11981 				 * So we need to check again.