--- old/exception_lists/packaging	2012-08-18 10:36:54.804005109 +0000
+++ new/exception_lists/packaging	2012-08-18 10:36:54.862680913 +0000
@@ -145,6 +145,7 @@
 usr/lib/amd64/llib-lipsecutil.ln	i386
 usr/lib/sparcv9/llib-lipsecutil.ln	sparc
 #
+usr/include/inet/dccp_impl.h
 usr/include/inet/ip_impl.h
 usr/include/inet/ip_ndp.h
 usr/include/inet/ip2mac_impl.h
--- old/usr/src/cmd/cmd-inet/etc/sock2path.d/system%2Fkernel	2012-08-18 10:36:55.403356041 +0000
+++ new/usr/src/cmd/cmd-inet/etc/sock2path.d/system%2Fkernel	2012-08-18 10:36:55.454975507 +0000
@@ -52,3 +52,5 @@
 	29	4	1	/dev/spdsock
 
 	31	1	0	trill
+
+	2	6	33	dccp
--- old/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c	2012-08-18 10:36:55.854250712 +0000
+++ new/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c	2012-08-18 10:36:55.900569885 +0000
@@ -193,6 +193,8 @@
 static void		udp_report(const mib_item_t *item);
 static void		group_report(mib_item_t *item);
 static void		dce_report(mib_item_t *item);
+static void		sctp_report(const mib_item_t *item);
+static void		dccp_report(const mib_item_t *item);
 static void		print_ip_stats(mib2_ip_t *ip);
 static void		print_icmp_stats(mib2_icmp_t *icmp);
 static void		print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6);
@@ -203,7 +205,7 @@
 static void		print_rawip_stats(mib2_rawip_t *rawip);
 static void		print_igmp_stats(struct igmpstat *igps);
 static void		print_mrt_stats(struct mrtstat *mrts);
-static void		sctp_report(const mib_item_t *item);
+static void		print_dccp_stats(mib2_dccp_t *dccp);
 static void		sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6,
 			    mib2_ipv6IfStatsEntry_t *sum6);
 static void		sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6,
@@ -284,6 +286,8 @@
 static int sctpEntrySize;
 static int sctpLocalEntrySize;
 static int sctpRemoteEntrySize;
+static int dccpEntrySize;
+static int dccp6EntrySize;
 
 #define	protocol_selected(p)	(proto == IPPROTO_MAX || proto == (p))
 
@@ -477,6 +481,8 @@
 			} else if (strcmp(optarg, "raw") == 0 ||
 			    strcmp(optarg, "rawip") == 0) {
 				proto = IPPROTO_RAW;
+			} else if (strcmp(optarg, "dccp") == 0) {
+				proto = IPPROTO_DCCP;
 			} else {
 				fatal(1, "%s: unknown protocol.\n", optarg);
 			}
@@ -622,6 +628,8 @@
 					tcp_report(item);
 				if (protocol_selected(IPPROTO_SCTP))
 					sctp_report(item);
+				if (protocol_selected(IPPROTO_DCCP))
+					dccp_report(item);
 			}
 			if (Iflag)
 				if_report(item, ifname, Iflag_only, once_only);
@@ -1006,6 +1014,7 @@
 			case MIB2_UDP:
 			case MIB2_SCTP:
 			case EXPER_RAWIP:
+			case MIB2_DCCP:
 				nitems++;
 			}
 	}
@@ -1452,6 +1461,10 @@
 				prevp = diffptr++;
 				break;
 			}
+			case MIB2_DCCP: {
+				/* XXX:DCCP */
+				break;
+			}
 			case EXPER_RAWIP: {
 				mib2_rawip_t *r2;
 				mib2_rawip_t *r1;
@@ -1861,6 +1874,17 @@
 			sctpRemoteEntrySize = sctp->sctpRemoteEntrySize;
 			break;
 		}
+		case MIB2_DCCP: {
+			mib2_dccp_t	*dccp = (mib2_dccp_t *)item->valp;
+
+			dccpEntrySize = dccp->dccpConnTableSize;
+			dccp6EntrySize = dccp->dccp6ConnTableSize;
+			assert(IS_P2ALIGNED(dccpEntrySize,
+			    sizeof (mib2_dccpConnEntry_t *)));
+			assert(IS_P2ALIGNED(dccp6EntrySize,
+			    sizeof (mib2_dccp6ConnEntry_t *)));
+			break;
+		}
 		}
 	} /* 'for' loop 1 ends */
 
@@ -1896,6 +1920,8 @@
 		(void) printf("\tsctpLocalEntrySize %d\n", sctpLocalEntrySize);
 		(void) printf("\tsctpRemoteEntrySize %d\n",
 		    sctpRemoteEntrySize);
+		(void) printf("\tdccpEntrySize %d\n", dccpEntrySize);
+		(void) printf("\ttcp6EntrySize %d\n", dccp6EntrySize);
 	}
 }
 
@@ -5431,6 +5457,133 @@
 		free(attrs);
 }
 
+/* ------------------------------ DCCP_REPORT------------------------------- */
+
+static const char dccp_hdr_v4[] =
+"\nDCCP: IPv4\n";
+static const char dccp_hdr_v4_compat[] =
+"\nDCCP\n";
+static const char dccp_hdr_v4_verbose[] =
+"Local/Remote Address Swind  Snext     Suna   Rwind  Rnext     Rack   "
+" Rto   Mss     State\n"
+"-------------------- ----- -------- -------- ----- -------- -------- "
+"----- ----- -----------\n";
+static const char dccp_hdr_v4_normal[] =
+"   Local Address        Remote Address    Swind Send-Q Rwind Recv-Q "
+"   State\n"
+"-------------------- -------------------- ----- ------ ----- ------ "
+"-----------\n";
+
+static const char dccp_hdr_v6[] =
+"\nDCCP: IPv6\n";
+static const char dccp_hdr_v6_verbose[] =
+"Local/Remote Address              Swind  Snext     Suna   Rwind  Rnext   "
+"  Rack    Rto   Mss    State      If\n"
+"--------------------------------- ----- -------- -------- ----- -------- "
+"-------- ----- ----- ----------- -----\n";
+static const char dccp_hdr_v6_normal[] =
+"   Local Address                     Remote Address                 "
+"Swind Send-Q Rwind Recv-Q   State      If\n"
+"--------------------------------- --------------------------------- "
+"----- ------ ----- ------ ----------- -----\n";
+
+static boolean_t dccp_report_item_v4(const mib2_dccpConnEntry_t *,
+    boolean_t, const mib2_transportMLPEntry_t *);
+static boolean_t dccp_report_item_v6(const mib2_dccp6ConnEntry_t *,
+    boolean_t, const mib2_transportMLPEntry_t *);
+
+static void
+dccp_report(const mib_item_t *item)
+{
+	mib2_dccpConnEntry_t		*dp;
+	mib2_transportMLPEntry_t	**v4_attrs;
+	mib2_transportMLPEntry_t	**v6_attrs;
+	mib2_transportMLPEntry_t	**v4a;
+	mib2_transportMLPEntry_t	**v6a;
+	mib2_transportMLPEntry_t	*aptr;
+	boolean_t			print_hdr_once_v4 = B_TRUE;
+	boolean_t			print_hdr_once_v6 = B_TRUE;
+	int				jtemp = 0;
+
+	if (!protocol_selected(IPPROTO_DCCP)) {
+		return;
+	}
+
+	v4_attrs = family_selected(AF_INET) && RSECflag ?
+	    gather_attrs(item, MIB2_DCCP, MIB2_DCCP_CONN, dccpEntrySize) :
+	    NULL;
+	v6_attrs = family_selected(AF_INET6) && RSECflag ?
+	    gather_attrs(item, MIB2_DCCP6, MIB2_DCCP6_CONN, dccp6EntrySize) :
+	    NULL;
+
+	v4a = v4_attrs;
+	v6a = v6_attrs;
+	for (; item != NULL; item = item->next_item) {
+		if (Xflag) {
+			(void) printf("\n--- Entry %d ---\n", ++jtemp);
+			(void) printf("Group = %d, mib_id = %d, "
+			    "length = %d, valp = 0x%p\n",
+			    item->group, item->mib_id,
+			    item->length, item->valp);
+		}
+
+		if (item->group == MIB2_DCCP) {
+			for (dp = (mib2_dccpConnEntry_t *)item->valp;
+			    (char *)dp < (char *)item->valp + item->length;
+			    dp = (mib2_dccpConnEntry_t *)((char *)dp +
+			    dccpEntrySize)) {
+				aptr = v4a == NULL ? NULL : *v4a++;
+				print_hdr_once_v4 = dccp_report_item_v4(dp,
+				    print_hdr_once_v4, aptr);
+			}
+		}
+	}
+
+	(void) fflush(stdout);
+
+	if (v4_attrs != NULL) {
+		free(v4_attrs);
+	}
+	if (v6_attrs != NULL) {
+		free(v6_attrs);
+	}
+}
+
+static boolean_t
+dccp_report_item_v4(const mib2_dccpConnEntry_t *dp, boolean_t first,
+    const mib2_transportMLPEntry_t *attr)
+{
+	char	lname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
+	char	fname[MAXHOSTNAMELEN + MAXHOSTNAMELEN + 1];
+
+	if (first) {
+		(void) printf(v4compat ? dccp_hdr_v4_compat : dccp_hdr_v4);
+		(void) printf(Vflag ? dccp_hdr_v4_verbose : dccp_hdr_v4_normal);
+	}
+
+	(void) printf("%-20s %-20s %5u %6d %5u %6d %s\n",
+	    pr_ap(dp->dccpConnLocalAddress,
+	    dp->dccpConnLocalPort, "dccp", lname, sizeof (lname)),
+	    pr_ap(dp->dccpConnRemAddress,
+	    dp->dccpConnRemPort, "dccp", fname, sizeof (fname)),
+	    0,
+	    0,
+	    0,
+	    0,
+	    0);
+
+	print_transport_label(attr);
+
+	return (B_FALSE);
+}
+
+static boolean_t
+dccp_report_item_v6(const mib2_dccp6ConnEntry_t *dp, boolean_t first,
+    const mib2_transportMLPEntry_t *attr)
+{
+	return (B_FALSE);
+}
+
 static char *
 plural(int n)
 {
--- old/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c	2012-08-18 10:36:56.557953842 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c	2012-08-18 10:36:56.590295328 +0000
@@ -633,7 +633,7 @@
 
 /*
  * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
- * for all the properties for the specified object, relavant information, will
+ * for all the properties for the specified object, relevant information, will
  * be displayed. Otherwise, for the selected property set, display relevant
  * information
  */
@@ -855,7 +855,7 @@
 
 /*
  * Display information for all or specific protocol properties, either for a
- * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
+ * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP/DCCP)
  */
 static void
 do_show_prop(int argc, char **argv, const char *use)
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile	2012-08-18 10:36:57.051774250 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile	2012-08-18 10:36:57.124376039 +0000
@@ -28,8 +28,8 @@
 OBJS=	nfs4_xdr.o snoop.o snoop_aarp.o snoop_adsp.o snoop_aecho.o \
 	snoop_apple.o snoop_arp.o snoop_atp.o snoop_bparam.o \
 	snoop_bpdu.o \
-	snoop_capture.o snoop_dhcp.o snoop_dhcpv6.o snoop_display.o \
-	snoop_dns.o snoop_ether.o \
+	snoop_capture.o snoop_dccp.o snoop_dhcp.o snoop_dhcpv6.o \
+	snoop_display.o snoop_dns.o snoop_ether.o \
 	snoop_filter.o snoop_http.o snoop_icmp.o snoop_igmp.o snoop_ip.o \
 	snoop_ipaddr.o snoop_ipsec.o snoop_isis.o \
 	snoop_ldap.o snoop_mip.o snoop_mount.o \
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h	2012-08-18 10:36:57.543773573 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h	2012-08-18 10:36:57.558162787 +0000
@@ -238,6 +238,8 @@
 extern int interpret_ah(int, uint8_t *, int, int);
 struct sctp_hdr;
 extern void interpret_sctp(int, struct sctp_hdr *, int, int);
+struct dccphdr;
+extern int interpret_dccp(int, struct dccphdr *, int, int);
 extern void interpret_mip_cntrlmsg(int, uchar_t *, int);
 struct dhcp;
 extern int interpret_dhcp(int, struct dhcp *, int);
--- /dev/null	2012-08-18 10:36:57.000000000 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_dccp.c	2012-08-18 10:36:57.854154024 +0000
@@ -0,0 +1,433 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/dccp.h>
+#include "snoop.h"
+
+/*
+ * Snoop interpreter for DCCP (RFC4340)
+ *
+ */
+
+extern char *dlc_header;
+
+static char	*get_type(uint8_t);
+static void	print_dccpoptions_summary(uchar_t *, uchar_t *);
+static void	print_dccpoptions(uchar_t *, uchar_t *);
+
+static char *
+get_type(uint8_t type)
+{
+	switch (type) {
+	case 0:
+		return ("DCCP-Request");
+	case 1:
+		return ("DCCP-Response");
+	case 2:
+		return ("DCCP-Data");
+	case 3:
+		return ("DCCP-Ack");
+	case 4:
+		return ("DCCP-DataAck");
+	case 5:
+		return ("DCCP-CloseReq");
+	case 6:
+		return ("DCCP-Close");
+	case 7:
+		return ("DCCP-Reset");
+	case 8:
+		return ("DCCP-Sync");
+	case 9:
+		return ("DCCP-SyncAck");
+	case 10 ... 15:
+		return ("Reserved");
+
+	default:
+		return ("Unknown");
+	}
+}
+
+int
+interpret_dccp(int flags, struct dccphdr *dccp, int iplen, int fraglen)
+{
+	char		*data;
+	char		*line;
+	char		*endline;
+	uint64_t	seq;
+	uint64_t	ack;
+	int		hdrlen;
+	int		dccplen;
+	int		option_offset;
+	int		i;
+
+	hdrlen = dccp->dh_offset * 4;
+	data = (char *)dccp + hdrlen;
+	dccplen = iplen - hdrlen;
+	fraglen -= hdrlen;
+
+	if (fraglen < 0) {
+		return (fraglen + hdrlen);	/* Incomplete header */
+	}
+
+	if (fraglen > dccplen) {
+		fraglen = dccplen;
+	}
+
+	if (dccp->dh_x == 1) {
+		switch (dccp->dh_type) {
+		case 0:		/* DCCP-Request */
+			option_offset = 20;
+			break;
+		case 1:		/* DCCP-Response */
+			option_offset = 28;
+			break;
+		case 7:		/* DCCP-Reset */
+			option_offset = 28;
+			break;
+		case 8:		/* DCCP-Sync */
+		case 9:		/* DCCP-SyncAck */
+			option_offset = 24;
+			break;
+
+		default:
+			option_offset = 20;
+			break;
+		}
+
+		/* Sequence number */
+		seq = ntohs(dccp->dh_seq);
+		seq <<= 32;
+		seq += (uint32_t)dccp + sizeof (struct dccphdr);
+
+		ack = (uint32_t)(dccp + 16) & 0xffff;
+	} else {
+		switch (dccp->dh_type) {
+		case 0:		/* DCCP-Request */
+		case 1:		/* DCCP-Response */
+		case 7:		/* DCCP-Reset */
+		case 8:		/* DCCP-Sync */
+		case 9:		/* DCCP-SyncAck */
+			break;
+
+		default:
+			option_offset = 20;
+			break;
+		}
+
+		/* Sequence number */
+		seq = dccp->dh_res_seq << 16;
+		seq |= ntohs(dccp->dh_seq);
+	}
+
+	if (flags & F_SUM) {
+		line = get_sum_line();
+		endline = line + MAXLINE;
+
+		(void) snprintf(line, endline - line, "DCCP D=%d S=%d",
+		    ntohs(dccp->dh_dport), ntohs(dccp->dh_sport));
+		line += strlen(line);
+
+		(void) snprintf(line, endline - line, "CCval=%d CsCov=%d",
+		    dccp->dh_ccval, dccp->dh_cscov);
+
+		(void) snprintf(line, endline - line, " Seq=%u Len=%d",
+		    seq, dccplen);
+		line += strlen(line);
+
+		/*
+		 * All packets except DCCP-Request and DCCP-Data carry
+		 * an acknowledgement number.
+		 */
+		if (dccp->dh_type != 0 && dccp->dh_type != 2) {
+			(void) snprintf(line, endline - line, " Ack=%u",
+			    seq, dccplen);
+		}
+		line += strlen(line);
+
+		print_dccpoptions_summary((uchar_t *)dccp + option_offset,
+		    (uchar_t *)dccp + dccp->dh_offset * 4);
+	}
+
+
+	if (flags & F_DTAIL) {
+		show_header("DCCP:  ", "DCCP Header", dccplen);
+		show_space();
+
+		(void) sprintf(get_line((char *)(uintptr_t)dccp->dh_sport -
+		    dlc_header, 2), "Source port = %d",
+		    ntohs(dccp->dh_sport));
+
+		(void) sprintf(get_line((char *)(uintptr_t)dccp->dh_dport -
+		    dlc_header, 2), "Destination port = %d",
+		    ntohs(dccp->dh_dport));
+
+		(void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_offset -
+		    dlc_header) + 4, 1), "Data offset = %d bytes",
+		    dccp->dh_offset * 4);
+
+		(void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_ccval -
+		    dlc_header) + 4, 1), "CCVal = %d",
+		    dccp->dh_ccval);
+
+		(void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_cscov -
+		    dlc_header) + 4, 1), "Checksum coverage (CsCov) = %d",
+		    dccp->dh_cscov);
+
+		(void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_sum -
+		    dlc_header) + 4, 1), "Checksum = 0x%04x",
+		    ntohs(dccp->dh_sum));
+
+		(void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_type -
+		    dlc_header) + 4, 1), "Type = %d (%s)",
+		    dccp->dh_type, get_type(dccp->dh_type));
+
+		(void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_x -
+		    dlc_header) + 4, 1), "Extended sequence numbers = %d",
+		    dccp->dh_x);
+
+		(void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_seq -
+		    dlc_header) + 4, 1), "Sequence number = %d",
+		    seq);
+
+		/*
+		 * All packets except DCCP-Request and DCCP-Data carry
+		 * an acknowledgement number.
+		 */
+		if (dccp->dh_type != 0 && dccp->dh_type != 2) {
+		(void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_seq -
+		    dlc_header) + 4, 1), "Acknowledgement number = %d",
+		    seq);
+		}
+
+		print_dccpoptions((uchar_t *)dccp + option_offset,
+		    (uchar_t *)dccp + dccp->dh_offset * 4);
+
+		show_space();
+	}
+
+	return (dccplen);
+}
+
+static void
+print_dccpoptions_summary(uchar_t *up, uchar_t *end)
+{
+	uchar_t		*value;
+	uint8_t		option_type;
+	uint8_t		option_length;
+	int		len;
+	boolean_t	mandatory = B_FALSE;
+
+	while (up != end) {
+		option_length = 0;
+		option_type = *up++;
+
+		/*
+		 * Is this a variable length option?
+		 */
+		if (option_type > 31) {
+			option_length = *up++;
+			option_length -= 2;
+			value = up;
+
+			up += option_length;
+		}
+		switch (option_type) {
+		case 0:		/* Padding */
+			break;
+		case 1:		/* Mandatory */
+			mandatory = B_TRUE;
+			break;
+		case 2:		/* Slow receiver */
+			break;
+		case 3 ... 31:	/* Reserved */
+			break;
+		case 32:	/* Change L */
+			break;
+		case 33:	/* Confirm L */
+			break;
+		case 34:	/* Change R */
+			break;
+		case 35:	/* Confirm R */
+			break;
+		case 36:	/* Init cookie */
+			break;
+		case 37:	/* NDP count */
+			break;
+		case 38:	/* Ack Vector 0 */
+			break;
+		case 39:	/* Ack vector 1 */
+			break;
+		case 40:	/* Data dropped */
+			break;
+		case 41:	/* Timestamp */
+			break;
+		case 42:	/* Timestamp echo */
+			break;
+		case 43:	/* Elapsed time */
+			break;
+		case 44:	/* Data checksum */
+			break;
+
+		default:
+			break;
+		}
+
+		if (option_type != 1) {
+			mandatory = B_FALSE;
+		}
+	}
+}
+
+static void
+print_dccpoptions(uchar_t *up, uchar_t *end)
+{
+	uchar_t		*value;
+	uint8_t		option_type;
+	uint8_t		option_length;
+	int		len;
+	boolean_t	mandatory = B_FALSE;
+
+	if (up == end) {
+		(void) sprintf(get_line((char *)&up - dlc_header, 1),
+		     "No options");
+		return;
+	}
+
+	(void) sprintf(get_line((char *)&up - dlc_header, 1),
+	    "Options: (%d bytes)", (int)(end - up));
+
+	while (up != end) {
+		option_length = 0;
+		option_type = *up++;
+
+		/*
+		 * Is this a variable length option?
+		 */
+		if (option_type > 31) {
+			option_length = *up++;
+			option_length -= 2;
+			value = up;
+
+			up += option_length;
+		}
+
+		switch (option_type) {
+		case 0:		/* Padding */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Padding");
+			break;
+		case 1:		/* Mandatory */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Mandatory");
+			mandatory = B_TRUE;
+			break;
+		case 2:		/* Slow receiver */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Slow receiver");
+			break;
+		case 3 ... 31:	/* Reserved */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Reserved");
+			break;
+		case 32:	/* Change L */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Change L");
+			break;
+		case 33:	/* Confirm L */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Confirm L");
+			break;
+		case 34:	/* Change R */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Change R");
+			break;
+		case 35:	/* Confirm R */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Confirm R");
+			break;
+		case 36:	/* Init cookie */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Init cookie");
+			break;
+		case 37:	/* NDP count */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "NDP count");
+			break;
+		case 38:	/* Ack vector 0 */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Ack vector 0");
+			break;
+		case 39:	/* Ack vector 1 */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Ack vector 1");
+			break;
+		case 40:	/* Data dropped */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Data dropped");
+			break;
+		case 41:	/* Timestamp */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Timestamp");
+			break;
+		case 42:	/* Timestamp echo */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "TImestamp echo");
+			break;
+		case 43:	/* Elapsed time */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Elapsed time");
+			break;
+		case 44:	/* Data checksum */
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Data checksum");
+			break;
+
+		default:
+			(void) sprintf(get_line(((char *)(uintptr_t)up -
+			    dlc_header) + 4, 1), "Unknown");
+			break;
+		}
+
+		if (option_type != 1) {
+			mandatory = B_FALSE;
+		}
+	}
+}
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_filter.c	2012-08-18 10:36:58.032703741 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_filter.c	2012-08-18 10:36:58.061056931 +0000
@@ -1346,6 +1346,8 @@
 	"ah",		6,  1, IPPROTO_AH,	 1,	OP_OFFSET_LINK,
 	"sctp",		9,  1, IPPROTO_SCTP,	 0,	OP_OFFSET_LINK,
 	"sctp",		6,  1, IPPROTO_SCTP,	 1,	OP_OFFSET_LINK,
+	"dccp",		9,  1, IPPROTO_DCCP,	 0,	OP_OFFSET_LINK,
+	"dccp",		6,  1, IPPROTO_DCCP,	 1,	OP_OFFSET_LINK,
 	0,		0,  0, 0,		 0,	0
 };
 
@@ -1372,6 +1374,8 @@
 	"ah",		6,  1, IPPROTO_AH,	 1,	OP_OFFSET_LINK,
 	"sctp",		9,  1, IPPROTO_SCTP,	 0,	OP_OFFSET_LINK,
 	"sctp",		6,  1, IPPROTO_SCTP,	 1,	OP_OFFSET_LINK,
+	"dccp",		9,  1, IPPROTO_DCCP,	 0,	OP_OFFSET_LINK,
+	"dccp",		6,  1, IPPROTO_DCCP,	 1,	OP_OFFSET_LINK,
 	0,		0,  0, 0,		 0,	0
 };
 
@@ -1393,6 +1397,8 @@
 	"ah",		6,  1, IPPROTO_AH,	1,	OP_OFFSET_LINK,
 	"sctp",		9,  1, IPPROTO_SCTP,	0,	OP_OFFSET_LINK,
 	"sctp",		6,  1, IPPROTO_SCTP,	1,	OP_OFFSET_LINK,
+	"dccp",		9,  1, IPPROTO_DCCP,	0,	OP_OFFSET_LINK,
+	"dccp",		6,  1, IPPROTO_DCCP,	1,	OP_OFFSET_LINK,
 	0,		0,  0, 0,		0,	0
 };
 
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c	2012-08-18 10:36:58.430359566 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ip.c	2012-08-18 10:36:58.447322753 +0000
@@ -299,6 +299,10 @@
 				(void) interpret_sctp(flags,
 				    (struct sctp_hdr *)data, iplen, fraglen);
 				break;
+			case IPPROTO_DCCP:
+				(void) interpret_dccp(flags,
+				    (struct dccphdr *)data, iplen, fraglen);
+				break;
 			}
 		}
 	}
@@ -477,6 +481,10 @@
 		case IPPROTO_OSPF:
 			interpret_ospf6(flags, data, iplen, fraglen);
 			break;
+		case IPPROTO_DCCP:
+			(void) interpret_dccp(flags, (struct dccphdr *)data,
+			    iplen, fraglen);
+			break;
 		}
 	}
 
@@ -730,6 +738,7 @@
 	case IPPROTO_EON:	return ("EON");
 	case IPPROTO_RAW:	return ("RAW");
 	case IPPROTO_OSPF:	return ("OSPF");
+	case IPPROTO_DCCP:	return ("DCCP");
 	default:		return ("");
 	}
 }
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipsec.c	2012-08-18 10:36:58.903832254 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ipsec.c	2012-08-18 10:36:58.913464934 +0000
@@ -236,6 +236,10 @@
 				(void) interpret_udp(flags,
 				    (struct udphdr *)data, new_iplen, fraglen);
 				break;
+			case IPPROTO_DCCP:
+				(void) interpret_dccp(flags,
+				    (struct dccphdr *)data, new_iplen, fraglen);
+				break;
 			/* default case is to not print anything else */
 		}
 
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_pf.c	2012-08-18 10:36:59.362113918 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_pf.c	2012-08-18 10:36:59.414585345 +0000
@@ -153,6 +153,8 @@
 	{IPPROTO_ESP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
 	{IPPROTO_AH, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
 	{IPPROTO_AH, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
+	{IPPROTO_DCCP, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
+	{IPPROTO_DCCP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
 	{-1, 0, 0}	/* must be the final entry */
 };
 
@@ -187,6 +189,10 @@
 	    IPV4_TYPE_HEADER_OFFSET},
 	{IPPROTO_AH, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
 	    IPV6_TYPE_HEADER_OFFSET},
+	{IPPROTO_DCCP, (DL_IPNETINFO_VERSION << 8 | AF_INET),
+	    IPV4_TYPE_HEADER_OFFSET},
+	{IPPROTO_DCCP, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
+	    IPV6_TYPE_HEADER_OFFSET},
 	{-1, 0, 0}	/* must be the final entry */
 };
 
@@ -206,6 +212,8 @@
 	{IPPROTO_ESP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
 	{IPPROTO_AH, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
 	{IPPROTO_AH, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
+	{IPPROTO_DCCP, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
+	{IPPROTO_DCCP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
 	{-1, 0, 0}	/* must be the final entry */
 };
 
@@ -1328,6 +1336,13 @@
 			break;
 		}
 
+		if (EQ("dccp")) {
+			pf_check_transport_protocol(IPPROTO_DCCP);
+			opstack++;
+			next();
+			break;
+		}
+
 		if (EQ("(")) {
 			inBrace++;
 			next();
--- old/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c	2012-08-18 10:36:59.832713471 +0000
+++ new/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_rport.c	2012-08-18 10:36:59.880379340 +0000
@@ -143,7 +143,8 @@
 	const struct porttable *p, *pt;
 
 	switch (proto) {
-	case IPPROTO_SCTP: /* fallthru */
+	case IPPROTO_DCCP: /* fallthru */
+	case IPPROTO_SCTP:
 	case IPPROTO_TCP: pt = pt_tcp; break;
 	case IPPROTO_UDP: pt = pt_udp; break;
 	default: return (NULL);
--- old/usr/src/cmd/devfsadm/misc_link.c	2012-08-18 10:37:00.253415552 +0000
+++ new/usr/src/cmd/devfsadm/misc_link.c	2012-08-18 10:37:00.319880705 +0000
@@ -101,8 +101,8 @@
 	    TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name
 	},
 	{ "pseudo", "ddi_pseudo",
-	    "(^ip$)|(^tcp$)|(^udp$)|(^icmp$)|"
-	    "(^ip6$)|(^tcp6$)|(^udp6$)|(^icmp6$)|"
+	    "(^ip$)|(^tcp$)|(^udp$)|(^icmp$)|(^dccp$)|"
+	    "(^ip6$)|(^tcp6$)|(^udp6$)|(^icmp6$)|(^dccp6$)|"
 	    "(^rts$)|(^arp$)|(^ipsecah$)|(^ipsecesp$)|(^keysock$)|(^spdsock$)|"
 	    "(^nca$)|(^rds$)|(^sdp$)|(^ipnet$)|(^dlpistub$)|(^bpf$)",
 	    TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name
--- old/usr/src/cmd/mdb/common/modules/genunix/genunix.c	2012-08-18 10:37:00.824583716 +0000
+++ new/usr/src/cmd/mdb/common/modules/genunix/genunix.c	2012-08-18 10:37:00.880491909 +0000
@@ -4081,7 +4081,7 @@
 		dladm, dladm_help },
 	{ "mi", ":[-p] [-d | -m]", "filter and display MI object or payload",
 		mi },
-	{ "netstat", "[-arv] [-f inet | inet6 | unix] [-P tcp | udp | icmp]",
+	{ "netstat", "[-arv] [-f inet | inet6 | unix] [-P tcp | udp | icmp | dccp]",
 		"show network statistics", netstat },
 	{ "sonode", "?[-f inet | inet6 | unix | #] "
 		"[-t stream | dgram | raw | #] [-p #]",
@@ -4480,6 +4480,8 @@
 		tcp_stacks_walk_init, tcp_stacks_walk_step, NULL },
 	{ "udp_stacks", "walk all the udp_stack_t",
 		udp_stacks_walk_init, udp_stacks_walk_step, NULL },
+	{ "dccp_stacks", "walk all the dccp_stack_t",
+		dccp_stacks_walk_init, dccp_stacks_walk_step, NULL },
 
 	/* from netstack.c */
 	{ "netstack", "walk a list of kernel netstacks",
--- old/usr/src/cmd/mdb/common/modules/genunix/net.c	2012-08-18 10:37:01.414967894 +0000
+++ new/usr/src/cmd/mdb/common/modules/genunix/net.c	2012-08-18 10:37:01.446987674 +0000
@@ -47,6 +47,7 @@
 #include <inet/udp_impl.h>
 #include <inet/rawip_impl.h>
 #include <inet/mi.h>
+#include <inet/dccp_impl.h>
 #include <fs/sockfs/socktpi_impl.h>
 #include <net/bridge_impl.h>
 #include <io/trill_impl.h>
@@ -142,6 +143,30 @@
 	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
 }
 
+int
+dccp_stacks_walk_init(mdb_walk_state_t *wsp)
+{
+	if (mdb_layered_walk("netstack", wsp) == -1) {
+		mdb_warn("can't walk 'netstack'");
+		return (WALK_ERR);
+	}
+	return (WALK_NEXT);
+}
+
+int
+dccp_stacks_walk_step(mdb_walk_state_t *wsp)
+{
+	uintptr_t kaddr;
+	netstack_t nss;
+
+	if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) {
+		mdb_warn("can't read netstack at %p", wsp->walk_addr);
+		return (WALK_ERR);
+	}
+	kaddr = (uintptr_t)nss.netstack_modules[NS_DCCP];
+	return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata));
+}
+
 /*
  * Print an IPv4 address and port number in a compact and easy to read format
  * The arguments are in network byte order
@@ -207,6 +232,27 @@
 	return (udp->udp_connp->conn_ipversion == IPV6_VERSION);
 }
 
+static int
+net_dccp_active(const dccp_t *dccp)
+{
+	return ((dccp->dccp_state == TS_IDLE) ||
+	    (dccp->dccp_state == TS_DATA_XFER));
+}
+
+static int
+net_dccp_ipv4(const dccp_t *dccp)
+{
+	return ((dccp->dccp_connp->conn_ipversion == IPV4_VERSION) ||
+	    (IN6_IS_ADDR_UNSPECIFIED(&dccp->dccp_connp->conn_laddr_v6) &&
+	    (dccp->dccp_state <= DCCPS_LISTEN)));
+}
+
+static int
+net_dccp_ipv6(const dccp_t *dccp)
+{
+	return (dccp->dccp_connp->conn_ipversion == IPV6_VERSION);
+}
+
 int
 sonode_walk_init(mdb_walk_state_t *wsp)
 {
@@ -745,6 +791,66 @@
 	return (WALK_NEXT);
 }
 
+static void
+netstat_dccp_verbose_pr(const dccp_t *dccp)
+{
+/* XXX:DCCP
+	mdb_printf("       %5i %08x %08x %5i %08x %08x %5li %5i\n",
+	    tcp->tcp_swnd, tcp->tcp_snxt, tcp->tcp_suna, tcp->tcp_rwnd,
+	    tcp->tcp_rack, tcp->tcp_rnxt, tcp->tcp_rto, tcp->tcp_mss);
+*/
+}
+
+/*ARGSUSED*/
+static int
+netstat_dccp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data)
+{
+	netstat_cb_data_t *ncb = cb_data;
+	uint_t opts = ncb->opts;
+	int af = ncb->af;
+	uintptr_t dccp_kaddr;
+	conn_t *connp = &ncb->conn;
+	dccp_t dccps, *dccp;
+
+	if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) {
+		mdb_warn("failed to read conn_t at %p", kaddr);
+		return (WALK_ERR);
+	}
+
+	dccp_kaddr = (uintptr_t)connp->conn_dccp;
+	if (mdb_vread(&dccps, sizeof (dccp_t), dccp_kaddr) == -1) {
+		mdb_warn("failed to read tcp_t at %p", dccp_kaddr);
+		return (WALK_ERR);
+	}
+
+	dccp = &dccps;
+	connp->conn_dccp = dccp;
+	dccp->dccp_connp = connp;
+
+	if (!((opts & NETSTAT_ALL) || net_dccp_active(dccp)) ||
+	    (af == AF_INET && !net_dccp_ipv4(dccp)) ||
+	    (af == AF_INET6 && !net_dccp_ipv6(dccp))) {
+		return (WALK_NEXT);
+	}
+
+	mdb_printf("%0?p %2i ", dccp_kaddr, dccp->dccp_state);
+	if (af == AF_INET) {
+		net_ipv4addrport_pr(&connp->conn_laddr_v6, connp->conn_lport);
+		mdb_printf(" ");
+		net_ipv4addrport_pr(&connp->conn_faddr_v6, connp->conn_fport);
+	} else if (af == AF_INET6) {
+		net_ipv6addrport_pr(&connp->conn_laddr_v6, connp->conn_lport);
+		mdb_printf(" ");
+		net_ipv6addrport_pr(&connp->conn_faddr_v6, connp->conn_fport);
+	}
+	mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack));
+	mdb_printf(" %4i\n", connp->conn_zoneid);
+	if (opts & NETSTAT_VERBOSE)
+		netstat_dccp_verbose_pr(dccp);
+
+	return (WALK_NEXT);
+}
+
 /*
  * print the address of a unix domain socket
  *
@@ -1216,6 +1322,13 @@
 		if (status != DCMD_OK)
 			goto out;
 	}
+
+	if ((optP == NULL) || (strcmp("dccp", optP) == 0)) {
+		status = netstat_print_common("dccp_conn_cache", IPPROTO_DCCP,
+		    netstat_dccp_cb, cbdata);
+		if (status != DCMD_OK)
+			goto out;
+	}
 out:
 	mdb_free(cbdata, sizeof (netstat_cb_data_t));
 	return (status);
--- old/usr/src/cmd/mdb/common/modules/genunix/net.h	2012-08-18 10:37:01.844473962 +0000
+++ new/usr/src/cmd/mdb/common/modules/genunix/net.h	2012-08-18 10:37:01.862477111 +0000
@@ -47,6 +47,8 @@
 extern int tcp_stacks_walk_step(mdb_walk_state_t *);
 extern int udp_stacks_walk_init(mdb_walk_state_t *);
 extern int udp_stacks_walk_step(mdb_walk_state_t *);
+extern int dccp_stacks_walk_init(mdb_walk_state_t *);
+extern int dccp_stacks_walk_step(mdb_walk_state_t *);
 
 extern int sonode(uintptr_t, uint_t, int, const mdb_arg_t *);
 extern int mi(uintptr_t, uint_t, int, const mdb_arg_t *);
--- old/usr/src/cmd/mdb/common/modules/ip/ip.c	2012-08-18 10:37:02.205360760 +0000
+++ new/usr/src/cmd/mdb/common/modules/ip/ip.c	2012-08-18 10:37:02.263975689 +0000
@@ -341,7 +341,7 @@
 
 /*
  * Generic network stack walker initialization function.  It is used by all
- * other netwrok stack walkers.
+ * other network stack walkers.
  */
 int
 ns_walk_init(mdb_walk_state_t *wsp)
@@ -374,6 +374,15 @@
 }
 
 /*
+ * DCCP network stack walker stepping function.
+ */
+int
+dccp_stacks_walk_step(mdb_walk_state_t *wsp)
+{
+	return (ns_walk_step(wsp, NS_DCCP));
+}
+
+/*
  * IP network stack walker stepping function.
  */
 int
@@ -1953,6 +1962,8 @@
 		nce_walk_init, nce_walk_step, NULL },
 	{ "dce", "walk active dce_t structures",
 		dce_walk_init, dce_walk_step, NULL },
+	{ "dccp_stacks", "walk all the dccp_stack_t",
+		ns_walk_init, dccp_stacks_walk_step, NULL },
 	{ "ip_stacks", "walk all the ip_stack_t",
 		ns_walk_init, ip_stacks_walk_step, NULL },
 	{ "tcp_stacks", "walk all the tcp_stack_t",
--- old/usr/src/lib/libdtrace/Makefile.com	2012-08-18 10:37:02.745786664 +0000
+++ new/usr/src/lib/libdtrace/Makefile.com	2012-08-18 10:37:02.779340038 +0000
@@ -73,6 +73,7 @@
 DRTIOBJ = $(DRTISRC:%.c=%.o)
 
 DLIBSRCS += \
+	dccp.d \
 	errno.d \
 	fc.d \
 	io.d \
@@ -109,6 +110,7 @@
 CLEANFILES += ../common/sysevent.sed ../common/sysevent.d
 CLEANFILES += ../common/tcp.sed ../common/tcp.d
 CLEANFILES += ../common/udp.sed ../common/udp.d
+CLEANFILES += ../common/dccp.sed ../common/dccp.d
 
 CLOBBERFILES += drti.o
 
@@ -193,6 +195,9 @@
 ../common/udp.d: ../common/udp.sed ../common/udp.d.in
 	sed -f ../common/udp.sed < ../common/udp.d.in > $@
 
+../common/dccp.d: ../common/dccp.sed ../common/dccp.d.in
+	sed -f ../common/dccp.sed < ../common/dccp.d.in > $@
+
 pics/%.o: ../$(MACH)/%.c
 	$(COMPILE.c) -o $@ $<
 	$(POST_PROCESS_O)
--- /dev/null	2012-08-18 10:37:03.000000000 +0000
+++ new/usr/src/lib/libdtrace/common/dccp.d.in	2012-08-18 10:37:03.150470353 +0000
@@ -0,0 +1,181 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#pragma D depends_on module unix
+#pragma D depends_on provider dccp
+
+inline int32_t DCCP_STATE_CLOSED = @DCCPS_CLOSED@;
+#pragma D binding "1.10" DCCP_STATE_CLOSED
+inline int32_t DCCP_STATE_BOUND = @DCCPS_BOUND@;
+#pragma D binding "1.10" DCCP_STATE_BOUND
+inline int32_t DCCP_STATE_REQUEST = @DCCPS_REQUEST@;
+#pragma D binding "1.10" DCCP_STATE_REQUEST
+inline int32_t DCCP_STATE_LISTEN = @DCCPS_LISTEN@;
+#pragma D binding "1.10" DCCP_STATE_LISTEN
+inline int32_t DCCP_STATE_PARTOPEN = @DCCPS_PARTOPEN@;
+#pragma D binding "1.10" DCCP_STATE_PARTOPEN
+inline int32_t DCCP_STATE_RESPOND = @DCCPS_RESPOND@;
+#pragma D binding "1.10" DCCP_STATE_RESPOND
+inline int32_t DCCP_STATE_OPEN = @DCCPS_OPEN@;
+#pragma D binding "1.10" DCCP_STATE_OPEN
+inline int32_t DCCP_STATE_CLOSING = @DCCPS_CLOSING@;
+#pragma D binding "1.10" DCCP_STATE_CLOSING
+inline int32_t DCCP_STATE_CLOSEREQ = @DCCPS_CLOSEREQ@;
+#pragma D binding "1.10" DCCP_STATE_CLOSEREQ
+inline int32_t DCCP_STATE_TIMEWAIT = @DCCPS_TIMEWAIT@;
+#pragma D binding "1.10" DCCP_STATE_TIMEWAIT
+
+/*
+ * Convert a DCCP state value to a string.
+ */
+inline string dccp_state_string[int32_t state] =
+	state == DCCP_STATE_CLOSED ? "state-closed" :
+	state == DCCP_STATE_BOUND ? "state-bound" :
+	state == DCCP_STATE_REQUEST ? "state-request" :
+	state == DCCP_STATE_LISTEN ? "state-listen" :
+	state == DCCP_STATE_PARTOPEN ? "state-partopen" :
+	state == DCCP_STATE_RESPOND ? "state-respond" :
+	state == DCCP_STATE_OPEN ? "state-open" :
+	state == DCCP_STATE_CLOSING ? "state-closing" :
+	state == DCCP_STATE_CLOSEREQ ? "state-closereq" :
+	state == DCCP_STATE_TIMEWAIT ? "state-timewait" :
+	"<unknown>";
+#pragma D binding "1.10" dccp_state_string
+
+/*
+ * dccpinfo is the DCCP header fields.
+ */
+typedef struct dccpinfo {
+	uint16_t dccp_sport;		/* source port */
+	uint16_t dccp_dport;		/* destination port */
+	uint32_t dccp_seq;		/* sequence number */
+	uint8_t dccp_offset;		/* data offset, in bytes */
+	uint16_t dccp_checksum;		/* checksum */
+	dccph_t *dccp_hdr;		/* raw DCCP header */
+} dccpinfo_t;
+
+/*
+ * dccpsinfo contains stable DCCP details from dccp_t.
+ */
+typedef struct dccpsinfo {
+	uintptr_t dccps_addr;
+	int dccps_local;		/* Is delivered locally, boolean */
+	int dccps_active;		/* Active open (from here), boolean */
+	uint16_t dccps_lport;		/* Local port */
+	uint16_t dccps_rport;		/* Remote port */
+	string dccps_laddr;		/* Local address, as a string */
+	string dccps_raddr;		/* Remote address, as a string */
+	int32_t dccps_state;		/* DCCP state */
+	uint32_t dccps_iss;		/* Initial sequence # sent */
+} dccpsinfo_t;
+
+/*
+ * dccplsinfo provides the old dccp state for state changes.
+ */
+typedef struct dccplsinfo {
+	int32_t dccps_state;		/* Previous DCCP state */
+} dccplsinfo_t;
+
+/*
+ * __dtrace_tcp_tcph_t is used by the tcpinfo_t * translator to take either
+ * the non-NULL tcph_t * passed in or, if it is NULL, uses arg3 (tcp_t *)
+ * from the tcp:::send and tcp:::recieve probes and translates the tcp_t *
+ * into the tcpinfo_t.  When no headers are available - as is the case for
+ * TCP fusion tcp:::send and tcp:::receive - this allows us to present the
+ * consumer with header data based on tcp_t * content and hide TCP fusion
+ * implementation details.
+ */
+typedef dccph_t * __dtrace_dccp_dccph_t;
+
+#pragma D binding "1.10" translator
+translator dccpinfo_t < dccph_t *T > {
+	dccp_sport = ntohs(*(uint16_t *)T->dh_lport);
+	dccp_dport = ntohs(*(uint16_t *)T->dh_fport);
+	dccp_seq = ntohl(*(uint32_t *)T->dh_seq); /* XXX */
+	dccp_offset = (*(uint8_t *)T->dh_offset & 0xf0) >> 2;
+	dccp_checksum = ntohs(*(uint16_t *)T->dh_sum);
+	dccp_hdr = T;
+};
+
+#pragma D binding "1.10" translator
+translator dccpinfo_t < __dtrace_dccp_dccph_t *T > {
+	dccp_sport =
+	    T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_lport) :
+	    arg3 != NULL && probename == "send" ?
+	    ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_lport) :
+	    arg3 != NULL && probename == "receive" ?
+	    ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_fport) :
+	    0;
+	dccp_dport =
+	    T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_fport) :
+	    arg3 != NULL && probename == "send" ?
+	    ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_fport) :
+	    arg3 != NULL && probename == "receive" ?
+	    ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_lport) :
+	    0;
+	dccp_seq =
+	    T != NULL ? ntohl(*(uint32_t *)((dccph_t *)T)->dh_seq) :
+	    0;
+	dccp_offset = T != NULL ?
+	    (*(uint8_t *)((dccph_t *)T)->dh_offset & 0xf0) >> 2 :
+	    @DCCP_MIN_HEADER_LENGTH@;
+	dccp_checksum = T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_sum) :
+	    0;
+	dccp_hdr = NULL;
+};
+
+#pragma D binding "1.10" translator
+translator dccpsinfo_t < dccp_t *T > {
+	dccps_addr = (uintptr_t)T;
+	/*
+	 * The following two members should just use tcp_t->tcp_loopback
+	 * and tcp_t->tcp_active_open, however these are bit fields and
+	 * can't be used until CR 6876830 is fixed.  Meanwhile we source
+	 * them a different way.
+	 */
+	dccps_local = T ? T->dccp_ipha ?
+	    T->dccp_ipha->ipha_src == T->dccp_ipha->ipha_dst : 1 : 0;
+	dccps_active = T ? !T->dccp_saved_listener : 0;
+	dccps_lport = T ?
+	    ntohs(T->dccp_connp->u_port.connu_ports.connu_lport) : 0;
+	dccps_rport = T ?
+	    ntohs(T->dccp_connp->u_port.connu_ports.connu_fport) : 0;
+	dccps_laddr = T ?
+	    inet_ntoa6(&T->dccp_connp->connua_v6addr.connua_laddr) : "<unknown>";
+	dccps_raddr = T ?
+	    inet_ntoa6(&T->dccp_connp->connua_v6addr.connua_faddr) : "<unknown>";
+	dccps_state = T ? T->dccp_state : DCCP_STATE_CLOSED;
+	dccps_iss = T ? T->dccp_iss : 0;
+};
+
+/*
+ * Note: although we specify that the old state argument used as the
+ * input to the tcplsinfo_t translator is an int32_t, it reaches us as an
+ * int64_t (since it is a probe argument) so explicitly cast it back to
+ * interpret the negatively-valued states correctly.
+ */
+#pragma D binding "1.10" translator
+translator dccplsinfo_t < int64_t I > {
+	dccps_state = (int32_t) I;
+};
--- /dev/null	2012-08-18 10:37:03.000000000 +0000
+++ new/usr/src/lib/libdtrace/common/dccp.sed.in	2012-08-18 10:37:03.330628152 +0000
@@ -0,0 +1,42 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <inet/dccp.h>
+#include <sys/netstack.h>
+
+#define	SED_REPLACE(x)	s/#x/x/g
+
+
+SED_REPLACE(DCCPS_CLOSED)
+SED_REPLACE(DCCPS_BOUND)
+SED_REPLACE(DCCPS_REQUEST)
+SED_REPLACE(DCCPS_LISTEN)
+SED_REPLACE(DCCPS_PARTOPEN)
+SED_REPLACE(DCCPS_RESPOND)
+SED_REPLACE(DCCPS_OPEN)
+SED_REPLACE(DCCPS_CLOSING)
+SED_REPLACE(DCCPS_CLOSEREQ)
+SED_REPLACE(DCCPS_TIMEWAIT)
+
+SED_REPLACE(DCCP_MIN_HEADER_LENGTH)
--- old/usr/src/lib/libdtrace/common/dt_open.c	2012-08-18 10:37:03.472135181 +0000
+++ new/usr/src/lib/libdtrace/common/dt_open.c	2012-08-18 10:37:03.506251130 +0000
@@ -110,8 +110,9 @@
 #define	DT_VERS_1_8	DT_VERSION_NUMBER(1, 8, 0)
 #define	DT_VERS_1_8_1	DT_VERSION_NUMBER(1, 8, 1)
 #define	DT_VERS_1_9	DT_VERSION_NUMBER(1, 9, 0)
-#define	DT_VERS_LATEST	DT_VERS_1_9
-#define	DT_VERS_STRING	"Sun D 1.9"
+#define	DT_VERS_1_10	DT_VERSION_NUMBER(1, 10, 0)
+#define	DT_VERS_LATEST	DT_VERS_1_10
+#define	DT_VERS_STRING	"Sun D 1.10"
 
 const dt_version_t _dtrace_versions[] = {
 	DT_VERS_1_0,	/* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -132,6 +133,7 @@
 	DT_VERS_1_8,	/* D API 1.8 */
 	DT_VERS_1_8_1,	/* D API 1.8.1 */
 	DT_VERS_1_9,	/* D API 1.9 */
+	DT_VERS_1_10,	/* D API 1.10 */
 	0
 };
 
--- old/usr/src/lib/libdtrace/common/ip.d.in	2012-08-18 10:37:03.936540231 +0000
+++ new/usr/src/lib/libdtrace/common/ip.d.in	2012-08-18 10:37:03.976861008 +0000
@@ -86,6 +86,8 @@
 inline int IPPROTO_RAW = @IPPROTO_RAW@;
 #pragma D binding "1.5" IPPROTO_MAX
 inline int IPPROTO_MAX = @IPPROTO_MAX@;
+#pragma D binding "1.10" IPPROTO_DCCP
+inline int IPPROTO_DCCP = @IPPROTO_DCCP@;
 
 /*
  * pktinfo is where packet ID info can be made available for deeper
--- old/usr/src/lib/libdtrace/common/ip.sed.in	2012-08-18 10:37:04.406902794 +0000
+++ new/usr/src/lib/libdtrace/common/ip.sed.in	2012-08-18 10:37:04.419268282 +0000
@@ -71,6 +71,7 @@
 SED_REPLACE(IPPROTO_PIM)
 SED_REPLACE(IPPROTO_SCTP)
 SED_REPLACE(IPPROTO_RAW)
+SED_REPLACE(IPPROTO_DCCP)
 SED_REPLACE(IPPROTO_MAX)
 
 SED_REPLACE(TCP_MIN_HEADER_LENGTH)
--- old/usr/src/lib/libipadm/common/ipadm_prop.c	2012-08-18 10:37:04.826353628 +0000
+++ new/usr/src/lib/libipadm/common/ipadm_prop.c	2012-08-18 10:37:04.886186356 +0000
@@ -26,7 +26,7 @@
  * This file contains routines that are used to modify/retrieve protocol or
  * interface property values. It also holds all the supported properties for
  * both IP interface and protocols in `ipadm_prop_desc_t'. Following protocols
- * are supported: IP, IPv4, IPv6, TCP, SCTP, UDP and ICMP.
+ * are supported: IP, IPv4, IPv6, TCP, SCTP, UDP, ICMP and DCCP.
  *
  * This file also contains walkers, which walks through the property table and
  * calls the callback function, of the form `ipadm_prop_wfunc_t' , for every
@@ -82,7 +82,7 @@
 /* array of protocols we support */
 static int protocols[] = { MOD_PROTO_IP, MOD_PROTO_RAWIP,
 			    MOD_PROTO_TCP, MOD_PROTO_UDP,
-			    MOD_PROTO_SCTP };
+			    MOD_PROTO_SCTP, MOD_PROTO_DCCP };
 
 /*
  * Supported IP protocol properties.
@@ -239,6 +239,30 @@
 	{ NULL, 0, 0, 0, NULL, NULL, NULL }
 };
 
+/* Supported DCCP protocol properties */
+static ipadm_prop_desc_t ipadm_dccp_prop_table[] = {
+	{ "extra_priv_ports", IPADMPROP_CLASS_MODULE, MOD_PROTO_DCCP,
+	    IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
+	    i_ipadm_get_prop },
+
+	{ "largest_anon_port", IPADMPROP_CLASS_MODULE, MOD_PROTO_DCCP, 0,
+	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
+
+	{ "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_DCCP, 0,
+	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
+
+	{ "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_DCCP, 0,
+	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
+
+	{ "smallest_anon_port", IPADMPROP_CLASS_MODULE, MOD_PROTO_DCCP, 0,
+	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
+
+	{ "smallest_nonpriv_port", IPADMPROP_CLASS_MODULE, MOD_PROTO_DCCP, 0,
+	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
+
+	{ NULL, 0, 0, 0, NULL, NULL, NULL }
+};
+
 /*
  * A dummy private property structure, used while handling private
  * protocol properties (properties not yet supported by libipadm).
@@ -266,6 +290,8 @@
 		return (ipadm_udp_prop_table);
 	case MOD_PROTO_SCTP:
 		return (ipadm_sctp_prop_table);
+	case MOD_PROTO_DCCP:
+		return (ipadm_dccp_prop_table);
 	}
 
 	return (NULL);
@@ -320,6 +346,8 @@
 		return ("udp");
 	case MOD_PROTO_SCTP:
 		return ("sctp");
+	case MOD_PROTO_DCCP:
+		return ("dccp");
 	}
 
 	return (NULL);
@@ -346,6 +374,8 @@
 		return (MOD_PROTO_SCTP);
 	else if (strcmp(protostr, "arp") == 0)
 		return (MOD_PROTO_IP);
+	else if (strcmp(protostr, "dccp") == 0)
+		return (MOD_PROTO_DCCP);
 
 	return (MOD_PROTO_NONE);
 }
--- old/usr/src/pkg/manifests/developer-dtrace.mf	2012-08-18 10:37:05.360309075 +0000
+++ new/usr/src/pkg/manifests/developer-dtrace.mf	2012-08-18 10:37:05.422012677 +0000
@@ -179,6 +179,7 @@
 file path=usr/lib/$(ARCH64)/llib-ldtrace.ln
 file path=usr/lib/devfsadm/linkmod/SUNW_dtrace_link.so group=sys
 file path=usr/lib/dtrace/64/drti.o
+file path=usr/lib/dtrace/dccp.d
 file path=usr/lib/dtrace/drti.o
 file path=usr/lib/dtrace/errno.d
 file path=usr/lib/dtrace/fc.d
--- old/usr/src/pkg/manifests/system-header.mf	2012-08-18 10:37:05.800568505 +0000
+++ new/usr/src/pkg/manifests/system-header.mf	2012-08-18 10:37:05.848117403 +0000
@@ -400,6 +400,10 @@
 file path=usr/include/ifaddrs.h
 file path=usr/include/inet/arp.h
 file path=usr/include/inet/common.h
+file path=usr/include/inet/dccp.h
+file path=usr/include/inet/dccp_ip.h
+file path=usr/include/inet/dccp_stack.h
+file path=usr/include/inet/dccp_stats.h
 file path=usr/include/inet/ip.h
 file path=usr/include/inet/ip6.h
 file path=usr/include/inet/ip6_asp.h
@@ -556,6 +560,7 @@
 file path=usr/include/netdb.h
 file path=usr/include/netdir.h
 file path=usr/include/netinet/arp.h
+file path=usr/include/netinet/dccp.h
 file path=usr/include/netinet/dhcp.h
 file path=usr/include/netinet/dhcp6.h
 file path=usr/include/netinet/icmp6.h
--- old/usr/src/pkg/manifests/system-kernel.mf	2012-08-18 10:37:06.252023962 +0000
+++ new/usr/src/pkg/manifests/system-kernel.mf	2012-08-18 10:37:06.261816404 +0000
@@ -126,6 +126,8 @@
 driver name=crypto perms="crypto 0666 root sys"
 driver name=cryptoadm perms="cryptoadm 0644 root sys"
 $(sparc_ONLY)driver name=dad alias=ide-disk perms="* 0640 root sys"
+driver name=dccp perms="dccp 0666 root sys"
+driver name=dccp6 perms="dccp6 0666 root sys"
 driver name=devinfo perms="devinfo 0640 root sys" \
     perms="devinfo,ro 0444 root sys"
 driver name=dld perms="* 0666 root sys"
@@ -341,6 +343,8 @@
 file path=kernel/drv/$(ARCH64)/crypto group=sys
 file path=kernel/drv/$(ARCH64)/cryptoadm group=sys
 $(sparc_ONLY)file path=kernel/drv/$(ARCH64)/dad group=sys
+file path=kernel/drv/$(ARCH64)/dccp group=sys
+file path=kernel/drv/$(ARCH64)/dccp6 group=sys
 file path=kernel/drv/$(ARCH64)/devinfo group=sys
 file path=kernel/drv/$(ARCH64)/dld group=sys
 file path=kernel/drv/$(ARCH64)/dlpistub group=sys
@@ -439,6 +443,10 @@
 $(i386_ONLY)file path=kernel/drv/cryptoadm group=sys
 file path=kernel/drv/cryptoadm.conf group=sys
 $(sparc_ONLY)file path=kernel/drv/dad.conf group=sys
+$(i386_ONLY)file path=kernel/drv/dccp group=sys
+file path=kernel/drv/dccp.conf group=sys
+$(i386_ONLY)file path=kernel/drv/dccp6 group=sys
+file path=kernel/drv/dccp6.conf group=sys
 $(i386_ONLY)file path=kernel/drv/devinfo group=sys
 file path=kernel/drv/devinfo.conf group=sys
 $(i386_ONLY)file path=kernel/drv/dld group=sys
@@ -826,6 +834,8 @@
 $(i386_ONLY)hardlink path=kernel/misc/md5 target=../../kernel/crypto/md5
 $(i386_ONLY)hardlink path=kernel/misc/sha1 target=../../kernel/crypto/sha1
 $(i386_ONLY)hardlink path=kernel/misc/sha2 target=../../kernel/crypto/sha2
+hardlink path=kernel/socketmod/$(ARCH64)/dccp \
+    target=../../../kernel/drv/$(ARCH64)/dccp
 hardlink path=kernel/socketmod/$(ARCH64)/icmp \
     target=../../../kernel/drv/$(ARCH64)/icmp
 hardlink path=kernel/socketmod/$(ARCH64)/rts \
@@ -834,12 +844,15 @@
     target=../../../kernel/drv/$(ARCH64)/tcp
 hardlink path=kernel/socketmod/$(ARCH64)/udp \
     target=../../../kernel/drv/$(ARCH64)/udp
+$(i386_ONLY)hardlink path=kernel/socketmod/dccp target=../../kernel/drv/dccp
 $(i386_ONLY)hardlink path=kernel/socketmod/icmp target=../../kernel/drv/icmp
 $(i386_ONLY)hardlink path=kernel/socketmod/rts target=../../kernel/drv/rts
 $(i386_ONLY)hardlink path=kernel/socketmod/tcp target=../../kernel/drv/tcp
 $(i386_ONLY)hardlink path=kernel/socketmod/udp target=../../kernel/drv/udp
 hardlink path=kernel/strmod/$(ARCH64)/arp \
     target=../../../kernel/drv/$(ARCH64)/arp
+hardlink path=kernel/strmod/$(ARCH64)/dccp \
+    target=../../../kernel/drv/$(ARCH64)/dccp
 hardlink path=kernel/strmod/$(ARCH64)/icmp \
     target=../../../kernel/drv/$(ARCH64)/icmp
 hardlink path=kernel/strmod/$(ARCH64)/ip \
@@ -855,6 +868,7 @@
 hardlink path=kernel/strmod/$(ARCH64)/udp \
     target=../../../kernel/drv/$(ARCH64)/udp
 $(i386_ONLY)hardlink path=kernel/strmod/arp target=../../kernel/drv/arp
+$(i386_ONLY)hardlink path=kernel/strmod/dccp target=../../kernel/drv/dccp
 $(i386_ONLY)hardlink path=kernel/strmod/icmp target=../../kernel/drv/icmp
 $(i386_ONLY)hardlink path=kernel/strmod/ip target=../../kernel/drv/ip
 $(i386_ONLY)hardlink path=kernel/strmod/ipsecah \
--- old/usr/src/uts/common/Makefile.files	2012-08-18 10:37:06.701807517 +0000
+++ new/usr/src/uts/common/Makefile.files	2012-08-18 10:37:06.749654936 +0000
@@ -542,6 +542,9 @@
 		sctp_addr.o tn_ipopt.o tnet.o ip_netinfo.o \
 		sctp_misc.o
 IP_ILB_OBJS =	ilb.o ilb_nat.o ilb_conn.o ilb_alg_hash.o ilb_alg_rr.o
+IP_DCCP_OBJS =	dccp.o dccp_bind.o dccp_features.o dccp_input.o dccp_misc.o \
+		dccp_opt_data.o dccp_options.o dccp_output.o dccp_stats.o \
+		dccp_socket.o dccp_timers.o dccp_tpi.o dccp_tunables.o
 
 IP_OBJS +=	igmp.o ipmp.o ip.o ip6.o ip6_asp.o ip6_if.o ip6_ire.o \
 		ip6_rts.o ip_if.o ip_ire.o ip_listutils.o ip_mroute.o \
@@ -557,7 +560,8 @@
 		$(IP_TCP_OBJS) \
 		$(IP_UDP_OBJS) \
 		$(IP_SCTP_OBJS) \
-		$(IP_ILB_OBJS)
+		$(IP_ILB_OBJS) \
+		$(IP_DCCP_OBJS)
 
 IP6_OBJS +=	ip6ddi.o
 
@@ -616,6 +620,10 @@
 
 UDP6_OBJS +=	udp6ddi.o
 
+DCCP_OBJS +=	dccpddi.o
+
+DCCP6_OBJS +=	dccp6ddi.o
+
 SY_OBJS +=	gentty.o
 
 TCO_OBJS +=	ticots.o
--- old/usr/src/uts/common/Makefile.rules	2012-08-18 10:37:07.124748775 +0000
+++ new/usr/src/uts/common/Makefile.rules	2012-08-18 10:37:07.158380336 +0000
@@ -476,6 +476,10 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(UTSBASE)/common/inet/dccp/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(UTSBASE)/common/inet/ip/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -1877,6 +1881,9 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/inet/arp/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
+$(LINTS_DIR)/%.ln:		$(UTSBASE)/common/inet/dccp/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/inet/ip/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- old/usr/src/uts/common/dtrace/sdt_subr.c	2012-08-18 10:37:07.648695804 +0000
+++ new/usr/src/uts/common/dtrace/sdt_subr.c	2012-08-18 10:37:07.698630889 +0000
@@ -107,6 +107,7 @@
 	{ "ip", "__ip_", &stab_attr, 0 },
 	{ "tcp", "__tcp_", &stab_attr, 0 },
 	{ "udp", "__udp_", &stab_attr, 0 },
+	{ "dccp", "__dccp_", &stab_attr, 0 },
 	{ "mib", "__mib_", &stab_attr, 0 },
 	{ "fsinfo", "__fsinfo_", &fsinfo_attr, 0 },
 	{ "iscsi", "__iscsi_", &iscsi_attr, 0 },
@@ -943,6 +944,49 @@
 	{ "udp", "receive", 3, 3, "udp_t *", "udpsinfo_t *" },
 	{ "udp", "receive", 4, 4, "udpha_t *", "udpinfo_t *" },
 
+	{ "dccp", "connect-established", 0, 0, "mblk_t *", "pktinfo_t *" },
+	{ "dccp", "connect-established", 1, 1, "ip_xmit_attr_t *",
+	    "csinfo_t *" },
+	{ "dccp", "connect-established", 2, 2, "void_ip_t *", "ipinfo_t *" },
+	{ "dccp", "connect-established", 3, 3, "dccp_t *", "dccpsinfo_t *" },
+	{ "dccp", "connect-established", 4, 4, "dccph_t *", "dccpinfo_t *" },
+	{ "dccp", "connect-refused", 0, 0, "mblk_t *", "pktinfo_t *" },
+	{ "dccp", "connect-refused", 1, 1, "ip_xmit_attr_t *", "csinfo_t *" },
+	{ "dccp", "connect-refused", 2, 2, "void_ip_t *", "ipinfo_t *" },
+	{ "dccp", "connect-refused", 3, 3, "dccp_t *", "dccpsinfo_t *" },
+	{ "dccp", "connect-refused", 4, 4, "dccph_t *", "dccpinfo_t *" },
+	{ "dccp", "connect-request", 0, 0, "mblk_t *", "pktinfo_t *" },
+	{ "dccp", "connect-request", 1, 1, "ip_xmit_attr_t *", "csinfo_t *" },
+	{ "dccp", "connect-request", 2, 2, "void_ip_t *", "ipinfo_t *" },
+	{ "dccp", "connect-request", 3, 3, "dccp_t *", "dccpsinfo_t *" },
+	{ "dccp", "connect-request", 4, 4, "dccph_t *", "dccpinfo_t *" },
+	{ "dccp", "accept-established", 0, 0, "mblk_t *", "pktinfo_t *" },
+	{ "dccp", "accept-established", 1, 1, "ip_xmit_attr_t *", "csinfo_t *" },
+	{ "dccp", "accept-established", 2, 2, "void_ip_t *", "ipinfo_t *" },
+	{ "dccp", "accept-established", 3, 3, "dccp_t *", "dccpsinfo_t *" },
+	{ "dccp", "accept-established", 4, 4, "dccph_t *", "dccpinfo_t *" },
+	{ "dccp", "accept-refused", 0, 0, "mblk_t *", "pktinfo_t *" },
+	{ "dccp", "accept-refused", 1, 1, "ip_xmit_attr_t *", "csinfo_t *" },
+	{ "dccp", "accept-refused", 2, 2, "void_ip_t *", "ipinfo_t *" },
+	{ "dccp", "accept-refused", 3, 3, "dccp_t *", "dccpsinfo_t *" },
+	{ "dccp", "accept-refused", 4, 4, "dccph_t *", "dccpinfo_t *" },
+	{ "dccp", "state-change", 0, 0, "void", "void" },
+	{ "dccp", "state-change", 1, 1, "ip_xmit_attr_t *", "csinfo_t *" },
+	{ "dccp", "state-change", 2, 2, "void", "void" },
+	{ "dccp", "state-change", 3, 3, "dccp_t *", "dccpsinfo_t *" },
+	{ "dccp", "state-change", 4, 4, "void", "void" },
+	{ "dccp", "state-change", 5, 5, "int32_t", "dccplsinfo_t *" },
+	{ "dccp", "send", 0, 0, "mblk_t *", "pktinfo_t *" },
+	{ "dccp", "send", 1, 1, "ip_xmit_attr_t *", "csinfo_t *" },
+	{ "dccp", "send", 2, 2, "__dtrace_dccp_void_ip_t *", "ipinfo_t *" },
+	{ "dccp", "send", 3, 3, "dccp_t *", "dccpsinfo_t *" },
+	{ "dccp", "send", 4, 4, "__dtrace_dccp_dccph_t *", "dccpinfo_t *" },
+	{ "dccp", "receive", 0, 0, "mblk_t *", "pktinfo_t *" },
+	{ "dccp", "receive", 1, 1, "ip_xmit_attr_t *", "csinfo_t *" },
+	{ "dccp", "receive", 2, 2, "__dtrace_dccp_void_ip_t *", "ipinfo_t *" },
+	{ "dccp", "receive", 3, 3, "dccp_t *", "dccpsinfo_t *" },
+	{ "dccp", "receive", 4, 4, "__dtrace_dccp_dccph_t *", "dccpinfo_t *" },
+
 	{ "sysevent", "post", 0, 0, "evch_bind_t *", "syseventchaninfo_t *" },
 	{ "sysevent", "post", 1, 1, "sysevent_impl_t *", "syseventinfo_t *" },
 
--- old/usr/src/uts/common/inet/Makefile	2012-08-18 10:37:08.069076164 +0000
+++ new/usr/src/uts/common/inet/Makefile	2012-08-18 10:37:08.102859760 +0000
@@ -34,7 +34,8 @@
 	led.h mi.h mib2.h nd.h optcom.h sadb.h sctp_itf.h snmpcom.h tcp.h \
 	tcp_sack.h tcp_stack.h tunables.h udp_impl.h rawip_impl.h ipp_common.h \
 	ip_ftable.h ip_impl.h ip_stack.h ip_arp.h tcp_impl.h wifi_ioctl.h \
-	ip2mac.h ip2mac_impl.h tcp_stats.h
+	ip2mac.h ip2mac_impl.h tcp_stats.h dccp.h dccp_impl.h dccp_ip.h \
+	dccp_stack.h dccp_stats.h
 
 ROOTDIRS= $(ROOT)/usr/include/inet
 
--- /dev/null	2012-08-18 10:37:08.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp.h	2012-08-18 10:37:08.481916091 +0000
@@ -0,0 +1,247 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner. All rights reserved.
+ */
+
+#ifndef	_INET_DCCP_H
+#define	_INET_DCCP_H
+
+#include <sys/inttypes.h>
+#include <sys/socket.h>
+#include <sys/socket_proto.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/dccp.h>
+
+#include <inet/common.h>
+#include <inet/ip.h>
+#include <inet/ip6.h>
+#include <inet/tunables.h>
+#include <inet/dccp_stack.h>
+#include <inet/optcom.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * DCCP states
+ */
+#define	DCCPS_CLOSED		1
+#define	DCCPS_BOUND		2
+#define	DCCPS_REQUEST		3
+#define	DCCPS_LISTEN		4
+#define	DCCPS_PARTOPEN		5
+#define	DCCPS_RESPOND		6
+#define	DCCPS_OPEN		7
+#define	DCCPS_CLOSING		8
+#define	DCCPS_CLOSEREQ		9
+#define	DCCPS_TIMEWAIT		10
+
+/*
+ * DCCP header structures.
+ */
+
+/* Generic protocol header (RFC 4340, Section 5.1.) */
+typedef struct dccphdr_s {
+	uint8_t		dh_lport[2];
+	uint8_t		dh_fport[2];
+	uint8_t		dh_offset;
+	uint8_t		dh_ccval:4,
+			dh_cscov:4;
+	uint8_t		db_sum[2];
+	uint8_t		dh_reserved:3,
+			dh_type:4,
+			dh_x:1;
+	uint8_t		dh_res_seq;
+	uint8_t		dh_seq[2];
+} dccph_t;
+
+#define	DCCP_HDR_LENGTH(dccph)	\
+	(((dccph_t *)dccph)->dh_offset * 4) /* XXX >> 2 */
+#define	DCCP_MAX_HDR_LENGTH		1020
+#define	DCCP_MIN_HEADER_LENGTH		12
+
+/* Generic protocol header aligned (RFC 4340, Section 5.1.) */
+typedef struct dccphdra_s {
+	in_port_t	dha_lport;		/* Source port */
+	in_port_t	dha_fport;		/* Destination port */
+	uint8_t		dha_offset;		/* Data offset */
+	uint8_t		dha_cscov:4,		/* Checksum coverage */
+			dha_ccval:4;		/* */
+	uint16_t	dha_sum;		/* Checksum */
+	uint8_t		dha_x:1,		/* Reserved */
+			dha_type:4,		/* Packet type */
+			dha_reserved:3;		/* Header type */
+	uint8_t		dha_res_seq;
+	uint16_t	dha_seq;		/* Partial sequence number */
+} dccpha_t;
+
+typedef struct dccphdra_ext_s {
+	uint32_t	dha_ext_seq;
+} dccpha_ext_t;
+
+/* Acknowledgement number */
+typedef struct dccphdra_ack {
+	uint16_t	dha_ack_reserved;
+	uint16_t	dha_ack_high;
+	uint32_t	dha_ack_low;
+} dccpha_ack_t;
+
+/* Service number */
+typedef	struct dccphdra_srv {
+	uint32_t	dha_srv_code;
+} dccpha_srv_t;
+
+/* Reset data */
+typedef struct dccphdra_reset {
+	uint8_t		dha_reset_code;
+	uint8_t		dha_reset_data[3];
+} dccpha_reset_t;
+
+/*
+ * Control structure for each open TCP stream,
+ * defined only within the kernel or for a kmem user.
+ * NOTE: tcp_reinit_values MUST have a line for each field in this structure!
+ */
+#if (defined(_KERNEL) || defined(_KMEMUSER))
+
+/* Internal DCCP structure */
+typedef struct dccp_s {
+
+	conn_t		*dccp_connp;	/* Backpointer to conn_t */
+	dccp_stack_t	*dccp_dccps;	/* Backpointer to dccp_stack_t */
+
+	int32_t		dccp_state;
+
+	uint64_t	dccp_last_rcv_lbolt;
+
+	uint32_t	dccp_ibsegs;	/* Inbound segments on this stream */
+	uint32_t	dccp_obsegs;	/* Outbound segments on this stream */
+
+	uint32_t
+		dccp_hard_binding: 1,
+		dccp_loopback: 1,	/* Src and dst are the same machine */
+		dccp_localnet: 1,	/* Src and dst are on the same subnet */
+		dccp_active_open: 1,	/* This is a active open */
+		dccp_detached : 1,	/* If we're detached from a stream */
+		dccp_dummy: 1;
+
+	uint32_t
+		dccp_tconnind_started: 1,
+		dccp_dummy2: 1;
+
+	uint32_t
+		dccp_allow_short_seqnos: 1,
+		dccp_ecn_incapable: 1;
+
+	/*
+	 * Timers and timestamps.
+	 */
+	mblk_t		*dccp_timercache;	/* Timer cache */
+
+	timeout_id_t	dccp_timer_tid;		/* Timer service id */
+	timeout_id_t	dccp_ka_tid;		/* Keepalive timer id */
+
+	clock_t		dccp_timestamp_init;	/* Time reference */
+	int32_t		dccp_timestamp_echo;	/* Timestamp found in options */
+	clock_t		dccp_timestamp;
+
+	clock_t		dccp_first_timer_threshold;
+	clock_t		dccp_second_timer_threshold;
+	clock_t		dccp_first_ctimer_threshold;
+	clock_t		dccp_second_ctimer_threshold;
+
+	int32_t		dccp_ka_last_intrvl;	/* Last probe interval */
+	uint32_t	dccp_ka_interval;	/* Keepalive interval */
+	uint32_t	dccp_ka_rinterval;	/* Keepalive retransmit */
+	uint32_t	dccp_ka_abort_thres;	/* Abort threshold */
+	uint32_t	dccp_ka_cnt;		/* Probes counter */
+
+	int64_t		dccp_last_recv_time;	/* Last segment recv time */
+
+	int		dccp_conn_req_max;	/* # request allowed */
+
+	int32_t		dccp_client_errno;	/* How the client screwed up */
+
+	/*
+	 * Bind related.
+	 */
+	struct dccp_s	*dccp_bind_hash;	/* Bind hash chain */
+	struct dccp_s	*dccp_bind_hash_port;	/* Bound to the same port */
+	struct dccp_s	**dccp_ptpbhn;
+
+	struct dccphdra_s *dccp_dccpha;		/* Template header */
+
+	mblk_t		*dccp_xmit_head;
+
+	/*
+	 * Pointers into the header template.
+	 */
+	ipha_t		*dccp_ipha;
+	ip6_t		*dccp_ip6h;
+
+	t_uscalar_t	dccp_acceptor_id;	/* ACCEPTOR_id */
+
+	sock_connid_t	dccp_connid;
+
+	/* Incrementing pending conn req ID */
+	t_scalar_t	dccp_conn_req_seqnum;
+
+	boolean_t	dccp_issocket;		/* This is a socket dccp */
+
+	/* List of features being negotiated */
+	list_t		dccp_features;
+
+	struct dccp_s	*dccp_listener;		/* Our listener */
+	struct dccp_s	*dccp_saved_listener;	/* Saved listener */
+
+	kmutex_t	dccp_eager_lock;
+
+	/*
+	 * Sequence numbers (Section 7.1.)
+	 */
+	uint64_t	dccp_swl;	/* Sequence number window low */
+	uint64_t	dccp_swh;	/* Sequence number window high */
+	uint64_t	dccp_awl;	/* Ack number window low */
+	uint64_t	dccp_awh;	/* Ack number window high */
+	uint64_t	dccp_iss;	/* Initial sequence number sent */
+	uint64_t	dccp_isr;	/* Initial sequence number received */
+	uint64_t	dccp_osr;	/* First OPEN sequence number */
+	uint64_t	dccp_gss;	/* Greatest sequence number sent */
+	uint64_t	dccp_gsr;	/* Greatest sequence */
+					/* number received */
+	uint64_t	dccp_gar;	/* Greatest acknowledgement */
+					/* number received */
+
+	uint64_t	dccp_sequence_window;
+
+	uint8_t		dccp_reset_code;
+	uint8_t		dccp_reset_data[3];
+} dccp_t;
+
+typedef struct dccp_df_s {
+	struct dccp_s	*df_dccp;
+	kmutex_t	df_lock;
+	uchar_t		df_pad[TF_CACHEL_PAD - (sizeof (dccp_t *) +
+			    sizeof (kmutex_t))];
+} dccp_df_t;
+
+#endif	/* _KERNEL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _INET_DCCP_H */
--- /dev/null	2012-08-18 10:37:08.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp.c	2012-08-18 10:37:08.673733704 +0000
@@ -0,0 +1,1370 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * This file implements the Data Congestion Control Protocol (DCCP).
+ */
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#include <sys/strlog.h>
+#include <sys/strsun.h>
+#define	_SUN_TPI_VERSION 2
+#include <sys/tihdr.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sockio.h>
+#include <sys/priv.h>
+#include <sys/vtrace.h>
+#include <sys/sdt.h>
+#include <sys/debug.h>
+#include <sys/ddi.h>
+#include <sys/isa_defs.h>
+#include <sys/policy.h>
+#include <sys/tsol/label.h>
+#include <sys/tsol/tnet.h>
+
+#include <inet/common.h>
+#include <inet/ip.h>
+#include <inet/ip_impl.h>
+#include <inet/ip6.h>
+#include <inet/dccp.h>
+#include <inet/dccp_impl.h>
+#include <inet/dccp_stack.h>
+#include <inet/kstatcom.h>
+#include <inet/snmpcom.h>
+
+#include <sys/cmn_err.h>
+
+int dccp_squeue_flag;
+
+/* Setable in /etc/system */
+uint_t dccp_bind_fanout_size = DCCP_BIND_FANOUT_SIZE;
+
+static void	dccp_notify(void *, ip_xmit_attr_t *, ixa_notify_type_t,
+		    ixa_notify_arg_t);
+
+/* Functions to register netstack */
+static void	*dccp_stack_init(netstackid_t, netstack_t *);
+static void	dccp_stack_fini(netstackid_t, void *);
+
+/* Stream device open functions */
+static int	dccp_openv4(queue_t *, dev_t *, int, int, cred_t *);
+static int	dccp_openv6(queue_t *, dev_t *, int, int, cred_t *);
+static int	dccp_open(queue_t *, dev_t *, int, int, cred_t *,
+		    boolean_t);
+
+/* Write service routine */
+static void	dccp_wsrv(queue_t *);
+
+/* Connection related functions */
+static int	dccp_connect_ipv4(dccp_t *, ipaddr_t *, in_port_t, uint_t);
+static int	dccp_connect_ipv6(dccp_t *, in6_addr_t *, in_port_t, uint32_t,
+    uint_t, uint32_t);
+
+/* Initialise ISS */
+static void	dccp_iss_init(dccp_t *);
+static void	dccp_reinit(dccp_t *);
+
+struct module_info dccp_rinfo = {
+	DCCP_MOD_ID, DCCP_MOD_NAME, 0, INFPSZ, DCCP_RECV_HIWATER,
+	DCCP_RECV_LOWATER
+};
+
+static struct module_info dccp_winfo = {
+	DCCP_MOD_ID, DCCP_MOD_NAME, 0, INFPSZ, 127, 16
+};
+
+/*
+ * Queue information structure with DCCP entry points.
+ */
+struct qinit dccp_rinitv4 = {
+	NULL, (pfi_t)dccp_rsrv, dccp_openv4, dccp_tpi_close, NULL, &dccp_rinfo
+};
+
+struct qinit dccp_rinitv6 = {
+	NULL, (pfi_t)dccp_rsrv, dccp_openv6, dccp_tpi_close, NULL, &dccp_rinfo
+};
+
+struct qinit dccp_winit = {
+	(pfi_t)dccp_wput, (pfi_t)dccp_wsrv, NULL, NULL, NULL, &dccp_winfo
+};
+
+/* Initial entry point for TCP in socket mode */
+struct qinit dccp_sock_winit = {
+	(pfi_t)dccp_wput_sock, (pfi_t)dccp_wsrv, NULL, NULL, NULL, &dccp_winfo
+};
+
+struct qinit dccp_fallback_sock_winit = {
+	(pfi_t)dccp_wput_fallback, NULL, NULL, NULL, NULL, &dccp_winfo
+};
+/*
+ * DCCP as acceptor STREAM.
+ */
+struct qinit dccp_acceptor_rinit = {
+	NULL, (pfi_t)dccp_rsrv, NULL, dccp_tpi_close_accept, NULL, &dccp_winfo
+};
+
+struct qinit dccp_acceptor_winit = {
+	(pfi_t)dccp_tpi_accept, NULL, NULL, NULL, NULL, &dccp_winfo
+};
+
+/* AF_INET /dev/dccp */
+struct streamtab dccpinfov4 = {
+	&dccp_rinitv4, &dccp_winit
+};
+
+/* AF_INET6 /dev/dccp6 */
+struct streamtab dccpinfov6 = {
+	&dccp_rinitv6, &dccp_winit
+};
+
+/* Template for response to info request */
+struct T_info_ack dccp_g_t_info_ack = {
+	T_INFO_ACK,		/* PRIM_type */
+	0,			/* TSDU_size */
+	T_INFINITE,		/* ETSDU_size */
+	T_INVALID,		/* CDATA_size */
+	T_INVALID,		/* DDATA_size */
+	sizeof (sin_t),		/* ADDR_size */
+	0,			/* OPT_size - not initialized here */
+	TIDUSZ,			/* TIDU_size */
+	T_COTS_ORD,		/* SERV_type */
+	DCCPS_CLOSED,		/* CURRENT_state */
+	(XPG4_1|EXPINLINE)	/* PROVIDER_flag */
+};
+
+struct T_info_ack dccp_g_t_info_ack_v6 = {
+	T_INFO_ACK,		/* PRIM_type */
+	0,			/* TSDU_size */
+	T_INFINITE,		/* ETSDU_size */
+	T_INVALID,		/* CDATA_size */
+	T_INVALID,		/* DDATA_size */
+	sizeof (sin6_t),	/* ADDR_size */
+	0,			/* OPT_size - not initialized here */
+	TIDUSZ,			/* TIDU_size */
+	T_COTS_ORD,		/* SERV_type */
+	DCCPS_CLOSED,		/* CURRENT_state */
+	(XPG4_1|EXPINLINE)	/* PROVIDER_flag */
+};
+
+/*
+ * DCCP Tunables.
+ */
+extern mod_prop_info_t dccp_propinfo_tbl[];
+extern int dccp_propinfo_count;
+
+/*
+ * Register DCCP in ip netstack.
+ */
+void
+dccp_ddi_g_init(void)
+{
+	/* Global timer cache */
+	dccp_timercache = kmem_cache_create("dccp_timercache",
+	    sizeof (dccp_timer_t) + sizeof (mblk_t), 0,
+	    NULL, NULL, NULL, NULL, NULL, 0);
+ 
+	netstack_register(NS_DCCP, dccp_stack_init, NULL, dccp_stack_fini);
+}
+
+/*
+ * Unregister DCCP from ip netstack.
+ */
+void
+dccp_ddi_g_destroy(void)
+{
+	/* Global timer cache */
+	kmem_cache_destroy(dccp_timercache);
+
+	netstack_unregister(NS_DCCP);
+}
+
+#define	INET_NAME	"ip"
+
+/*
+ * Initialize this DCCP stack instance.
+ */
+static void *
+dccp_stack_init(netstackid_t stackid, netstack_t *ns)
+{
+	dccp_stack_t	*dccps;
+	major_t		major;
+	size_t		arrsz;
+	int		error;
+	int		i;
+
+	dccps = kmem_zalloc(sizeof (*dccps), KM_SLEEP);
+	if (dccps == NULL) {
+		return (NULL);
+	}
+	dccps->dccps_netstack = ns;
+
+	/* Ports */
+	mutex_init(&dccps->dccps_epriv_port_lock, NULL, MUTEX_DEFAULT, NULL);
+	dccps->dccps_num_epriv_ports = DCCP_NUM_EPRIV_PORTS;
+	dccps->dccps_epriv_ports[0] = ULP_DEF_EPRIV_PORT1;
+	dccps->dccps_epriv_ports[1] = ULP_DEF_EPRIV_PORT2;
+	dccps->dccps_min_anonpriv_port = 512;
+
+	dccps->dccps_bind_fanout_size = dccp_bind_fanout_size;
+
+	/* Bind fanout */
+	dccps->dccps_bind_fanout = kmem_zalloc(dccps->dccps_bind_fanout_size *
+	    sizeof (dccp_df_t), KM_SLEEP);
+	for (i = 0; i < dccps->dccps_bind_fanout_size; i++) {
+		mutex_init(&dccps->dccps_bind_fanout[i].df_lock, NULL,
+		    MUTEX_DEFAULT, NULL);
+	}
+
+	/* Tunable properties */
+	arrsz = dccp_propinfo_count * sizeof (mod_prop_info_t);
+	dccps->dccps_propinfo_tbl = kmem_alloc(arrsz, KM_SLEEP);
+	if (dccps->dccps_propinfo_tbl == NULL) {
+		kmem_free(dccps, sizeof (*dccps));
+		return (NULL);
+	}
+	bcopy(dccp_propinfo_tbl, dccps->dccps_propinfo_tbl, arrsz);
+
+	/* Allocate per netstack cpu stats */
+	mutex_enter(&cpu_lock);
+	dccps->dccps_sc_cnt = MAX(ncpus, boot_ncpus);
+	mutex_exit(&cpu_lock);
+
+	dccps->dccps_sc = kmem_zalloc(max_ncpus * sizeof (dccp_stats_cpu_t *),
+	    KM_SLEEP);
+	for (i = 0; i < dccps->dccps_sc_cnt; i++) {
+		dccps->dccps_sc[i] = kmem_zalloc(sizeof (dccp_stats_cpu_t),
+		    KM_SLEEP);
+	}
+
+	/* Kernel statistics */
+	//dccps->dccps_kstat = dccp_kstat2_init(stackid);
+	//dccps->dccps_mibkp = dccp_kstat_init(stackid);
+
+	/* Driver major number */
+	major = mod_name_to_major(INET_NAME);
+	error = ldi_ident_from_major(major, &dccps->dccps_ldi_ident);
+	ASSERT(error == 0);
+
+	return (dccps);
+}
+
+/*
+ * Destroy this DCCP netstack instance.
+ */
+static void
+dccp_stack_fini(netstackid_t stackid, void *arg)
+{
+	dccp_stack_t	*dccps = (dccp_stack_t *)arg;
+	int		i;
+
+	/* Free cpu stats */
+	for (i = 0; i < dccps->dccps_sc_cnt; i++) {
+		kmem_free(dccps->dccps_sc[i], sizeof (dccp_stats_cpu_t));
+	}
+	kmem_free(dccps->dccps_sc, max_ncpus * sizeof (dccp_stats_cpu_t *));
+
+	/* Free tunable properties */
+	kmem_free(dccps->dccps_propinfo_tbl,
+	    dccp_propinfo_count * sizeof (mod_prop_info_t));
+	dccps->dccps_propinfo_tbl = NULL;
+
+	/* Free bind fanout */
+	for (i = 0; i < dccps->dccps_bind_fanout_size; i++) {
+		ASSERT(dccps->dccps_bind_fanout[i].df_dccp == NULL);
+		mutex_destroy(&dccps->dccps_bind_fanout[i].df_lock);
+	}
+	kmem_free(dccps->dccps_bind_fanout, dccps->dccps_bind_fanout_size *
+	    sizeof (dccp_df_t));
+	dccps->dccps_bind_fanout = NULL;
+
+	/* Kernel statistics */
+	dccp_kstat_fini(stackid, dccps->dccps_mibkp);
+	dccps->dccps_mibkp = NULL;
+	dccp_kstat2_fini(stackid, dccps->dccps_kstat);
+	dccps->dccps_kstat = NULL;
+
+	ldi_ident_release(dccps->dccps_ldi_ident);
+
+	kmem_free(dccps, sizeof (*dccps));
+}
+
+/* /dev/dccp */
+static int
+dccp_openv4(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
+{
+	cmn_err(CE_NOTE, "dccp.c: dccp_openv4\n");
+
+	return (dccp_open(q, devp, flag, sflag, credp, B_FALSE));
+}
+
+/* /dev/dccp6 */
+static int
+dccp_openv6(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
+{
+	cmn_err(CE_NOTE, "dccp.c: dccp_openv6\n");
+
+	return (dccp_open(q, devp, flag, sflag, credp, B_TRUE));
+}
+
+/*
+ * Common open function for v4 and v6 devices.
+ */
+static int
+dccp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp,
+    boolean_t isv6)
+{
+	conn_t		*connp;
+	dccp_t		*dccp;
+	vmem_t		*minor_arena;
+	dev_t		conn_dev;
+	boolean_t	issocket;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_open");
+
+	/* If the stream is already open, return immediately */
+	if (q->q_ptr != NULL) {
+		return (0);
+	}
+
+	if (sflag == MODOPEN) {
+		return (EINVAL);
+	}
+
+	if ((ip_minor_arena_la != NULL) && (flag & SO_SOCKSTR) &&
+	    ((conn_dev = inet_minor_alloc(ip_minor_arena_la)) != 0)) {
+		minor_arena = ip_minor_arena_la;
+	} else {
+		/*
+		 * Either minor numbers in the large arena were exhausted
+		 * or a non socket application is doing the open.
+		 * Try to allocate from the small arena.
+		 */
+		if ((conn_dev = inet_minor_alloc(ip_minor_arena_sa)) == 0) {
+			return (EBUSY);
+		}
+		minor_arena = ip_minor_arena_sa;
+	}
+
+	ASSERT(minor_arena != NULL);
+
+	*devp = makedevice(getmajor(*devp), (minor_t)conn_dev);
+
+	if (flag & SO_FALLBACK) {
+		/*
+		 * Non streams socket needs a stream to fallback to.
+		 */
+		RD(q)->q_ptr = (void *)conn_dev;
+		WR(q)->q_qinfo = &dccp_fallback_sock_winit;
+		WR(q)->q_ptr = (void *)minor_arena;
+		qprocson(q);
+		return (0);
+	} else if (flag & SO_ACCEPTOR) {
+		q->q_qinfo = &dccp_acceptor_rinit;
+		/*
+		 * The conn_dev and minor_arena will be subsequently used by
+		 * dccp_tli_accept() and dccp_tpi_close_accept() to figure out
+		 * the minor device number for this connection from the q_ptr.
+		 */
+		RD(q)->q_ptr = (void *)conn_dev;
+		WR(q)->q_qinfo = &dccp_acceptor_winit;
+		WR(q)->q_ptr = (void *)minor_arena;
+		qprocson(q);
+		return (0);
+	}
+
+	issocket = flag & SO_SOCKSTR;
+	connp = dccp_create_common(credp, isv6, issocket, &error);
+	if (connp == NULL) {
+		inet_minor_free(minor_arena, conn_dev);
+		q->q_ptr = WR(q)->q_ptr = NULL;
+		return (error);
+	}
+
+	connp->conn_rq = q;
+	connp->conn_wq = WR(q);
+	q->q_ptr = WR(q)->q_ptr = connp;
+
+	connp->conn_dev = conn_dev;
+	connp->conn_minor_arena = minor_arena;
+
+	ASSERT(q->q_qinfo == &dccp_rinitv4 || q->q_qinfo == &dccp_rinitv6);
+	ASSERT(WR(q)->q_qinfo == &dccp_winit);
+
+	dccp = connp->conn_dccp;
+
+	if (issocket) {
+		WR(q)->q_qinfo = &dccp_sock_winit;
+	} else {
+#ifdef	_ILP32
+		dccp->dccp_acceptor_id = (t_uscalar_t)RD(q);
+#else
+		dccp->dccp_acceptor_id = conn_dev;
+#endif	/* _ILP32 */
+	}
+
+	/*
+	 * Put the ref for DCCP. Ref for IP was already put
+	 * by ipcl_conn_create. Also Make the conn_t globally
+	 * visible to walkers.
+	 */
+	mutex_enter(&connp->conn_lock);
+	CONN_INC_REF_LOCKED(connp);
+	ASSERT(connp->conn_ref == 2);
+	connp->conn_state_flags &= ~CONN_INCIPIENT;
+	mutex_exit(&connp->conn_lock);
+
+	qprocson(q);
+
+	return (0);
+}
+
+/*
+ * IXA notify
+ */
+static void
+dccp_notify(void *arg, ip_xmit_attr_t *ixa, ixa_notify_type_t ntype,
+    ixa_notify_arg_t narg)
+{
+	cmn_err(CE_NOTE, "dccp.c: dccp_notify");
+}
+
+/*
+ * Build the template headers.
+ */
+int
+dccp_build_hdrs(dccp_t *dccp)
+{
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	conn_t		*connp = dccp->dccp_connp;
+	dccpha_t	*dccpha;
+	uint32_t	cksum;
+	char		buf[DCCP_MAX_HDR_LENGTH];
+	uint_t		buflen;
+	uint_t		ulplen = 12;
+	uint_t		extralen = 0;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_build_hdrs");
+
+	buflen = connp->conn_ht_ulp_len;
+	if (buflen != 0) {
+		cmn_err(CE_NOTE, "buflen != 0");
+		bcopy(connp->conn_ht_ulp, buf, buflen);
+		extralen -= buflen - ulplen;
+		ulplen = buflen;
+	}
+
+	mutex_enter(&connp->conn_lock);
+	error = conn_build_hdr_template(connp, ulplen, extralen,
+	    &connp->conn_laddr_v6, &connp->conn_faddr_v6, connp->conn_flowinfo);
+	mutex_exit(&connp->conn_lock);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "conn_build_hdr_template failed");
+		return (error);
+	}
+
+	dccpha = (dccpha_t *)connp->conn_ht_ulp;
+	dccp->dccp_dccpha = dccpha;
+
+	if (buflen != 0) {
+		bcopy(buf, connp->conn_ht_ulp, buflen);
+	} else {
+		dccpha->dha_sum = 0;
+		dccpha->dha_lport = connp->conn_lport;
+		dccpha->dha_fport = connp->conn_fport;
+	}
+
+	cksum = sizeof (dccpha_t) + connp->conn_sum;
+	cksum = (cksum >> 16) + (cksum & 0xFFFF);
+	dccpha->dha_sum = htons(cksum);
+	dccpha->dha_offset = 7;
+	dccpha->dha_x = 1;
+
+	if (connp->conn_ipversion == IPV4_VERSION) {
+		dccp->dccp_ipha = (ipha_t *)connp->conn_ht_iphc;
+	} else {
+		dccp->dccp_ip6h = (ip6_t *)connp->conn_ht_iphc;
+	}
+
+	/* XXX */
+
+	return (0);
+}
+
+/*
+ * DCCP write service routine.
+ */
+static void
+dccp_wsrv(queue_t *q)
+{
+	dccp_stack_t	*dccps = Q_TO_DCCP(q)->dccp_dccps;
+
+	DCCP_STAT(dccps, dccp_wsrv_called);
+}
+
+/*
+ * Common create function for streams and sockets.
+ */
+conn_t *
+dccp_create_common(cred_t *credp, boolean_t isv6, boolean_t issocket,
+    int *errorp)
+{
+	conn_t		*connp;
+	dccp_t		*dccp;
+	dccp_stack_t	*dccps;
+	netstack_t	*ns;
+	squeue_t	*sqp;
+	zoneid_t	zoneid;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_create_common\n");
+
+	ASSERT(errorp != NULL);
+
+	error = secpolicy_basic_net_access(credp);
+	if (error != 0) {
+		*errorp = error;
+		return (NULL);
+	}
+
+	/*
+	 * Find the right netstack.
+	 */
+	ns = netstack_find_by_cred(credp);
+	ASSERT(ns != NULL);
+	dccps = ns->netstack_dccp;
+	ASSERT(dccps != NULL);
+
+	/*
+	 * For exclusive stacks we set the zoneid to zero
+	 * to make TCP operate as if in the global zone.
+	 */
+	if (ns->netstack_stackid != GLOBAL_NETSTACKID) {
+		zoneid = GLOBAL_ZONEID;
+	} else {
+		zoneid = crgetzoneid(credp);
+	}
+
+	sqp = IP_SQUEUE_GET((uint_t)gethrtime());
+	connp = (conn_t *)dccp_get_conn(sqp, dccps);
+	netstack_rele(dccps->dccps_netstack);
+	if (connp == NULL) {
+		*errorp = ENOSR;
+		return (NULL);
+	}
+	ASSERT(connp->conn_ixa->ixa_protocol == connp->conn_proto);
+
+	connp->conn_sqp = sqp;
+	connp->conn_initial_sqp = connp->conn_sqp;
+	connp->conn_ixa->ixa_sqp = connp->conn_sqp;
+	dccp = connp->conn_dccp;
+
+	/* Setting flags for ip output */
+	connp->conn_ixa->ixa_flags |= IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE |
+	    IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO;
+
+	ASSERT(connp->conn_proto == IPPROTO_DCCP);
+	ASSERT(connp->conn_dccp == dccp);
+	ASSERT(dccp->dccp_connp == connp);
+
+	if (isv6) {
+		connp->conn_ixa->ixa_src_preferences = IPV6_PREFER_SRC_DEFAULT;
+		connp->conn_ipversion = IPV6_VERSION;
+		connp->conn_family = AF_INET6;
+		/* XXX mms, ttl */
+	} else {
+		connp->conn_ipversion = IPV4_VERSION;
+		connp->conn_family = AF_INET;
+		/* XXX mms, ttl */
+	}
+	connp->conn_xmit_ipp.ipp_unicast_hops = connp->conn_default_ttl;
+
+	crhold(credp);
+	connp->conn_cred = credp;
+	connp->conn_cpid = curproc->p_pid;
+	connp->conn_open_time = ddi_get_lbolt64();
+
+	ASSERT(!(connp->conn_ixa->ixa_free_flags & IXA_FREE_CRED));
+	connp->conn_ixa->ixa_cred = credp;
+	connp->conn_ixa->ixa_cpid = connp->conn_cpid;
+
+	connp->conn_zoneid = zoneid;
+	connp->conn_zone_is_global = (crgetzoneid(credp) == GLOBAL_ZONEID);
+	connp->conn_ixa->ixa_zoneid = zoneid;
+	connp->conn_mlp_type = mlptSingle;
+
+	dccp->dccp_dccps = dccps;
+	dccp->dccp_state = DCCPS_CLOSED;
+
+	ASSERT(connp->conn_netstack == dccps->dccps_netstack);
+	ASSERT(dccp->dccp_dccps == dccps);
+
+	/*
+	 * If the caller has the process-wide flag set, then default to MAC
+	 * exempt mode.  This allows read-down to unlabeled hosts.
+	 */
+	if (getpflags(NET_MAC_AWARE, credp) != 0) {
+		connp->conn_mac_mode = CONN_MAC_AWARE;
+	}
+
+	if (issocket) {
+		dccp->dccp_issocket = 1;
+	}
+
+	/* XXX rcvbuf, sndbuf etc */
+
+	connp->conn_so_type = SOCK_STREAM;
+
+	SOCK_CONNID_INIT(dccp->dccp_connid);
+	dccp_init_values(dccp, NULL);
+
+	return (connp);
+}
+
+/*
+ * Common close function for streams and sockets.
+ */
+void
+dccp_close_common(conn_t *connp, int flags)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	mblk_t		*mp;
+	boolean_t	conn_ioctl_cleanup_reqd = B_FALSE;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_close_common");
+
+	ASSERT(connp->conn_ref >= 2);
+
+	/*
+	 * Mark the conn as closing. ipsq_pending_mp_add will not
+	 * add any mp to the pending mp list, after this conn has
+	 * started closing.
+	 */
+	mutex_enter(&connp->conn_lock);
+	connp->conn_state_flags |= CONN_CLOSING;
+
+	if (connp->conn_oper_pending_ill != NULL) {
+		conn_ioctl_cleanup_reqd = B_TRUE;
+	}
+
+	CONN_INC_REF_LOCKED(connp);
+	mutex_exit(&connp->conn_lock);
+
+	ASSERT(connp->conn_ref >= 3);
+
+	/*
+	 * Cleanup any queued ioctls here. This must be done before the wq/rq
+	 * are re-written by dccp_close_output().
+	 */
+	if (conn_ioctl_cleanup_reqd) {
+		conn_ioctl_cleanup(connp);
+	}
+
+	mutex_enter(&connp->conn_lock);
+	while (connp->conn_ioctlref > 0) {
+		cv_wait(&connp->conn_cv, &connp->conn_lock);
+	}
+	ASSERT(connp->conn_ioctlref == 0);
+	ASSERT(connp->conn_oper_pending_ill == NULL);
+	mutex_exit(&connp->conn_lock);
+
+	/* generate close */
+/*
+	SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_close_output, connp,
+	    NULL, dccp_squeue_flag, SQTAG_IP_DCCP_CLOSE);
+
+*/
+
+nowait:
+	connp->conn_cpid = NOPID;
+}
+
+/*
+ * Common bind function.
+ */
+int
+dccp_do_bind(conn_t *connp, struct sockaddr *sa, socklen_t len, cred_t *cr,
+    boolean_t bind_to_req_port_only)
+{
+	dccp_t	*dccp = connp->conn_dccp;
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_do_bind");
+
+	if (dccp->dccp_state >= DCCPS_BOUND) {
+		if (connp->conn_debug) {
+			(void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
+			    "dccp_bind: bad state, %d", dccp->dccp_state);
+		}
+		return (-TOUTSTATE);
+	}
+
+	error = dccp_bind_check(connp, sa, len, cr, bind_to_req_port_only);
+	if (error != 0) {
+		return (error);
+	}
+
+	ASSERT(dccp->dccp_state == DCCPS_LISTEN);
+	/* XXX dccp_conn_req_max = 0 */	
+
+	return (0);
+}
+
+/*
+ * Common unbind function.
+ */
+int
+dccp_do_unbind(conn_t *connp)
+{
+	dccp_t	*dccp = connp->conn_dccp;
+	int32_t	oldstate;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_do_unbind");
+
+	switch (dccp->dccp_state) {
+	case DCCPS_OPEN:
+	case DCCPS_LISTEN:
+		break;
+	default:
+		return (-TOUTSTATE);
+	}
+
+	connp->conn_laddr_v6 = ipv6_all_zeros;
+	connp->conn_saddr_v6 = ipv6_all_zeros;
+
+	dccp_bind_hash_remove(dccp);
+
+	oldstate = dccp->dccp_state;
+	dccp->dccp_state = DCCPS_CLOSED;
+	DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *,
+	    connp->conn_ixa, void, NULL, dccp_t *, dccp, void, NULL,
+	    int32_t, oldstate);
+
+	ip_unbind(connp);
+	bzero(&connp->conn_ports, sizeof (connp->conn_ports));
+
+	return (0);
+}
+
+/*
+ * Common listen function.
+ */
+int
+dccp_do_listen(conn_t *connp, struct sockaddr *sa, socklen_t len,
+    int backlog, cred_t *cr, boolean_t bind_to_req_port_only)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	int32_t		oldstate;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_do_listen");
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	if (dccp->dccp_state >= DCCPS_BOUND) {
+
+		if ((dccp->dccp_state == DCCPS_BOUND ||
+		    dccp->dccp_state == DCCPS_LISTEN) && backlog > 0) {
+			goto do_listen;
+		}
+		cmn_err(CE_NOTE, "DCCPS_BOUND, bad state");
+
+		if (connp->conn_debug) {
+			(void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
+			    "dccp_listen: bad state, %d", dccp->dccp_state);
+		}
+		return (-TOUTSTATE);
+	} else {
+		if (sa == NULL) {
+			sin6_t	addr;
+			sin6_t	*sin6;
+			sin_t	*sin;
+
+			ASSERT(IPCL_IS_NONSTR(connp));
+
+			if (connp->conn_family == AF_INET) {
+				len = sizeof (sin_t);
+				sin = (sin_t *)&addr;
+				*sin = sin_null;
+				sin->sin_family = AF_INET;
+			} else {
+				ASSERT(connp->conn_family == AF_INET6);
+
+				len = sizeof (sin6_t);
+				sin6 = (sin6_t *)&addr;
+				*sin6 = sin6_null;
+				sin6->sin6_family = AF_INET6;
+			}
+
+			sa = (struct sockaddr *)&addr;
+		}
+
+		error = dccp_bind_check(connp, sa, len, cr,
+		    bind_to_req_port_only);
+		if (error != 0) {
+			cmn_err(CE_NOTE, "dccp_bind_check failed");
+			return (error);
+		}
+		/* Fall through and do the fanout insertion */
+	}
+
+do_listen:
+	ASSERT(dccp->dccp_state == DCCPS_BOUND ||
+	    dccp->dccp_state == DCCPS_LISTEN);
+
+	dccp->dccp_conn_req_max = backlog;
+	if (dccp->dccp_conn_req_max) {
+		if (dccp->dccp_state != DCCPS_LISTEN) {
+			dccp->dccp_state = DCCPS_LISTEN;
+			DTRACE_DCCP6(state__change, void, NULL,
+			    ip_xmit_attr_t *, connp->conn_ixa, void, NULL,
+			    dccp_t *, dccp, void, NULL, int32_t, DCCPS_BOUND);
+
+			dccp->dccp_second_ctimer_threshold =
+			    dccps->dccps_ip_abort_linterval;
+		}
+	}
+
+	/* XXX */
+
+	connp->conn_recv = dccp_input_listener_unbound;
+
+	/* Insert into the classifier table */
+	error = ip_laddr_fanout_insert(connp);
+	if (error != 0) {
+		/* Error - undo the bind */
+		oldstate = dccp->dccp_state;
+		dccp->dccp_state = DCCPS_CLOSED;
+		DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *,
+		    connp->conn_ixa, void, NULL, dccp_t *, dccp, void, NULL,
+		    int32_t, oldstate);
+
+		connp->conn_bound_addr_v6 = ipv6_all_zeros;
+		connp->conn_laddr_v6 = ipv6_all_zeros;
+		connp->conn_saddr_v6 = ipv6_all_zeros;
+		connp->conn_ports = 0;
+
+		if (connp->conn_anon_port) {
+			zone_t	*zone;
+
+			zone = crgetzone(cr);
+			connp->conn_anon_port = B_FALSE;
+			(void) tsol_mlp_anon(zone, connp->conn_mlp_type,
+			    connp->conn_proto, connp->conn_lport, B_FALSE);
+		}
+		connp->conn_mlp_type = mlptSingle;
+
+		dccp_bind_hash_remove(dccp);
+
+		return (error);
+	} else {
+		/* XXX connection limits */
+	}
+
+	return (error);
+}
+
+/*
+ * Common connect function.
+ */
+int
+dccp_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len,
+    cred_t *cr, pid_t pid)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	ip_xmit_attr_t	*ixa = connp->conn_ixa;
+	mblk_t		*req_mp;
+	sin_t		*sin = (sin_t *)sa;
+	sin6_t		*sin6 = (sin6_t *)sa;
+	ipaddr_t	*dstaddrp;
+	in_port_t	dstport;
+	uint_t		srcid;
+	int32_t		oldstate;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_do_connect");
+
+	oldstate = dccp->dccp_state;
+
+	switch (len) {
+	case sizeof (sin_t):
+		sin = (sin_t *)sa;
+		if (sin->sin_port == 0) {
+			return (-TBADADDR);
+		}
+		if (connp->conn_ipv6_v6only) {
+			return (EAFNOSUPPORT);
+		}
+		break;
+
+	case sizeof (sin6_t):
+		sin6 = (sin6_t *)sa;
+		if (sin6->sin6_port == 0) {
+			return (-TBADADDR);
+		}
+		break;
+
+	default:
+		return (EINVAL);
+	}
+
+	if (connp->conn_family == AF_INET6 &&
+	    connp->conn_ipversion == IPV6_VERSION &&
+	    IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+		if (connp->conn_ipv6_v6only) {
+			return (EADDRNOTAVAIL);
+		}
+
+		connp->conn_ipversion = IPV4_VERSION;
+	}
+
+	switch (dccp->dccp_state) {
+	case DCCPS_LISTEN:
+		/*
+		 * Listening sockets are not allowed to issue connect().
+		 */
+		if (IPCL_IS_NONSTR(connp)) {
+			return (EOPNOTSUPP);
+		}
+
+	case DCCPS_CLOSED:
+		/*
+		 * We support quick connect.
+		 */
+		/* FALLTHRU */
+	case DCCPS_OPEN:
+		break;
+
+	default:
+		return (-TOUTSTATE);
+	}
+
+	/*
+	 * We update our cred/cpid based on the caller of connect.
+	 */
+	if (connp->conn_cred != cr) {
+		crhold(cr);
+		crfree(connp->conn_cred);
+		connp->conn_cred = cr;
+	}
+	connp->conn_cpid = pid;
+
+	/* Cache things in the ixa without any refhold */
+	ASSERT(!(ixa->ixa_free_flags & IXA_FREE_CRED));
+	ixa->ixa_cred = cr;
+	ixa->ixa_cpid = pid;
+
+	if (is_system_labeled()) {
+		ip_xmit_attr_restore_tsl(ixa, ixa->ixa_cred);
+	}
+
+	if (connp->conn_family == AF_INET6) {
+		if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+			error = dccp_connect_ipv6(dccp, &sin6->sin6_addr,
+			    sin6->sin6_port, sin6->sin6_flowinfo,
+			    sin6->__sin6_src_id, sin6->sin6_scope_id);
+		} else {
+			/*
+			 * Destination adress is mapped IPv6 address.
+			 * Source bound address should be unspecified or
+			 * IPv6 mapped address as well.
+			 */
+			if (!IN6_IS_ADDR_UNSPECIFIED(
+			    &connp->conn_bound_addr_v6) &&
+			    !IN6_IS_ADDR_V4MAPPED(&connp->conn_bound_addr_v6)) {
+				return (EADDRNOTAVAIL);
+			}
+
+			dstaddrp = &V4_PART_OF_V6((sin6->sin6_addr));
+			dstport = sin6->sin6_port;
+			srcid = sin6->__sin6_src_id;
+			error = dccp_connect_ipv4(dccp, dstaddrp, dstport,
+			    srcid);
+		}
+	} else {
+		dstaddrp = &sin->sin_addr.s_addr;
+		dstport = sin->sin_port;
+		srcid = 0;
+		error = dccp_connect_ipv4(dccp, dstaddrp, dstport, srcid);
+	}
+
+	if (error != 0) {
+		cmn_err(CE_NOTE, "dccp_connect_ip failed");
+		goto connect_failed;
+	}
+
+	/* XXX cluster */
+
+	/* Connect succeeded */
+	DCCPS_BUMP_MIB(dccps, dccpActiveOpens);
+	dccp->dccp_active_open = 1;
+
+	DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *,
+	    connp->conn_ixa, void, NULL, dccp_t *, dccp, void, NULL,
+	    int32_t, DCCPS_BOUND);
+
+	DCCP_TIMER_RESTART(dccp, 100);
+	req_mp = dccp_generate_request(connp);
+	if (req_mp != NULL) {
+		/*
+		 * We must bump the generation before sending the request
+		 * to ensure that we use the right generation in case
+		 * this thread issues a "connected" up call.
+		 */
+		SOCK_CONNID_BUMP(dccp->dccp_connid);
+
+		DTRACE_DCCP5(connect__request, mblk_t *, NULL,
+		    ip_xmit_attr_t *, connp->conn_ixa,
+		    void_ip_t *, req_mp->b_rptr, dccp_t *, dccp,
+		    dccpha_t *,
+		    &req_mp->b_rptr[connp->conn_ixa->ixa_ip_hdr_length]);
+
+		dccp_send_data(dccp, req_mp);
+	}
+
+	return (0);
+
+connect_failed:
+	cmn_err(CE_NOTE, "dccp_do_connect failed");
+
+	connp->conn_faddr_v6 = ipv6_all_zeros;
+	connp->conn_fport = 0;
+	dccp->dccp_state = oldstate;
+
+	/* XXX */
+	return (error);
+}
+
+/*
+ * Init values of a connection.
+ */
+void
+dccp_init_values(dccp_t *dccp, dccp_t *parent)
+{
+	conn_t		*connp = dccp->dccp_connp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+
+	ASSERT((connp->conn_family == AF_INET &&
+	    connp->conn_ipversion == IPV4_VERSION) ||
+	    (connp->conn_family == AF_INET6 &&
+	    (connp->conn_ipversion == IPV4_VERSION ||
+	    connp->conn_ipversion == IPV6_VERSION)));
+
+	if (parent == NULL) {
+
+		dccp->dccp_first_ctimer_threshold =
+		    dccps->dccps_ip_notify_cinterval;
+		dccp->dccp_second_ctimer_threshold =
+		    dccps->dccps_ip_abort_cinterval;
+		dccp->dccp_first_timer_threshold =
+		    dccps->dccps_ip_notify_interval;
+		dccp->dccp_second_timer_threshold =
+		    dccps->dccps_ip_abort_interval;
+
+		dccp->dccp_ka_interval =
+		    dccps->dccps_keepalive_interval;
+		dccp->dccp_ka_abort_thres =
+		    dccps->dccps_keepalive_abort_interval;
+		dccp->dccp_ka_cnt = 0;
+		dccp->dccp_ka_rinterval = 0;
+	} else {
+		/* Inherit various DCCP parameters from the parent */
+		dccp->dccp_first_ctimer_threshold =
+		    parent->dccp_first_ctimer_threshold;
+		dccp->dccp_second_ctimer_threshold =
+		    parent->dccp_second_ctimer_threshold;
+		dccp->dccp_first_timer_threshold =
+		    parent->dccp_first_timer_threshold;
+		dccp->dccp_second_timer_threshold =
+		    parent->dccp_second_timer_threshold;
+
+		dccp->dccp_ka_interval = parent->dccp_ka_interval;
+		dccp->dccp_ka_abort_thres = parent->dccp_ka_abort_thres;
+		dccp->dccp_ka_cnt = parent->dccp_ka_cnt;
+		dccp->dccp_ka_rinterval = parent->dccp_ka_rinterval;
+	}
+
+	dccp->dccp_last_recv_time = ddi_get_lbolt();
+	dccp->dccp_sequence_window = 100;
+
+	connp->conn_mlp_type = mlptSingle;
+
+	if (!connp->conn_debug) {
+		connp->conn_debug = dccps->dccps_dbg;
+	}
+}
+
+/*
+ * Free dccp structure.
+ */
+void
+dccp_free(dccp_t *dccp)
+{
+	conn_t	*connp = dccp->dccp_connp;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_free");
+
+	connp->conn_rq = NULL;
+	connp->conn_wq = NULL;
+
+	if (connp->conn_upper_handle != NULL) {
+		if (IPCL_IS_NONSTR(connp)) {
+			(*connp->conn_upcalls->su_closed)(
+			    connp->conn_upper_handle);
+			dccp->dccp_detached = B_TRUE;
+		}
+
+		connp->conn_upper_handle = NULL;
+		connp->conn_upcalls = NULL;
+	}
+}
+
+void *
+dccp_get_conn(void *arg, dccp_stack_t *dccps)
+{
+	conn_t		*connp;
+	dccp_t		*dccp = NULL;
+	squeue_t	*sqp = (squeue_t *)arg;
+	netstack_t	*ns;
+
+	/* XXX timewait */
+
+	connp = ipcl_conn_create(IPCL_DCCPCONN, KM_NOSLEEP,
+	    dccps->dccps_netstack);
+	if (connp == NULL) {
+		return (NULL);
+	}
+
+	dccp = connp->conn_dccp;
+	dccp->dccp_dccps = dccps;
+
+	/* List of features being negotated */
+	list_create(&dccp->dccp_features, sizeof (dccp_feature_t),
+	    offsetof(dccp_feature_t, df_next));
+
+	connp->conn_recv = dccp_input_data;
+	connp->conn_recvicmp = dccp_icmp_input;
+	connp->conn_verifyicmp = dccp_verifyicmp;
+
+	connp->conn_ixa->ixa_notify = dccp_notify;
+	connp->conn_ixa->ixa_notify_cookie = dccp;
+
+	return ((void *)connp);
+}
+
+/*
+ * Collect protocol properties to send to the upper handle.
+ */
+void
+dccp_get_proto_props(dccp_t *dccp, struct sock_proto_props *sopp)
+{
+	conn_t	*connp = dccp->dccp_connp;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_get_proto_props");
+
+	sopp->sopp_flags = SOCKOPT_RCVHIWAT | SOCKOPT_MAXBLK | SOCKOPT_WROFF;
+}
+
+/*
+ * IPv4 connect.
+ */
+static int
+dccp_connect_ipv4(dccp_t *dccp, ipaddr_t *dstaddrp, in_port_t dstport,
+    uint_t srcid)
+{
+	conn_t		*connp = dccp->dccp_connp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	ipaddr_t	dstaddr = *dstaddrp;
+	uint16_t	lport;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp.c: dccp_connect_ipv4");
+
+	ASSERT(connp->conn_ipversion == IPV4_VERSION);
+
+	if (dstaddr == INADDR_ANY) {
+		dstaddr = htonl(INADDR_LOOPBACK);
+		*dstaddrp = dstaddr;
+	}
+
+	/* Handle __sin6_src_id if socket not bound to an IP address */
+	if (srcid != 0 && connp->conn_laddr_v4 == INADDR_ANY) {
+		ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
+		    IPCL_ZONEID(connp), dccps->dccps_netstack);
+		connp->conn_saddr_v6 = connp->conn_laddr_v6;
+	}
+
+	IN6_IPADDR_TO_V4MAPPED(dstaddr, &connp->conn_faddr_v6);
+	connp->conn_fport = dstport;
+
+	if (dccp->dccp_state == DCCPS_CLOSED) {
+		lport = dccp_update_next_port(dccps->dccps_next_port_to_try,
+		    dccp, B_TRUE);
+		lport = dccp_bindi(dccp, lport, &connp->conn_laddr_v6, 0,
+		    B_TRUE, B_FALSE, B_FALSE);
+		if (lport == 0) {
+			return (-TNOADDR);
+		}
+	}
+
+	error = dccp_set_destination(dccp);
+	if (error != 0) {
+		return (error);
+	}
+
+	/*
+	 * Don't connect to oneself.
+	 */
+	if (connp->conn_faddr_v4 == connp->conn_laddr_v4 &&
+	    connp->conn_fport == connp->conn_lport) {
+		return (-TBADADDR);
+	}
+
+	dccp->dccp_state = DCCPS_REQUEST;
+
+	return (ipcl_conn_insert_v4(connp));
+}
+
+/*
+ * IPv6 connect.
+ */
+static int
+dccp_connect_ipv6(dccp_t *dccp, in6_addr_t *dstaddrp, in_port_t dstport,
+    uint32_t flowinfo, uint_t srcid, uint32_t scope_id)
+{
+	cmn_err(CE_NOTE, "dccp.c: dccp_connect_ipv6");
+
+	return (0);
+}
+
+/*
+ * Set the ports via conn_connect and build the template
+ * header.
+ */
+int
+dccp_set_destination(dccp_t *dccp)
+{
+	conn_t		*connp = dccp->dccp_connp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	iulp_t		uinfo;
+	uint32_t	flags;
+	int		error;
+
+	flags = IPDF_LSO | IPDF_ZCOPY;
+	flags |= IPDF_UNIQUE_DCE;
+
+	mutex_enter(&connp->conn_lock);
+	error = conn_connect(connp, &uinfo, flags);
+	mutex_exit(&connp->conn_lock);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "conn_connect failed");
+		return (error);
+	}
+
+	error = dccp_build_hdrs(dccp);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "dccp_build_hdrs failed");
+		return (error);
+	}
+
+	/* XXX */
+
+	/* Initialise the ISS */
+	dccp_iss_init(dccp);
+
+	mutex_enter(&connp->conn_lock);
+	connp->conn_state_flags &= ~CONN_INCIPIENT;
+	mutex_exit(&connp->conn_lock);
+
+	return (0);
+}
+
+/*
+ * Clean up.
+ */
+int
+dccp_clean_death(dccp_t *dccp, int error)
+{
+	conn_t		*connp = dccp->dccp_connp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+
+	ASSERT(dccp != NULL);
+	ASSERT((connp->conn_family == AF_INET &&
+	    connp->conn_ipversion == IPV4_VERSION) ||
+	    (connp->conn_family == AF_INET6 &&
+	    (connp->conn_ipversion == IPV4_VERSION ||
+	    connp->conn_ipversion == IPV6_VERSION)));
+
+	dccp_reinit(dccp);
+	if (IPCL_IS_NONSTR(connp)) {
+		(void) dccp_do_unbind(connp);
+	}
+
+	return (-1);
+}
+
+/*
+ * Init the ISS.
+ */
+static void
+dccp_iss_init(dccp_t *dccp)
+{
+	cmn_err(CE_NOTE, "dccp.c: dccp_iss_init");
+
+	dccp->dccp_iss += gethrtime();
+	dccp->dccp_gss = dccp->dccp_iss;
+}
+
+/*
+ * Reinitialization of a dccp structure.
+ */
+static void
+dccp_reinit(dccp_t *dccp)
+{
+	conn_t		*connp = dccp->dccp_connp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+
+	ASSERT(dccp->dccp_listener == NULL);
+	ASSERT((connp->conn_family == AF_INET &&
+	    connp->conn_ipversion == IPV4_VERSION) ||
+	    (connp->conn_family == AF_INET6 &&
+	    (connp->conn_ipversion == IPV4_VERSION ||
+	    connp->conn_ipversion == IPV6_VERSION)));
+
+	/* Cancel outstanding timers */
+	dccp_timers_stop(dccp);
+}
--- /dev/null	2012-08-18 10:37:08.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp.conf	2012-08-18 10:37:08.851395644 +0000
@@ -0,0 +1,26 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License").  You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1992, by Sun Microsystems, Inc.
+#
+
+name="dccp" parent="pseudo" instance=0;
--- /dev/null	2012-08-18 10:37:09.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp6.conf	2012-08-18 10:37:09.002958871 +0000
@@ -0,0 +1,26 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License").  You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1992, by Sun Microsystems, Inc.
+#
+
+name="dccp6" parent="pseudo" instance=0;
--- /dev/null	2012-08-18 10:37:09.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp6ddi.c	2012-08-18 10:37:09.245328145 +0000
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/modctl.h>
+#include <inet/common.h>
+#include <inet/ip.h>
+
+#define	INET_NAME	"dccp6"
+#define	INET_DEVSTRTAB	dccpinfov6
+#define	INET_DEVDESC	"DCCP6 STREAMS driver"
+#define	INET_DEVMINOR	0
+#define	INET_DEVMTFLAGS	(D_MP|_D_DIRECT)
+
+#include "../inetddi.c"
+
+int
+_init(void)
+{
+	/*
+	 * device initialization happens when the actual code containing
+	 * module (/kernel/drv/ip) is loaded, and driven from ip_ddi_init()
+	 */
+	return (mod_install(&modlinkage));
+}
+
+int
+_fini(void)
+{
+	return (mod_remove(&modlinkage));
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+	return (mod_info(&modlinkage, modinfop));
+}
--- /dev/null	2012-08-18 10:37:09.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_bind.c	2012-08-18 10:37:09.439794968 +0000
@@ -0,0 +1,709 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * This file contains function related to binding.
+ */
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/stropts.h>
+#include <sys/strlog.h>
+#define	_SUN_TPI_VERSION 2
+#include <sys/tihdr.h>
+#include <sys/suntpi.h>
+#include <sys/xti_inet.h>
+#include <sys/squeue_impl.h>
+#include <sys/squeue.h>
+#include <sys/tsol/tnet.h>
+
+#include <rpc/pmap_prot.h>
+
+#include <inet/common.h>
+#include <inet/dccp_impl.h>
+#include <inet/ip.h>
+#include <inet/proto_set.h>
+
+#include <sys/cmn_err.h>
+
+/* Setable in /etc/system */
+static uint32_t dccp_random_anon_port = 1;
+
+static int	dccp_bind_select_lport(dccp_t *, in_port_t *, boolean_t,
+		    cred_t *);
+static in_port_t dccp_get_next_priv_port(const dccp_t *);
+
+void
+dccp_bind_hash_insert(dccp_df_t *tbf, dccp_t *dccp, int caller_holds_lock)
+{
+	conn_t	*connp = dccp->dccp_connp;
+	conn_t	*connext;
+	dccp_t	**dccpp;
+	dccp_t	*dccpnext;
+	dccp_t	*dccphash;
+
+	cmn_err(CE_NOTE, "dccp_bind.c: dccp_bind_hash_insert");
+
+	/* XXX:DCCP */
+
+	dccpp = &tbf->df_dccp;
+	if (!caller_holds_lock) {
+		mutex_enter(&tbf->df_lock);
+	} else {
+		ASSERT(MUTEX_HELD(&tbf->df_lock));
+	}
+
+	dccphash = dccpp[0];
+	dccpnext = NULL;
+
+	if (dccphash != NULL) {
+		/* Look for an entry using the same port */
+		while ((dccphash = dccpp[0]) != NULL &&
+		    connp->conn_lport != dccphash->dccp_connp->conn_lport) {
+			dccpp = &(dccphash->dccp_bind_hash);
+		}
+
+		/* The port was not found, just add to the end */
+		if (dccphash == NULL) {
+			goto insert;
+		}
+
+		dccpnext = dccphash;
+		connext = dccpnext->dccp_connp;
+		dccphash = NULL;
+		if (V6_OR_V4_INADDR_ANY(connp->conn_bound_addr_v6) &&
+		    !V6_OR_V4_INADDR_ANY(connext->conn_bound_addr_v6)) {
+			while ((dccpnext = dccpp[0]) != NULL) {
+				connext = dccpnext->dccp_connp;
+				if (!V6_OR_V4_INADDR_ANY(
+				    connext->conn_bound_addr_v6)) {
+					dccpp = &(dccpnext->dccp_bind_hash_port);
+				} else {
+					break;
+				}
+			}
+
+			if (dccpnext != NULL) {
+				dccpnext->dccp_ptpbhn = &dccp->dccp_bind_hash_port;
+				dccphash = dccpnext->dccp_bind_hash;
+				if (dccphash != NULL) {
+					dccphash->dccp_ptpbhn =
+					    &(dccp->dccp_bind_hash);
+					dccpnext->dccp_bind_hash = NULL;
+				}
+			}
+		} else {
+			dccpnext->dccp_ptpbhn = &dccp->dccp_bind_hash_port;
+			dccphash = dccpnext->dccp_bind_hash;
+			if (dccphash != NULL) {
+				dccphash->dccp_ptpbhn =
+				    &(dccp->dccp_bind_hash);
+				dccpnext->dccp_bind_hash = NULL;
+			}
+		}
+	}
+
+insert:
+	dccp->dccp_bind_hash_port = dccpnext;
+	dccp->dccp_bind_hash = dccphash;
+	dccp->dccp_ptpbhn = dccpp;
+	dccpp[0] = dccp;
+
+	if (!caller_holds_lock) {
+		mutex_exit(&tbf->df_lock);
+	}
+}
+
+/*
+ * Remove bind hash.
+ */
+void
+dccp_bind_hash_remove(dccp_t *dccp)
+{
+	conn_t		*connp = dccp->dccp_connp;
+	dccp_t		*dccpnext;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	kmutex_t	*lockp;
+
+	cmn_err(CE_NOTE, "dccp_bind.c: dccp_bind_hash_remove");
+
+	/* Nothing to remove */
+	if (dccp->dccp_ptpbhn == NULL) {
+		return;
+	}
+
+	ASSERT(connp->conn_lport != 0);
+	lockp = &dccps->dccps_bind_fanout[DCCP_BIND_HASH(connp->conn_lport,
+	    dccps->dccps_bind_fanout_size)].df_lock;
+	ASSERT(lockp != NULL);
+
+	mutex_enter(lockp);
+	if (dccp->dccp_ptpbhn) {
+		dccpnext = dccp->dccp_bind_hash_port;
+		if (dccpnext != NULL) {
+			dccp->dccp_bind_hash_port = NULL;
+			dccpnext->dccp_ptpbhn = dccp->dccp_ptpbhn;
+			dccpnext->dccp_bind_hash = dccp->dccp_bind_hash;
+			if (dccpnext->dccp_bind_hash != NULL) {
+				dccpnext->dccp_bind_hash->dccp_ptpbhn =
+				    &(dccpnext->dccp_bind_hash);
+				dccp->dccp_bind_hash = NULL;
+			}
+		} else if ((dccpnext = dccp->dccp_bind_hash) != NULL) {
+			dccpnext->dccp_ptpbhn = dccp->dccp_ptpbhn;
+			dccp->dccp_bind_hash = NULL;
+		}
+		*dccp->dccp_ptpbhn = dccpnext;
+		dccp->dccp_ptpbhn = NULL;
+	}
+	mutex_exit(lockp);
+}
+
+/*
+ * Check for a valid address and get a local port.
+ */
+int
+dccp_bind_check(conn_t *connp, struct sockaddr *sa, socklen_t len, cred_t *cr,
+    boolean_t bind_to_req_port_only)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	ip_stack_t	*ips = connp->conn_netstack->netstack_ip;
+	ip_xmit_attr_t	*ixa = connp->conn_ixa;
+	sin_t		*sin;
+	sin6_t		*sin6;
+	ipaddr_t	v4addr;
+	in6_addr_t	v6addr;
+	ip_laddr_t	laddr_type = IPVL_UNICAST_UP;
+	zoneid_t	zoneid = IPCL_ZONEID(connp);
+	in_port_t	requested_port;
+	uint_t		scopeid = 0;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp_bind.c: dccp_bind_check");
+
+	ASSERT((uintptr_t)len <= (uintptr_t)INT_MAX);
+
+	/*
+	 * We should be in a pre-listen state.
+	 */
+	if (dccp->dccp_state == DCCPS_LISTEN) {
+		return (0);
+	} else if (dccp->dccp_state > DCCPS_LISTEN) {
+		if (connp->conn_debug) {
+			(void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
+			    "dccp_bind: bad state, %d", dccp->dccp_state);
+		}
+		return (-TOUTSTATE);
+	}
+
+	/*
+	 * Check for a valid address parameter. Then validate the
+	 * addresses and copy them and the required port in.
+	 */
+	ASSERT(sa != NULL && len != 0);
+
+	if (!OK_32PTR((char *)sa)) {
+		if (connp->conn_debug) {
+			(void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
+			    "dccp_bind: bad address parameter, "
+			    "address %p, len %d", (void *)sa, len);
+		}
+		return (-TPROTO);
+	}
+
+	error = proto_verify_ip_addr(connp->conn_family, sa, len);
+	if (error != 0) {
+		return (error);
+	}
+
+	switch (len) {
+	case sizeof (sin_t):
+		sin = (sin_t *)sa;
+		v4addr = sin->sin_addr.s_addr;
+		requested_port = ntohs(sin->sin_port);
+		IN6_IPADDR_TO_V4MAPPED(v4addr, &v6addr);
+		if (v4addr != INADDR_ANY) {
+			laddr_type = ip_laddr_verify_v4(v4addr, zoneid, ips,
+			    B_FALSE);
+		}
+		break;
+
+	case sizeof (sin6_t):
+		sin6 = (sin6_t *)sa;
+		v6addr = sin6->sin6_addr;
+		requested_port = ntohs(sin6->sin6_port);
+		if (IN6_IS_ADDR_V4MAPPED(&v6addr)) {
+			if (connp->conn_ipv6_v6only) {
+				return (EADDRNOTAVAIL);
+			}
+
+			IN6_V4MAPPED_TO_IPADDR(&v6addr, v4addr);
+			if (v4addr != INADDR_ANY) {
+				laddr_type = ip_laddr_verify_v4(v4addr, zoneid,
+				    ips, B_FALSE);
+			}
+		} else {
+			if (!IN6_IS_ADDR_UNSPECIFIED(&v6addr)) {
+				if (IN6_IS_ADDR_LINKSCOPE(&v6addr)) {
+					scopeid = sin6->sin6_scope_id;
+					laddr_type = ip_laddr_verify_v6(&v6addr,
+					    zoneid, ips, B_FALSE, scopeid);
+				}
+			}
+		}
+		break;
+
+	default:
+		if (connp->conn_debug) {
+			(void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
+			    "dccp_bind: bad address length, %d", len);
+		}
+		return (EAFNOSUPPORT);
+	}
+
+	if (laddr_type == IPVL_BAD) {
+		return (EADDRNOTAVAIL);
+	}
+
+	connp->conn_bound_addr_v6 = v6addr;
+	if (scopeid != 0) {
+		ixa->ixa_flags |= IXAF_SCOPEID_SET;
+		ixa->ixa_scopeid = scopeid;
+		connp->conn_incoming_ifindex = scopeid;
+	} else {
+		ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
+		connp->conn_incoming_ifindex = connp->conn_bound_if;
+	}
+
+	connp->conn_laddr_v6 = v6addr;
+	connp->conn_saddr_v6 = v6addr;
+
+	bind_to_req_port_only = requested_port != 0 && bind_to_req_port_only;
+
+	error = dccp_bind_select_lport(dccp, &requested_port,
+	    bind_to_req_port_only, cr);
+	if (error != 0) {
+		connp->conn_laddr_v6 = ipv6_all_zeros;
+		connp->conn_saddr_v6 = ipv6_all_zeros;
+		connp->conn_bound_addr_v6 = ipv6_all_zeros;
+	}
+
+	return (error);
+}
+
+/*
+ * Bind to a local port.
+ */
+static int
+dccp_bind_select_lport(dccp_t *dccp, in_port_t *requested_port_ptr,
+    boolean_t bind_to_req_port_only, cred_t *cr)
+{
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	conn_t		*connp = dccp->dccp_connp;
+	zone_t		*zone;
+	in_port_t	allocated_port;
+	in_port_t	requested_port = *requested_port_ptr;
+	in_port_t	mlp_port;
+	in6_addr_t	v6addr = connp->conn_laddr_v6;
+	mlp_type_t	addrtype;
+	mlp_type_t	mlptype;
+	boolean_t	user_specified;
+
+	cmn_err(CE_NOTE, "dccp_bind.c: dccp_bind_select_lport");
+
+	ASSERT(cr != NULL);
+
+	mlptype = mlptSingle;
+	mlp_port = requested_port;
+	if (requested_port == 0) {
+		requested_port = connp->conn_anon_priv_bind ?
+		    dccp_get_next_priv_port(dccp) :
+		    dccp_update_next_port(dccps->dccps_next_port_to_try,
+		    dccp, B_TRUE);
+		if (requested_port == 0) {
+			return (-TNOADDR);
+		}
+		user_specified = B_FALSE;
+
+		if (connp->conn_anon_mlp && is_system_labeled()) {
+			zone = crgetzone(cr);
+			addrtype = tsol_mlp_addr_type(
+			    connp->conn_allzones ? ALL_ZONES : zone->zone_id,
+			    IPV6_VERSION, &v6addr,
+			    dccps->dccps_netstack->netstack_ip);
+			if (addrtype == mlptSingle) {
+				return (-TNOADDR);
+			}
+			mlptype = tsol_mlp_port_type(zone, IPPROTO_DCCP,
+			    PMAPPORT, addrtype);
+			mlp_port = PMAPPORT;
+		}
+	}  else {
+		int		i;
+		boolean_t	priv = B_FALSE;
+
+		if (requested_port < dccps->dccps_smallest_nonpriv_port) {
+			priv = B_TRUE;
+		} else {
+			for (i = 0; i < dccps->dccps_num_epriv_ports; i++) {
+				if (requested_port ==
+				    dccps->dccps_epriv_ports[i]) {
+					priv = B_TRUE;
+					break;
+				}
+			}
+		}
+
+		if (priv) {
+			if (secpolicy_net_privaddr(cr, requested_port,
+			    IPPROTO_DCCP) != 0) {
+				if (connp->conn_debug) {
+					(void) strlog(DCCP_MOD_ID, 0, 1,
+					    SL_ERROR|SL_TRACE,
+					    "tcp_bind: no priv for port %d",
+					    requested_port);
+				}
+				return (-TACCES);
+			}
+		}
+
+		user_specified = B_TRUE;
+
+		connp = dccp->dccp_connp;
+		if (is_system_labeled()) {
+			zone = crgetzone(cr);
+			addrtype = tsol_mlp_addr_type(
+			    connp->conn_allzones ? ALL_ZONES : zone->zone_id,
+			    IPV6_VERSION, &v6addr,
+			    dccps->dccps_netstack->netstack_ip);
+			if (addrtype == mlptSingle) {
+				return (-TNOADDR);
+			}
+			mlptype = tsol_mlp_port_type(zone, IPPROTO_DCCP,
+			    requested_port, addrtype);
+		}
+	}
+
+	if (mlptype != mlptSingle) {
+		if (secpolicy_net_bindmlp(cr) != 0) {
+			if (connp->conn_debug) {
+				(void) strlog(DCCP_MOD_ID, 0, 1,
+				    SL_ERROR|SL_TRACE,
+				    "dccp_bind: no priv for multilevel port %d",
+				    requested_port);
+			}
+			return (-TACCES);
+		}
+
+		/*
+		 * If we're specifically binding a shared IP address and the
+		 * port is MLP on shared addresses, then check to see if this
+		 * zone actually owns the MLP.  Reject if not.
+		 */
+		if (mlptype == mlptShared && addrtype == mlptShared) {
+			/*
+			 * No need to handle exclusive-stack zones since
+			 * ALL_ZONES only applies to the shared stack.
+			 */
+			zoneid_t	mlpzone;
+
+			mlpzone = tsol_mlp_findzone(IPPROTO_DCCP,
+			    htons(mlp_port));
+			if (connp->conn_zoneid != mlpzone) {
+				if (connp->conn_debug) {
+					(void) strlog(DCCP_MOD_ID, 0, 1,
+					    SL_ERROR|SL_TRACE,
+					    "dccp_bind: attempt to bind port "
+					    "%d on shared addr in zone %d "
+					    "(should be %d)",
+					    mlp_port, connp->conn_zoneid,
+					    mlpzone);
+				}
+				return (-TACCES);
+			}
+		}
+
+		if (!user_specified) {
+			int	error;
+
+			error = tsol_mlp_anon(zone, mlptype, connp->conn_proto,
+			    requested_port, B_TRUE);
+			if (error != 0) {
+				if (connp->conn_debug) {
+					(void) strlog(DCCP_MOD_ID, 0, 1,
+					    SL_ERROR|SL_TRACE,
+					    "dccp_bind: cannot establish anon "
+					    "MLP for port %d",
+					    requested_port);
+				}
+				return (error);
+			}
+			connp->conn_anon_port = B_TRUE;
+		}
+		connp->conn_mlp_type = mlptype;
+	}
+
+	allocated_port = dccp_bindi(dccp, requested_port, &v6addr,
+	    connp->conn_reuseaddr, B_FALSE, bind_to_req_port_only,
+	    user_specified);
+
+	if (allocated_port == 0) {
+		connp->conn_mlp_type = mlptSingle;
+
+		if (connp->conn_anon_port) {
+			connp->conn_anon_port = B_FALSE;
+			(void) tsol_mlp_anon(zone, mlptype, connp->conn_proto,
+			    requested_port, B_FALSE);
+		}
+
+		if (bind_to_req_port_only) {
+			if (connp->conn_debug) {
+				(void) strlog(DCCP_MOD_ID, 0, 1,
+				    SL_ERROR|SL_TRACE,
+				    "dccp_bind: requested addr busy");
+			}
+			return (-TADDRBUSY);
+		} else {
+			/* If we are out of ports, fail the bind */
+			if (connp->conn_debug) {
+				(void) strlog(DCCP_MOD_ID, 0, 1,
+				    SL_ERROR|SL_TRACE,
+				    "dccp_bind: out of ports?");
+			}
+			return (-TNOADDR);
+		}
+	}
+
+	/* Pass the allocated port back */
+	*requested_port_ptr = allocated_port;
+	return (0);
+}
+
+in_port_t
+dccp_bindi(dccp_t *dccp, in_port_t port, const in6_addr_t *laddr,
+    int reuseaddr, boolean_t quick_connect, boolean_t bind_to_req_port_only,
+    boolean_t user_specified)
+{
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	conn_t		*connp = dccp->dccp_connp;
+	int		count = 0;
+	int		loopmax;
+
+	cmn_err(CE_NOTE, "dccp_bind.c: dccp_bindi");
+
+	if (bind_to_req_port_only) {
+		loopmax = 1;
+	} else {
+		if (connp->conn_anon_priv_bind) {
+			loopmax = IPPORT_RESERVED -
+			    dccps->dccps_min_anonpriv_port;
+		} else {
+			loopmax = (dccps->dccps_largest_anon_port -
+			    dccps->dccps_smallest_anon_port + 1);
+		}
+	}
+
+	do {
+		conn_t		*lconnp;
+		dccp_t		*ldccp;
+		dccp_df_t	*ldf;
+		uint16_t	lport;
+
+		lport = htons(port);
+
+		dccp_bind_hash_remove(dccp);
+		ldf = &dccps->dccps_bind_fanout[DCCP_BIND_HASH(lport,
+		    dccps->dccps_bind_fanout_size)];
+		mutex_enter(&ldf->df_lock);
+		for (ldccp = ldf->df_dccp; ldccp != NULL;
+		    ldccp = ldccp->dccp_bind_hash) {
+			if (lport == ldccp->dccp_connp->conn_lport) {
+				break;
+			}
+		}
+
+		if (ldccp != NULL) {
+			/* The port number is busy */
+			mutex_exit(&ldf->df_lock);
+		} else {
+			/*
+			 * This port is ours. Insert in fanout and mark as
+			 * bound to prevent others from getting the port
+			 * number.
+			 */
+			dccp->dccp_state = DCCPS_BOUND;
+			DTRACE_DCCP6(state__change, void, NULL,
+			    ip_xmit_attr_t *, connp->conn_ixa,
+			    void, NULL, dccp_t *, dccp, void, NULL,
+			    int32_t, DCCPS_CLOSED);
+
+			connp->conn_lport = htons(port);
+
+			ASSERT(&dccps->dccps_bind_fanout[DCCP_BIND_HASH(
+			     connp->conn_lport,
+			     dccps->dccps_bind_fanout_size)] == ldf);
+			dccp_bind_hash_insert(ldf, dccp, 1);
+
+			mutex_exit(&ldf->df_lock);
+
+			/*
+			 * We don't want tcp_next_port_to_try to "inherit"
+			 * a port number supplied by the user in a bind.
+			 */
+			if (user_specified) {
+				return (port);
+			}
+
+			/*
+			 * This is the only place where dccp_next_port_to_try
+			 * is updated. After the update, it may or may not
+			 * be in the valid range.
+			 */
+			if (!connp->conn_anon_priv_bind) {
+				dccps->dccps_next_port_to_try = port + 1;
+			}
+
+			return (port);
+		}
+
+		if (connp->conn_anon_priv_bind) {
+			port = dccp_get_next_priv_port(dccp);
+		} else {
+			if (count == 0 && user_specified) {
+				/*
+				 * We may have to return an anonymous port. So
+				 * get one to start with.
+				 */
+				port =
+				    dccp_update_next_port(
+				    dccps->dccps_next_port_to_try,
+				    dccp, B_TRUE);
+				user_specified = B_FALSE;
+			} else {
+				port = dccp_update_next_port(port + 1, dccp,
+				    B_FALSE);
+			}
+		}
+
+		if (port == 0) {
+			break;
+		}
+
+	} while (++count < loopmax);
+
+	cmn_err(CE_NOTE, "dccp_bind.c: dccp_bindi exit");
+
+	return (0);
+}
+
+in_port_t
+dccp_update_next_port(in_port_t port, const dccp_t *dccp, boolean_t random)
+{
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	boolean_t	restart = B_FALSE;
+	int		i;
+
+	cmn_err(CE_NOTE, "dccp_bind.c: dccp_update_next_port");
+
+	if (random && dccp_random_anon_port != 0) {
+		(void) random_get_pseudo_bytes((uint8_t *)&port,
+		    sizeof (in_port_t));
+
+		if (port < dccps->dccps_smallest_anon_port) {
+			port = dccps->dccps_smallest_anon_port +
+			    port % (dccps->dccps_largest_anon_port -
+			    dccps->dccps_smallest_anon_port);
+		}
+	}
+
+retry:
+	if (port < dccps->dccps_smallest_anon_port) {
+		port = (in_port_t)dccps->dccps_smallest_anon_port;
+	}
+
+	if (port > dccps->dccps_largest_anon_port) {
+		if (restart) {
+			return (0);
+		}
+		restart = B_TRUE;
+		port = (in_port_t)dccps->dccps_smallest_anon_port;
+	}
+
+	if (port < dccps->dccps_smallest_nonpriv_port) {
+		port = (in_port_t)dccps->dccps_smallest_nonpriv_port;
+	}
+
+	for (i = 0; i < dccps->dccps_num_epriv_ports; i++) {
+		if (port == dccps->dccps_epriv_ports[i]) {
+			port++;
+			goto retry;
+		}
+	}
+
+	return (port);
+}
+
+/*
+ * Return the next anonymous port in the privileged port range for
+ * bind checking.  It starts at IPPORT_RESERVED - 1 and goes
+ * downwards.  This is the same behavior as documented in the userland
+ * library call rresvport(3N).
+ *
+ * TS note: skip multilevel ports.
+ */
+static in_port_t
+dccp_get_next_priv_port(const dccp_t *dccp)
+{
+	static in_port_t next_priv_port = IPPORT_RESERVED - 1;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	in_port_t	nextport;
+	boolean_t	restart = B_FALSE;
+
+retry:
+	if (next_priv_port < dccps->dccps_min_anonpriv_port ||
+	    next_priv_port >= IPPORT_RESERVED) {
+		next_priv_port = IPPORT_RESERVED - 1;
+		if (restart) {
+			return (0);
+		}
+		restart = B_TRUE;
+	}
+
+	if (is_system_labeled() &&
+	    (nextport = tsol_next_port(crgetzone(dccp->dccp_connp->conn_cred),
+	    next_priv_port, IPPROTO_DCCP, B_FALSE)) != 0) {
+		next_priv_port = nextport;
+		goto retry;
+	}
+
+	return (next_priv_port--);
+}
--- /dev/null	2012-08-18 10:37:09.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_features.c	2012-08-18 10:37:09.871548172 +0000
@@ -0,0 +1,115 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner. All rights reserved.
+ */
+
+#include <sys/types.h> 
+#include <sys/stream.h> 
+#include <sys/debug.h> 
+#include <sys/cmn_err.h>
+#include <inet/dccp_impl.h>
+#include <inet/dccp_stack.h>
+
+/*
+ * This file contains functions to parse and process DCCP features.
+ */
+
+/*
+ * Feature handling.
+ */
+int
+dccp_parse_feature(dccp_t *dccp, uint8_t option, uint8_t length, uchar_t *up,
+    boolean_t mandatory)
+{
+	dccp_feature_t	*feature;
+	uint64_t	feature_value;
+	uint8_t		feature_type;
+	uint8_t		feature_length = length - 1;
+
+	cmn_err(CE_NOTE, "dccp_features.c: dccp_parse_feature");
+
+	feature_type = *up;
+	up++;
+
+	switch (feature_type) {
+	case DCCP_FEATURE_CCID:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_CCID");
+		break;
+	case DCCP_FEATURE_ALLOW_SHORT_SEQNOS:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_ALLOW_SHORT_SEQNOS");
+		break;
+	case DCCP_FEATURE_SEQUENCE_WINDOW:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_SEQUENCE_WINDOW");
+		if (feature_length != 6)
+			return (DCCP_RESET_MANDATORY_ERROR);
+
+		feature_value = (uint64_t)up[0] << 40;
+		feature_value += ((uint64_t)up[1] << 32);
+		feature_value += ((uint64_t)up[2] << 24);
+		feature_value += ((uint64_t)up[3] << 16);
+		feature_value += ((uint64_t)up[4] << 8);
+		feature_value += (uint64_t)up[5];
+
+		if (feature_value < 32 || feature_value > 70368744177663)
+			return (DCCP_RESET_MANDATORY_ERROR);
+		dccp->dccp_sequence_window = feature_value;
+		break;
+	case DCCP_FEATURE_ECN_INCAPABLE:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_ECN_INCAPABLE");
+		break;
+	case DCCP_FEATURE_ACK_RATIO:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_ACK_RATIO");
+		break;
+	case DCCP_FEATURE_SEND_ACK_VECTOR:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_SEND_ACK_VECTOR");
+		break;
+	case DCCP_FEATURE_SEND_NDP_COUNT:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_SEND_NDP_COUNT");
+		break;
+	case DCCP_FEATURE_MIN_CHECKSUM_COVERAGE:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_MIN_CHECKSUM_COVERAGE");
+		break;
+	case DCCP_FEATURE_CHECK_DATA_CHECKSUM:
+		cmn_err(CE_NOTE, "DCCP_FEATURE_CHECK_DATA_CHECKSUM");
+		break;
+	default:
+		cmn_err(CE_NOTE, "ERROR DEFAULT");
+		break;
+	}
+
+	cmn_err(CE_NOTE, "feature len: %d", feature_length);
+
+	feature = (dccp_feature_t *)kmem_alloc(sizeof (dccp_feature_t),
+	    KM_SLEEP);
+	if (feature == NULL) {
+		return (0);
+	}
+
+	feature->df_option = option;
+	feature->df_type = feature_type;
+	feature->df_mandatory = mandatory;
+
+	list_insert_tail(&dccp->dccp_features, feature);
+
+	return (0);
+}
+
+void
+dccp_features_init(void)
+{
+}
+
+void
+dccp_features_destroy(void)
+{
+}
--- /dev/null	2012-08-18 10:37:10.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_input.c	2012-08-18 10:37:10.060449259 +0000
@@ -0,0 +1,1044 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/stropts.h>
+#include <sys/strlog.h>
+#define	_SUN_TPI_VERSION 2
+#include <sys/tihdr.h>
+#include <sys/suntpi.h>
+#include <sys/xti_inet.h>
+#include <sys/squeue_impl.h>
+#include <sys/squeue.h>
+#include <sys/tsol/tnet.h>
+
+#include <inet/common.h>
+#include <inet/dccp_impl.h>
+#include <inet/ip.h>
+
+#include <sys/cmn_err.h>
+
+static mblk_t	*dccp_conn_create_v4(conn_t *, conn_t *, mblk_t *,
+		    ip_recv_attr_t *);
+static mblk_t	*dccp_conn_create_v6(conn_t *, conn_t *, mblk_t *,
+		    ip_recv_attr_t *);
+static void	dccp_input_listener(void *, mblk_t *, void *, ip_recv_attr_t *);
+static void	dccp_icmp_error_ipv6(dccp_t *, mblk_t *, ip_recv_attr_t *);
+static int	dccp_check_input(conn_t *, mblk_t *, ip_recv_attr_t *);
+
+void
+dccp_icmp_input(void *arg1, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
+{
+	conn_t	*connp = (conn_t *)arg1;
+	dccp_t	*dccp = connp->conn_dccp;
+	ipha_t	*ipha;
+	icmph_t	*icmph;
+	sin_t	sin;
+	sin6_t	sin6;
+	int	iph_hdr_length;
+	int 	error;
+
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_icmp_input");
+
+	ipha = (ipha_t *)mp->b_rptr;
+
+	/* Assume IP provides aligned packets */
+	ASSERT(OK_32PTR(mp->b_rptr));
+	ASSERT((MBLKL(mp) >= sizeof (ipha_t)));
+
+	if (dccp->dccp_state == DCCPS_CLOSED) {
+		freemsg(mp);
+		return;
+	}
+
+	/*
+	 * Verify IP version. Anything other than IPv4 or IPv6 packet is sent
+	 * upstream. ICMPv6 is handled in dccp_icmp_error_ipv6.
+	 */
+	if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) {
+		ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION);
+		dccp_icmp_error_ipv6(dccp, mp, ira);
+		return;
+	}
+	ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
+
+	ASSERT(IPH_HDR_LENGTH(ipha) == ira->ira_ip_hdr_length);
+	/* Skip past the outer IP and ICMP headers */
+	iph_hdr_length = ira->ira_ip_hdr_length;
+	icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length];
+
+	switch (icmph->icmph_type) {
+	case ICMP_DEST_UNREACHABLE:
+		switch (icmph->icmph_code) {
+		case ICMP_FRAGMENTATION_NEEDED:
+		case ICMP_PORT_UNREACHABLE:
+		case ICMP_PROTOCOL_UNREACHABLE:
+		case ICMP_HOST_UNREACHABLE:
+		case ICMP_NET_UNREACHABLE:
+			break;
+		default:
+			break;
+		}
+		break;
+	case ICMP_SOURCE_QUENCH:
+		break;
+	}
+
+	freemsg(mp);
+}
+
+/*
+ * Handler for ICMPv6 error messages.
+ */
+static void
+dccp_icmp_error_ipv6(dccp_t *dccp, mblk_t *mp, ip_recv_attr_t *ira)
+{
+	ip6_t		*ip6h;
+	icmp6_t		*icmp6;
+	uint16_t	iph_hdr_length = ira->ira_ip_hdr_length;
+
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_icmp_error_ipv6");
+
+	ASSERT((MBLKL(mp) >= sizeof (ip6_t)));
+
+	icmp6 = (icmp6_t *)&mp->b_rptr[iph_hdr_length];
+	ip6h = (ip6_t *)&icmp6[1];
+
+}
+
+void
+dccp_rsrv(queue_t *q)
+{
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_rsrv");
+}
+
+/*
+ * Handle a REQUEST on an AF_INET6 socket; can be either IPv4 or IPv6.
+ */
+static mblk_t *
+dccp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp,
+    ip_recv_attr_t *ira)
+{
+	dccp_t		*ldccp = lconnp->conn_dccp;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	ipha_t		*ipha;
+	ip6_t		*ip6h;
+	mblk_t		*tpi_mp;
+	sin6_t		sin6;
+	uint_t		ifindex = ira->ira_ruifindex;
+
+	if (ira->ira_flags & IRAF_IS_IPV4) {
+		ipha = (ipha_t *)mp->b_rptr;
+
+		connp->conn_ipversion = IPV4_VERSION;
+		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_laddr_v6);
+		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_faddr_v6);
+		connp->conn_saddr_v6 = connp->conn_laddr_v6;
+
+		sin6 = sin6_null;
+		sin6.sin6_addr = connp->conn_faddr_v6;
+		sin6.sin6_port = connp->conn_fport;
+		sin6.sin6_family = AF_INET6;
+		sin6.__sin6_src_id = ip_srcid_find_addr(&connp->conn_laddr_v6,
+		    IPCL_ZONEID(lconnp), dccps->dccps_netstack);
+
+		if (connp->conn_recv_ancillary.crb_recvdstaddr) {
+			sin6_t	sin6d;
+
+			sin6d = sin6_null;
+			sin6d.sin6_addr = connp->conn_laddr_v6;
+			sin6d.sin6_port = connp->conn_lport;
+			sin6d.sin6_family = AF_INET;
+			tpi_mp = mi_tpi_extconn_ind(NULL,
+			    (char *)&sin6d, sizeof (sin6_t),
+			    (char *)&dccp,
+			    (t_scalar_t)sizeof (intptr_t),
+			    (char *)&sin6d, sizeof (sin6_t),
+			    (t_scalar_t)ldccp->dccp_conn_req_seqnum);
+		} else {
+			tpi_mp = mi_tpi_conn_ind(NULL,
+			    (char *)&sin6, sizeof (sin6_t),
+			    (char *)&dccp, (t_scalar_t)sizeof (intptr_t),
+			    (t_scalar_t)ldccp->dccp_conn_req_seqnum);
+		}
+	} else {
+		ip6h = (ip6_t *)mp->b_rptr;
+
+		connp->conn_ipversion = IPV6_VERSION;
+		connp->conn_laddr_v6 = ip6h->ip6_dst;
+		connp->conn_faddr_v6 = ip6h->ip6_src;
+		connp->conn_saddr_v6 = connp->conn_laddr_v6;
+
+		sin6 = sin6_null;
+		sin6.sin6_addr = connp->conn_faddr_v6;
+		sin6.sin6_port = connp->conn_fport;
+		sin6.sin6_family = AF_INET6;
+		sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK;
+		sin6.__sin6_src_id = ip_srcid_find_addr(&connp->conn_laddr_v6,
+		    IPCL_ZONEID(lconnp), dccps->dccps_netstack);
+
+		if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) {
+			/* Pass up the scope_id of remote addr */
+			sin6.sin6_scope_id = ifindex;
+		} else {
+			sin6.sin6_scope_id = 0;
+		}
+		if (connp->conn_recv_ancillary.crb_recvdstaddr) {
+			sin6_t	sin6d;
+
+			sin6d = sin6_null;
+			sin6.sin6_addr = connp->conn_laddr_v6;
+			sin6d.sin6_port = connp->conn_lport;
+			sin6d.sin6_family = AF_INET6;
+			if (IN6_IS_ADDR_LINKSCOPE(&connp->conn_laddr_v6))
+				sin6d.sin6_scope_id = ifindex;
+
+			tpi_mp = mi_tpi_extconn_ind(NULL,
+			    (char *)&sin6d, sizeof (sin6_t),
+			    (char *)&dccp, (t_scalar_t)sizeof (intptr_t),
+			    (char *)&sin6d, sizeof (sin6_t),
+			    (t_scalar_t)ldccp->dccp_conn_req_seqnum);
+		} else {
+			tpi_mp = mi_tpi_conn_ind(NULL,
+			    (char *)&sin6, sizeof (sin6_t),
+			    (char *)&dccp, (t_scalar_t)sizeof (intptr_t),
+			    (t_scalar_t)ldccp->dccp_conn_req_seqnum);
+		}
+	}
+
+	/* XXX mss */
+	return (tpi_mp);
+}
+
+/*
+ * Handle a REQUEST on an AF_INET socket.
+ */
+static mblk_t *
+dccp_conn_create_v4(conn_t *lconnp, conn_t *connp, mblk_t *mp,
+    ip_recv_attr_t *ira)
+{
+	dccp_t		*ldccp = lconnp->conn_dccp;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	ipha_t		*ipha;
+	mblk_t		*tpi_mp;
+	sin_t		sin;
+
+	ASSERT(ira->ira_flags & IRAF_IS_IPV4);
+	ipha = (ipha_t *)mp->b_rptr;
+
+	connp->conn_ipversion = IPV4_VERSION;
+	IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_laddr_v6);
+	IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_faddr_v6);
+	connp->conn_saddr_v6 = connp->conn_laddr_v6;
+
+	sin = sin_null;
+	sin.sin_addr.s_addr = connp->conn_faddr_v4;
+	sin.sin_port = connp->conn_fport;
+	sin.sin_family = AF_INET;
+
+	if (lconnp->conn_recv_ancillary.crb_recvdstaddr) {
+		cmn_err(CE_NOTE, "ancillary");
+
+		sin_t   sind;
+
+		sind = sin_null;
+		sind.sin_addr.s_addr = connp->conn_laddr_v4;
+		sind.sin_port = connp->conn_lport;
+		sind.sin_family = AF_INET;
+
+		tpi_mp = mi_tpi_extconn_ind(NULL,
+		    (char *)&sind, sizeof (sin_t), (char *)&dccp,
+		    (t_scalar_t)sizeof (intptr_t), (char *)&sind,
+		    sizeof (sin_t), (t_scalar_t)ldccp->dccp_conn_req_seqnum);
+
+	} else {
+		tpi_mp = mi_tpi_conn_ind(NULL,
+		(char *)&sin, sizeof (sin_t),
+		(char *)&dccp, (t_scalar_t)sizeof (intptr_t),
+		(t_scalar_t)ldccp->dccp_conn_req_seqnum);
+	}
+
+	/* XXX mss */
+
+	return (tpi_mp);
+}
+
+static void
+dccp_input_listener(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
+{
+	conn_t		*lconnp = (conn_t *)arg;
+	conn_t		*econnp;
+	dccp_t		*listener = lconnp->conn_dccp;
+	dccp_t		*eager;
+	dccp_stack_t	*dccps = listener->dccp_dccps;
+	ip_stack_t	*ipst = dccps->dccps_netstack->netstack_ip;
+	dccpha_t	*dccpha;
+	dccpha_ext_t	*dccpha_ext;
+	squeue_t	*new_sqp;
+	mblk_t		*tpi_mp;
+	mblk_t		*mp1;
+	uint64_t	seq;
+	uint_t		ifindex = ira->ira_ruifindex;
+	uint_t		ip_hdr_len;
+	uint_t		type;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener");
+
+
+	DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, lconnp->conn_ixa,
+	    __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, listener,
+	    __dtrace_dccp_dccph_t *, dccpha);
+
+	/* Basic checks on packet */
+	if (dccp_check_input(lconnp, mp, ira) == 0) {
+		cmn_err(CE_NOTE, "dccp_check_input failed.");
+		freemsg(mp);
+		return;
+	}
+
+	ip_hdr_len = ira->ira_ip_hdr_length;
+	dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
+	dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
+	type = (uint_t)dccpha->dha_type;
+
+	if (type != DCCP_PKT_REQUEST) {
+		if (type != DCCP_PKT_RESET) {
+			listener->dccp_reset_code = DCCP_RESET_NO_CONNECTION;
+			dccp_xmit_listeners_reset(mp, ira, ipst, lconnp);
+		}
+
+		freemsg(mp);
+		return;
+	}
+
+	/* XXX memory pressure */
+
+	/* XXX request defense */
+
+	/* XXX number of connections per listener */
+
+	ASSERT(ira->ira_sqp != NULL);
+	new_sqp = ira->ira_sqp;
+
+	econnp = (conn_t *)dccp_get_conn(arg2, dccps);
+	if (econnp == NULL) {
+		cmn_err(CE_NOTE, "econnp not found (eager)");
+		goto error2;
+	}
+
+	ASSERT(econnp->conn_netstack == lconnp->conn_netstack);
+	econnp->conn_sqp = new_sqp;
+	econnp->conn_initial_sqp = new_sqp;
+	econnp->conn_ixa->ixa_sqp = new_sqp;
+
+	econnp->conn_fport = dccpha->dha_lport;
+	econnp->conn_lport = dccpha->dha_fport;
+
+	error = conn_inherit_parent(lconnp, econnp);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "conn_inherit_parent failed");
+		goto error3;
+	}
+
+	/* We already know the laddr of the new connection is ours */
+	econnp->conn_ixa->ixa_src_generation = ipst->ips_src_generation;
+
+	ASSERT(OK_32PTR(mp->b_rptr));
+	ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ||
+	    IPH_HDR_VERSION(mp->b_rptr) == IPV6_VERSION);
+
+	if (lconnp->conn_family == AF_INET) {
+		ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION);
+		tpi_mp = dccp_conn_create_v4(lconnp, econnp, mp, ira);
+	} else {
+		tpi_mp = dccp_conn_create_v6(lconnp, econnp, mp, ira);
+	}
+
+	if (tpi_mp == NULL) {
+		cmn_err(CE_NOTE, "tpi_mo == NULL");
+		goto error3;
+	}
+
+	eager = econnp->conn_dccp;
+	SOCK_CONNID_INIT(eager->dccp_connid);
+
+	dccp_init_values(eager, listener);
+
+	ASSERT((econnp->conn_ixa->ixa_flags &
+	    (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE |
+	    IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)) ==
+	    (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE |
+	    IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO));
+
+	if (!(ira->ira_flags & IRAF_IS_IPV4) && econnp->conn_bound_if == 0) {
+		if (IN6_IS_ADDR_LINKSCOPE(&econnp->conn_faddr_v6) ||
+		    IN6_IS_ADDR_LINKSCOPE(&econnp->conn_laddr_v6)) {
+			econnp->conn_incoming_ifindex = ifindex;
+			econnp->conn_ixa->ixa_flags |= IXAF_SCOPEID_SET;
+			econnp->conn_ixa->ixa_scopeid = ifindex;
+		}
+	}
+
+	if (ira->ira_cred != NULL) {
+		mblk_setcred(tpi_mp, ira->ira_cred, ira->ira_cpid);
+	}
+
+	if (IPCL_IS_NONSTR(lconnp)) {
+		econnp->conn_flags |= IPCL_NONSTR;
+	}
+
+	/* XXX dccps is right? */
+	dccp_bind_hash_insert(&dccps->dccps_bind_fanout[
+	    DCCP_BIND_HASH(econnp->conn_lport, dccps->dccps_bind_fanout_size)],
+	    eager, 0);
+
+	/* XXX CLUSTER */
+
+	SOCK_CONNID_BUMP(eager->dccp_connid);
+
+	error = dccp_set_destination(eager);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "dccp_set_destination failed.");
+		DCCPS_BUMP_MIB(dccps, dccpAttemptFails);
+		/* Undo the bind_hash_insert */
+		dccp_bind_hash_remove(eager);
+		goto error3;
+	}
+
+	/* Eager lock */
+	CONN_INC_REF(lconnp);
+
+	/* Set tcp_listener before adding it to tcp_conn_fanout */
+	eager->dccp_listener = listener;
+	eager->dccp_saved_listener = listener;
+
+	eager->dccp_conn_req_seqnum = listener->dccp_conn_req_seqnum;
+	if (++listener->dccp_conn_req_seqnum == -1) {
+		/*
+		 * -1 is "special" and defined in TPI as something
+		 * that should never be used in T_CONN_IND
+		 */
+		++listener->dccp_conn_req_seqnum;
+	}
+
+	/* XXX SYN DEFENSE */
+
+	seq = ntohs(dccpha->dha_seq);
+	seq = seq << 32;
+	seq |= ntohl(dccpha_ext->dha_ext_seq);
+
+	/* ISS was set in set_destination */
+	eager->dccp_gar = eager->dccp_iss;
+	eager->dccp_gsr = seq;
+	eager->dccp_osr = seq;
+
+	/* Process all DCCP options */
+	error = dccp_process_options(eager, dccpha);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "dccp_process_options failed.");
+		mp1 = dccp_generate_reset(econnp);
+		eager->dccp_state = DCCPS_CLOSED;
+		if (mp1 == NULL) {
+			cmn_err(CE_NOTE, "dccp_generate_reset failed.");
+			goto error;	
+		}
+
+		ip_xmit_attr_t	 *ixa = econnp->conn_ixa;
+
+		ixa->ixa_pktlen = msgdsize(mp1);
+		(void) conn_ip_output(mp1, ixa);
+
+		return;
+	}
+
+	eager->dccp_state = DCCPS_RESPOND;
+	DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *,
+	    econnp->conn_ixa, void, NULL, dccp_t *, eager, void, NULL,
+	    int32_t, DCCPS_LISTEN);
+
+	mp1 = dccp_generate_response(econnp, mp);
+	if (mp1 == NULL) {
+		cmn_err(CE_NOTE, "dccp_generate_packet failed");
+		/*
+                 * Increment the ref count as we are going to
+                 * enqueueing an mp in squeue
+                 */
+		CONN_INC_REF(econnp);
+		goto error;
+	}
+
+	CONN_INC_REF(econnp);
+
+	error = ipcl_conn_insert(econnp);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "ipcl_conn_insert(econnp) failed");
+		goto error;
+	}
+
+	ASSERT(econnp->conn_ixa->ixa_notify_cookie == econnp->conn_dccp);
+	freemsg(mp);
+
+        /*
+         * Send the RESPONSE. Use the right squeue so that conn_ixa is
+         * only used by one thread at a time.
+         */
+	if (econnp->conn_sqp == lconnp->conn_sqp) {
+		DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *,
+		    econnp->conn_ixa, __dtrace_dccp_void_ip_t *, mp1->b_rptr,
+		    dccp_t *, eager, __dtrace_dccp_dccph_t *,
+		    &mp1->b_rptr[econnp->conn_ixa->ixa_ip_hdr_length]);
+		(void) conn_ip_output(mp1, econnp->conn_ixa);
+		CONN_DEC_REF(econnp);
+	} else {
+		SQUEUE_ENTER_ONE(econnp->conn_sqp, mp1, dccp_send_synack,
+		    econnp, NULL, SQ_PROCESS, SQTAG_DCCP_SEND_RESPONSE);
+	}
+
+	return;
+error:
+	freemsg(mp1);
+error2:
+	CONN_DEC_REF(econnp);
+error3:
+	freemsg(mp);
+}
+
+void
+dccp_input_listener_unbound(void *arg, mblk_t *mp, void *arg2,
+    ip_recv_attr_t *ira)
+{
+	conn_t		*connp = (conn_t *)arg;
+	squeue_t	*sqp = (squeue_t *)arg2;
+	squeue_t	*new_sqp;
+	uint32_t	conn_flags;
+
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener_unbound");
+
+	ASSERT(ira->ira_sqp != NULL);
+	new_sqp = ira->ira_sqp;
+
+	if (connp->conn_fanout == NULL) {
+		goto done;
+	}
+
+	/*
+	 * Bind to correct squeue.
+	 */
+	if (!(connp->conn_flags & IPCL_FULLY_BOUND)) {
+		cmn_err(CE_NOTE, "not fully bound");
+
+		mutex_enter(&connp->conn_fanout->connf_lock);
+		mutex_enter(&connp->conn_lock);
+
+		if (connp->conn_ref != 4 ||
+		    connp->conn_dccp->dccp_state != DCCPS_LISTEN) {
+			mutex_exit(&connp->conn_lock);
+			mutex_exit(&connp->conn_fanout->connf_lock);
+			goto done;
+		}
+
+		if (connp->conn_sqp != new_sqp) {
+			while (connp->conn_sqp != new_sqp) {
+				(void) casptr(&connp->conn_sqp, sqp, new_sqp);
+			}
+			connp->conn_ixa->ixa_sqp = new_sqp;
+		}
+
+		do {
+			conn_flags = connp->conn_flags;
+			conn_flags |= IPCL_FULLY_BOUND;
+			(void) cas32(&connp->conn_flags, connp->conn_flags,
+			    conn_flags);
+		} while (!(connp->conn_flags & IPCL_FULLY_BOUND));
+
+		mutex_exit(&connp->conn_lock);
+		mutex_exit(&connp->conn_fanout->connf_lock);
+
+		connp->conn_recv = dccp_input_listener;
+	}
+
+done:
+	if (connp->conn_sqp != sqp) {
+		CONN_INC_REF(connp);
+		SQUEUE_ENTER_ONE(connp->conn_sqp, mp, connp->conn_recv, connp,
+		    ira, SQ_FILL, SQTAG_DCCP_CONN_REQ_UNBOUND);
+	} else {
+		dccp_input_listener(connp, mp, sqp, ira);
+	}
+}
+
+boolean_t
+dccp_verifyicmp(conn_t *connp, void *arg2, icmph_t *icmph, icmp6_t *icmp6,
+    ip_recv_attr_t *ira)
+{
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_verifyicmp");
+
+	return (B_TRUE);
+}
+
+/*
+ * Basic sanity checks on all input packets.
+ */
+static int
+dccp_check_input(conn_t *connp, mblk_t *mp, ip_recv_attr_t *ira)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccpha_t	*dccpha;
+	uint32_t	size;
+	uint32_t	offset_size;
+	uint_t		ip_hdr_len = ira->ira_ip_hdr_length;
+
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_check_input");
+
+	size = msgdsize(mp) - (ip_hdr_len);
+	dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
+	offset_size = dccpha->dha_offset * 4;
+
+	cmn_err(CE_NOTE, "size: %d", size);
+	cmn_err(CE_NOTE, "offset_size: %d", offset_size);
+
+	/* Is packet shorter then 12 bytes? */
+	if (size < DCCP_MIN_HEADER_LENGTH) {
+		cmn_err(CE_NOTE, "header < 12");
+		return (0);
+	}
+
+	/* Data offset is greater then the packet itself */
+	if (offset_size > size) {
+		cmn_err(CE_NOTE, "offset > size");
+		return (0);
+	}
+
+	/* Check if known packet type */
+	if (dccpha->dha_type > DCCP_PKT_SYNCACK) {
+		cmn_err(CE_NOTE, "type unknown");
+		return (0);
+	}
+
+	/*
+	 * Check data offset for this packet type and
+	 * Data, Ack, or DataAck and P.X == 0
+	 */
+	if (dccpha->dha_x == 0) {
+		switch (dccpha->dha_type) {
+		case DCCP_PKT_DATA:
+			if (size < 12 || offset_size < 12)
+				return (0);
+			break;
+		case DCCP_PKT_ACK:
+		case DCCP_PKT_DATAACK:
+			if (size < 16 || offset_size < 16)
+				return (0);
+			break;
+		default:
+			return (0);
+		}
+	} else {
+		switch (dccpha->dha_type) {
+		case DCCP_PKT_REQUEST:
+			if (size < 20 || offset_size < 20)
+				return (0);
+			break;
+		case DCCP_PKT_RESPONSE:
+		case DCCP_PKT_RESET:
+			if (size < 28 || offset_size < 28)
+				return (0);
+			break;
+		case DCCP_PKT_DATA:
+			if (size < 16 || offset_size < 16)
+				return (0);
+			break;
+		case DCCP_PKT_ACK:
+		case DCCP_PKT_DATAACK:
+		case DCCP_PKT_CLOSEREQ:
+		case DCCP_PKT_CLOSE:
+		case DCCP_PKT_SYNC:
+		case DCCP_PKT_SYNCACK:
+			if (size < 24 || offset_size < 24)
+				return (0);
+			break;
+		default:
+			return (0);
+		}
+	}
+
+	/* Checksum coverage check */
+	if (dccpha->dha_cscov != 0 && ((dccpha->dha_offset +
+	    dccpha->dha_cscov - 1) * 4) > size) {
+		cmn_err(CE_NOTE, "cscov too large");
+		return (0);
+	}
+
+	return (1);
+}
+
+/*
+ * After a request-response-ack all packets end up here.
+ */
+void
+dccp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
+{
+	conn_t		*connp = (conn_t *)arg;
+	squeue_t	*sqp = (squeue_t *)arg2;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	dccpha_t	*dccpha;
+	dccpha_ack_t	*dccpha_ack;
+	dccpha_ext_t	*dccpha_ext;
+	mblk_t		*mp1;
+	uint64_t	seq_seq;
+	uint64_t	seq_ack;
+	uchar_t		*iphdr;
+	uchar_t		*rptr;
+	sock_upcalls_t	*sockupcalls;
+	ip_pkt_t	ipp;
+	uint_t		ip_hdr_len;
+	uint_t		len;
+	int		seg_len;
+	int		pkt_len;
+	int		hdr_length;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_input_data");
+
+	ASSERT(DB_TYPE(mp) == M_DATA);
+	ASSERT(mp->b_next == NULL);
+
+	iphdr = mp->b_rptr;
+	rptr = mp->b_rptr;
+	ASSERT(OK_32PTR(rptr));
+
+	/* Check basic characteristics */
+	if (dccp_check_input(connp, mp, ira) == 0) {
+		cmn_err(CE_NOTE, "rejected packet");
+		return;
+	}
+
+	ip_hdr_len = ira->ira_ip_hdr_length;
+	if (connp->conn_recv_ancillary.crb_all != 0) {
+		/*
+		 * Record packet information in the ip_pkt_t
+		 */
+		ipp.ipp_fields = 0;
+		if (ira->ira_flags & IRAF_IS_IPV4) {
+			(void) ip_find_hdr_v4((ipha_t *)rptr, &ipp,
+			    B_FALSE);
+		} else {
+			uint8_t nexthdrp;
+
+			/*
+			 * IPv6 packets can only be received by applications
+			 * that are prepared to receive IPv6 addresses.
+			 * The IP fanout must ensure this.
+			 */
+			ASSERT(connp->conn_family == AF_INET6);
+
+			(void) ip_find_hdr_v6(mp, (ip6_t *)rptr, B_TRUE, &ipp,
+			     &nexthdrp);
+			ASSERT(nexthdrp == IPPROTO_DCCP);
+
+			/* Could have caused a pullup? */
+			iphdr = mp->b_rptr;
+			rptr = mp->b_rptr;
+		}
+	}
+
+	len = ip_hdr_len;
+	dccpha = (dccpha_t *)&rptr[len];
+
+	ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
+	seg_len = (int)(mp->b_wptr - rptr) -
+	    (ip_hdr_len + DCCP_HDR_LENGTH(dccpha));
+	if ((mp1 = mp->b_cont) != NULL && mp1->b_datap->db_type == M_DATA) {
+		do {
+			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
+			    (uintptr_t)INT_MAX);
+			seg_len += (int)(mp1->b_wptr - mp1->b_rptr);
+		} while ((mp1 = mp1->b_cont) != NULL &&
+		    mp1->b_datap->db_type == M_DATA);
+	}
+
+	DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa,
+	    __dtrace_dccp_void_ip_t *, iphdr, dccp_t *, dccp,
+	    __dtrace_dccp_dccph_t *, dccpha);
+
+	if (sqp != NULL) {
+		dccp->dccp_last_recv_time = LBOLT_FASTPATH;
+	}
+
+	BUMP_LOCAL(dccp->dccp_ibsegs);
+	DTRACE_PROBE2(dccp__trace__recv, mblk_t *, mp, dccp_t *, dccp);
+
+	sockupcalls = connp->conn_upcalls;
+
+	len += sizeof (dccpha_t);
+	dccpha_ext = (dccpha_ext_t *)&rptr[len];
+
+	/*
+	 * Sequence number.
+	 */
+	if (dccpha->dha_x == 1) {
+		seq_seq = ntohs(dccpha->dha_seq);
+		seq_seq = seq_seq << 32;
+		seq_seq |= ntohl(dccpha_ext->dha_ext_seq);
+	} else {
+		/* XXX */
+	}
+
+	dccp->dccp_gsr = seq_seq;
+
+	/*
+	 * Acknowledgement Number.
+	 */
+	if (dccpha->dha_type != DCCP_PKT_DATA) {
+		dccpha_ack = (dccpha_ack_t *)&rptr[ip_hdr_len +
+		    sizeof (dccpha_t) + sizeof (dccpha_ext_t)];
+		seq_ack = ntohs(dccpha_ack->dha_ack_high);
+		seq_ack = seq_ack << 32;
+		seq_ack |= ntohl(dccpha_ack->dha_ack_low);
+
+		dccp->dccp_gar = seq_ack;
+	}
+
+
+	switch (dccp->dccp_state) {
+	case DCCPS_REQUEST:
+		cmn_err(CE_NOTE, "DCCPS_REQUEST");
+		break;
+	case DCCPS_RESPOND:
+		cmn_err(CE_NOTE, "DCCPS_RESPOND");
+		break;
+	case DCCPS_PARTOPEN:
+		cmn_err(CE_NOTE, "DCCPS_PARTOPEN");
+		break;
+	case DCCPS_LISTEN:
+		cmn_err(CE_NOTE, "DCCPS_LISTEN");
+		break;
+	case DCCPS_BOUND:
+		cmn_err(CE_NOTE, "DCCPS_BOUND");
+		break;
+	case DCCPS_OPEN:
+		cmn_err(CE_NOTE, "DCCPS_OPEN");
+		break;
+	default:
+		cmn_err(CE_NOTE, "Unknow state");
+		break;
+	}
+
+	/*
+	 * Check for unexpected packet types.
+	 */
+	if ((dccp->dccp_active_open == B_FALSE &&
+	    (dccpha->dha_type == DCCP_PKT_RESPONSE ||
+	    dccpha->dha_type == DCCP_PKT_CLOSEREQ)) ||
+	    (dccp->dccp_state >= DCCPS_OPEN &&
+	    (dccpha->dha_type == DCCP_PACKET_REQUEST ||
+	    dccpha->dha_type == DCCP_PACKET_RESPONSE) &&
+	    seq_seq >= dccp->dccp_osr) ||
+	    (dccp->dccp_state == DCCPS_RESPOND &&
+	    dccpha->dha_type == DCCP_PACKET_DATA)) {
+		mblk_t	*sync_mp;
+
+		sync_mp = dccp_generate_sync(connp);
+		if (sync_mp != NULL)
+			dccp_send_data(dccp, sync_mp);
+		return;
+	}
+
+	/*
+	 * Process options.
+	 */
+	error = dccp_process_options(dccp, dccpha);
+	if (error != 0) {
+		mblk_t	*reset_mp;
+
+		cmn_err(CE_NOTE, "dccp_process_options failed.");
+
+		reset_mp = dccp_generate_reset(connp);
+		dccp->dccp_state = DCCPS_CLOSED;
+		if (reset_mp != NULL) {
+			ip_xmit_attr_t	*ixa = connp->conn_ixa;
+
+			ixa->ixa_pktlen = msgdsize(reset_mp);
+			(void) conn_ip_output(reset_mp, ixa);
+		}
+
+		return;
+	}
+
+	if (dccp->dccp_state == DCCPS_RESPOND) {
+		dccp->dccp_state = DCCPS_OPEN;
+		//dccp->dccp_osr = DCCP_SEQNO_GET(mp);
+
+		if (dccp->dccp_active_open) {
+			cmn_err(CE_NOTE, "dccp_active_open");
+			if (!dccp_conn_con(dccp, iphdr, mp, NULL, ira)) {
+				cmn_err(CE_NOTE, "dccp_conn_con failed");
+				freemsg(mp);
+				dccp->dccp_state = DCCPS_RESPOND;
+				return;
+			}
+
+			DTRACE_DCCP5(connect__established, mblk_t *, NULL,
+			    ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *,
+			    iphdr, dccp_t *, dccp, dccph_t *, dccpha);
+		} else if (IPCL_IS_NONSTR(connp)) {
+			/*
+			 * Passive open socket
+			 */
+			cmn_err(CE_NOTE, "nonstr");
+
+			CONN_INC_REF(connp);
+
+			if (!dccp_newconn_notify(dccp, ira)) {
+				cmn_err(CE_NOTE, "dccp_newconn_notify failed");
+				dccp->dccp_state = DCCPS_RESPOND;
+				freemsg(mp);
+
+				CONN_DEC_REF(connp);
+				return;
+			}
+
+			/*
+			 * dccp_newconn_notify() changes conn_upcalls.
+			 */
+			if (connp->conn_upcalls != NULL) {
+				sockupcalls = connp->conn_upcalls;
+			}
+
+			DTRACE_DCCP5(accept__established, mlbk_t *, NULL,
+			    ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *,
+			    iphdr, dccp_t *, dccp, dccph_t *, dccpha);
+		} else {
+			cmn_err(CE_NOTE, "str stream");
+			dccp_t	*listener = dccp->dccp_listener;
+
+			ASSERT(mp != NULL);
+			CONN_INC_REF(connp);
+		}
+	}
+
+	switch (dccpha->dha_type) {
+	case DCCP_PKT_REQUEST:
+		cmn_err(CE_NOTE, "DCCP_REQUEST");
+		break;
+	case DCCP_PKT_RESPONSE:
+		cmn_err(CE_NOTE, "DCCP_RESPONSE");
+		break;
+	case DCCP_PKT_DATA:
+		cmn_err(CE_NOTE, "DCCP_DATA");
+		break;
+	case DCCP_PKT_ACK:
+		cmn_err(CE_NOTE, "DCCP_PKT_ACK");
+		break;
+	case DCCP_PKT_DATAACK:
+		cmn_err(CE_NOTE, "DCCP_DATAACK");
+		break;
+	case DCCP_PKT_CLOSEREQ:
+		cmn_err(CE_NOTE, "DCCP_CLOSEREQ");
+		break;
+	case DCCP_PKT_CLOSE:
+		cmn_err(CE_NOTE, "DCCP_CLOSE");
+		break;
+	case DCCP_PKT_RESET:
+		cmn_err(CE_NOTE, "DCCP_RESET");
+		break;
+	case DCCP_PKT_SYNC:
+		cmn_err(CE_NOTE, "DCCP_SYNC");
+		break;
+	case DCCP_PKT_SYNCACK:
+		cmn_err(CE_NOTE, "DCCP_SYNCACK");
+		break;
+	default:
+		break;
+	}
+
+	switch (dccpha->dha_type) {
+	/* case DCCP_PKT_ACK: { */
+	case DCCP_PKT_DATAACK: {
+		mblk_t	*ack_mp;
+
+		ack_mp = dccp_generate_ack(connp);
+		if (ack_mp != NULL)
+			dccp_send_data(dccp, ack_mp);
+
+		dccp->dccp_state = DCCPS_OPEN;
+		return;
+	}
+	case DCCP_PKT_CLOSE: {
+		mblk_t	*reset_mp;
+
+		dccp->dccp_reset_code = DCCP_RESET_CLOSED;
+		dccp->dccp_reset_data[0] = 0;
+		dccp->dccp_reset_data[1] = 0;
+		dccp->dccp_reset_data[2] = 0;
+		reset_mp = dccp_generate_reset(connp);
+		dccp_send_data(dccp, reset_mp);
+		dccp->dccp_state = DCCPS_CLOSED;
+		return;
+	}
+	default:
+		break;
+	}
+
+	hdr_length = ira->ira_ip_hdr_length;
+	hdr_length += DCCP_HDR_LENGTH(dccpha);
+	pkt_len = ira->ira_pktlen;
+
+	mp->b_wptr = rptr + pkt_len;
+	mp->b_rptr = (uchar_t *)&mp->b_rptr[hdr_length];
+	pkt_len -= hdr_length;
+
+	if (IPCL_IS_NONSTR(connp)) {
+		/*
+		 * Non-STREAMS socket.
+		 */
+		boolean_t	push;
+		int		error;
+
+		if ((*sockupcalls->su_recv)(connp->conn_upper_handle,
+		    mp, pkt_len, 0, &error, NULL) <= 0) {
+			cmn_err(CE_NOTE, "su_recv failed");
+			ASSERT(error != EOPNOTSUPP);
+		}
+	} else if (dccp->dccp_listener != NULL) {
+		// dccp_recv_enqueue(dccp, mp, seq_len, ira->ira_cred);
+	} else {
+		/*
+		 * Active-STREAMS socket.
+		 */
+	}
+}
--- /dev/null	2012-08-18 10:37:10.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_misc.c	2012-08-18 10:37:10.266551197 +0000
@@ -0,0 +1,124 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * This file contains various helper functions.
+ */
+
+#include <sys/types.h>
+#include <sys/strlog.h>
+#include <sys/policy.h>
+#include <sys/strsun.h>
+
+#include <inet/common.h>
+#include <inet/dccp_impl.h>
+
+/*
+ * When a CPU is added, we need to allocate the per CPU stats struct.
+ */
+void
+dccp_stack_cpu_add(dccp_stack_t *dccps, processorid_t cpu_seqid)
+{
+	int	i;
+
+	if (cpu_seqid < dccps->dccps_sc_cnt) {
+		return;
+	}
+
+	for (i = dccps->dccps_sc_cnt; i <= cpu_seqid; i++) {
+		ASSERT(dccps->dccps_sc[i] == NULL);
+		dccps->dccps_sc[i] = kmem_zalloc(sizeof (dccp_stats_cpu_t),
+		    KM_SLEEP);
+	}
+
+	membar_producer();
+	dccps->dccps_sc_cnt = cpu_seqid + 1;
+}
+
+/*
+ * Diagnostic routine used to return a string associated with the dccp state.
+ */
+char *
+dccp_display(dccp_t *dccp, char *sup_buf, char format)
+{
+	conn_t		*connp;
+	in6_addr_t	local;
+	in6_addr_t	remote;
+	char		local_addrbuf[INET6_ADDRSTRLEN];
+	char		remote_addrbuf[INET6_ADDRSTRLEN];
+	char		priv_buf[INET6_ADDRSTRLEN * 2 + 80];
+	char		buf1[30];
+	char		*buf;
+	char		*cp;
+
+	if (sup_buf != NULL) {
+		buf = sup_buf;
+	} else {
+		buf = priv_buf;
+	}
+
+	if (dccp == NULL) {
+		return ("NULL_DCCP");
+	}
+
+	connp = dccp->dccp_connp;
+	switch (dccp->dccp_state) {
+	case DCCPS_CLOSED:
+		cp = "DCCP_CLOSED";
+		break;
+	default:
+		(void) mi_sprintf(buf1, "DCCPUnkState(%d)", dccp->dccp_state);
+		cp = buf1;
+		break;
+	}
+
+	switch (format) {
+	case DISP_ADDR_AND_PORT:
+		if (connp->conn_ipversion == IPV4_VERSION) {
+			IN6_IPADDR_TO_V4MAPPED(connp->conn_laddr_v4, &local);
+			IN6_IPADDR_TO_V4MAPPED(connp->conn_faddr_v4, &remote);
+		} else {
+			local = connp->conn_laddr_v6;
+			remote = connp->conn_faddr_v6;
+		}
+
+		(void) inet_ntop(AF_INET6, &local, local_addrbuf,
+		    sizeof (local_addrbuf));
+		(void) inet_ntop(AF_INET6, &remote, remote_addrbuf,
+		    sizeof (remote_addrbuf));
+		(void) mi_sprintf(buf, "[%s.%u, %s.%u] %s",
+		    local_addrbuf, ntohs(connp->conn_lport), remote_addrbuf,
+		    ntohs(connp->conn_fport), cp);
+		break;
+	case DISP_PORT_ONLY:
+	default:
+		(void) mi_sprintf(buf, "[%u, %u] %s",
+		    ntohs(connp->conn_lport), ntohs(connp->conn_fport), cp);
+		break;
+	}
+
+	return (buf);
+}
--- /dev/null	2012-08-18 10:37:10.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_opt_data.c	2012-08-18 10:37:10.404969938 +0000
@@ -0,0 +1,327 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * This file contains functions related to getting and setting options
+ * thought the getsockopt and setsockopt socket functions.
+ */
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#define	_SUN_TPI_VERSION 2
+#include <sys/tihdr.h>
+#include <sys/xti_xtiopt.h>
+#include <sys/xti_inet.h>
+#include <sys/policy.h>
+
+#include <inet/common.h>
+#include <inet/dccp_impl.h>
+#include <inet/ip.h>
+#include <inet/optcom.h>
+#include <netinet/ip.h>
+
+#include <sys/cmn_err.h>
+
+static int dccp_opt_default(queue_t *, int, int, uchar_t *);
+
+/*
+ * Supported options.
+ */
+opdes_t dccp_opt_arr[] = {
+{ SO_DEBUG, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
+}; 
+
+/*
+ * Supported levels.
+ */
+optlevel_t dccp_valid_levels_arr[] = {
+	SOL_SOCKET,
+};
+
+#define	DCCP_OPT_ARR_CNT	A_CNT(dccp_opt_arr)
+#define	DCCP_VALID_LEVELS_CNT	A_CNT(dccp_valid_levels_arr)
+
+uint_t dccp_max_optsize;
+
+/*
+ * Options database object.
+ */
+optdb_obj_t dccp_opt_obj = {
+	dccp_opt_default,
+	dccp_tpi_opt_get,
+	dccp_tpi_opt_set,
+	DCCP_OPT_ARR_CNT,
+	dccp_opt_arr,
+	DCCP_VALID_LEVELS_CNT,
+	dccp_valid_levels_arr,
+};
+
+/*
+ * Default value for certain options.
+ */
+int
+dccp_opt_default(queue_t *q, int level, int name, uchar_t *ptr)
+{
+	dccp_stack_t	*dccps = Q_TO_DCCP(q)->dccp_dccps;
+	int32_t		*il = (int32_t *)ptr;
+
+	return (sizeof (int));
+}
+
+int
+dccp_opt_get(conn_t *connp, int level, int name, uchar_t *ptr)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	conn_opt_arg_t	coas;
+	int		*i1 = (int *)ptr;
+	int		retval;
+
+	coas.coa_connp = connp;
+	coas.coa_ixa = connp->conn_ixa;
+	coas.coa_ipp = &connp->conn_xmit_ipp;
+	coas.coa_ancillary = B_FALSE;
+	coas.coa_changed = 0;
+
+	switch (level) {
+	case SOL_SOCKET:
+		break;
+	case IPPROTO_DCCP:
+		switch (name) {
+		case DCCP_NOTIFY_THRESHOLD:
+			*i1 = dccp->dccp_first_timer_threshold;
+			return (sizeof (int));
+		case DCCP_ABORT_THRESHOLD:
+			*i1 = dccp->dccp_second_timer_threshold;
+			return (sizeof (int));
+		case DCCP_CONN_NOTIFY_THRESHOLD:
+			*i1 = dccp->dccp_first_ctimer_threshold;
+			return (sizeof (int));
+		case DCCP_CONN_ABORT_THRESHOLD:
+			*i1 = dccp->dccp_second_ctimer_threshold;
+			return (sizeof (int));
+		case DCCP_KEEPALIVE_THRESHOLD:
+			*i1 = dccp->dccp_ka_interval;
+			return (sizeof (int));
+		case DCCP_KEEPINTVL:
+			*i1 = dccp->dccp_ka_rinterval / 1000;
+			return (sizeof (int));
+		}
+		break;
+	case IPPROTO_IP:
+		break;
+	case IPPROTO_IPV6:
+		break;
+	}
+
+	mutex_enter(&connp->conn_lock);
+	retval = conn_opt_get(&coas, level, name, ptr);
+	mutex_exit(&connp->conn_lock);
+
+	return (retval);
+}
+
+/* ARGSUSED */
+int
+dccp_opt_set(conn_t *connp, uint_t optset_context, int level, int name,
+    uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp,
+    void *thisdg_attrs, cred_t *cr)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	conn_opt_arg_t	coas;
+	uint32_t	val = *((uint32_t *)invalp);
+	int		*i1 = (int *)invalp;
+	boolean_t	onoff = (*i1 == 0) ? B_FALSE : B_TRUE;
+	boolean_t	checkonly = B_FALSE;
+	int		error;
+
+	coas.coa_connp = connp;
+	coas.coa_ixa = connp->conn_ixa;
+	coas.coa_ipp = &connp->conn_xmit_ipp;
+	coas.coa_ancillary = B_FALSE;
+	coas.coa_changed = 0;
+
+	switch (optset_context) {
+	case SETFN_OPTCOM_CHECKONLY:
+		checkonly = B_TRUE;
+		if (inlen = 0) {
+			*outlenp = 0;
+			return (0);
+		}
+		break;
+	case SETFN_OPTCOM_NEGOTIATE:
+		break;
+	case SETFN_UD_NEGOTIATE:
+	case SETFN_CONN_NEGOTIATE:
+		break;
+	default:
+		/*
+		 * We should never get here.
+		 */
+		*outlenp = 0;
+		return (EINVAL);
+	}
+
+	ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
+	    (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
+
+	/*
+	 * No ancillary data should be sent down.
+	 */
+	ASSERT(thisdg_attrs == NULL);
+
+	switch (level) {
+	case SOL_SOCKET:
+		switch (name) {
+		case SO_KEEPALIVE:
+			if (checkonly) {
+				/* Check only case */
+				break;
+			}
+
+			if (!onoff) {
+				if (connp->conn_keepalive) {
+					if (dccp->dccp_ka_tid != 0) {
+						(void) DCCP_TIMER_CANCEL(dccp,
+						    dccp->dccp_ka_tid);
+						dccp->dccp_ka_tid = 0;
+					}
+					connp->conn_keepalive = 0;
+				}
+				break;
+			}
+
+			if (!connp->conn_keepalive) {
+				/* Crank up the keepalive timer */
+				dccp->dccp_ka_last_intrvl = 0;
+				dccp->dccp_ka_tid = DCCP_TIMER(dccp,
+				    dccp_keepalive_timer, dccp->dccp_ka_interval);
+				connp->conn_keepalive = 1;
+			}
+			break;
+		}
+		break;
+	case IPPROTO_DCCP:
+		switch (name) {
+		case DCCP_NOTIFY_THRESHOLD:
+			if (!checkonly)
+				dccp->dccp_first_timer_threshold = *i1;
+			break;
+		case DCCP_ABORT_THRESHOLD:
+			if (!checkonly)
+				dccp->dccp_second_timer_threshold = *i1;
+		case DCCP_CONN_NOTIFY_THRESHOLD:
+			if (!checkonly)
+				dccp->dccp_first_ctimer_threshold = *i1;
+			break;
+		case DCCP_CONN_ABORT_THRESHOLD:
+			if (!checkonly)
+				dccp->dccp_second_ctimer_threshold = *i1;
+			break;
+		case DCCP_KEEPIDLE:
+			*i1 *= 1000;
+			/* FALLTHRU */
+		case DCCP_KEEPALIVE_THRESHOLD:
+			if (checkonly)
+				break;
+
+			if (*i1 < dccps->dccps_keepalive_interval_low ||
+			    *i1 > dccps->dccps_keepalive_interval_high) {
+				*outlenp = 0;
+				return (EINVAL);
+			}
+
+			if (*i1 != dccp->dccp_ka_interval) {
+				dccp->dccp_ka_interval = *i1;
+
+				if (dccp->dccp_ka_tid != 0) {
+					ASSERT(connp->conn_keepalive);
+					(void) DCCP_TIMER_CANCEL(dccp,
+					    dccp->dccp_ka_tid);
+					dccp->dccp_ka_last_intrvl = 0;
+					dccp->dccp_ka_tid = DCCP_TIMER(dccp,
+					    dccp_keepalive_timer,
+					    dccp->dccp_ka_interval);
+				}
+			}
+			break;
+		}
+		break;
+	case IPPROTO_IP:
+		break;
+	case IPPROTO_IPV6:
+		break;
+	}
+
+	error = conn_opt_set(&coas, level, name, inlen, invalp,
+	    B_FALSE, cr);
+	if (error !=0) {
+		*outlenp = 0;
+		return (error);
+	}
+
+	/*
+	 * Common case of OK return with outval same as inval.
+	 */
+	if (invalp != outvalp) {
+		(void) bcopy(invalp, outvalp, inlen);
+	}
+	*outlenp = inlen;
+
+	if (coas.coa_changed && COA_HEADER_CHANGED) {
+		/* If we are connected we rebuilt the headers */
+		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) &&
+		    !IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
+			error = dccp_build_hdrs(dccp);
+			if (error != 0) {
+				return (error);
+			}
+		}
+	}
+
+	if (coas.coa_changed & COA_ROUTE_CHANGED) {
+		in6_addr_t	nexthop;
+
+		ip_attr_nexthop(&connp->conn_xmit_ipp, connp->conn_ixa,
+		    &connp->conn_faddr_v6, &nexthop);
+
+		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) &&
+		    !IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
+			(void) ip_attr_connect(connp, connp->conn_ixa,
+			    &connp->conn_laddr_v6, &connp->conn_faddr_v6,
+			    &nexthop, connp->conn_fport, NULL, NULL,
+			    IPDF_VERIFY_DST);
+		}
+	}
+
+	/* XXX */
+
+	return (0);
+}
--- /dev/null	2012-08-18 10:37:10.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_options.c	2012-08-18 10:37:10.530253402 +0000
@@ -0,0 +1,336 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner. All rights reserved.
+ */
+
+#include <sys/types.h> 
+#include <sys/stream.h> 
+#include <sys/debug.h> 
+#include <sys/cmn_err.h>
+
+#include <inet/dccp_impl.h>
+#include <inet/dccp_stack.h>
+
+/*
+ * This file contains functions to parse and process DCCP options.
+ */
+
+
+/*
+ * Parse the options in a DCCP header.
+ */
+int
+dccp_parse_options(dccp_t *dccp, dccpha_t *dccpha)
+{
+	uchar_t		*end;
+	uchar_t		*up;
+	uint8_t		dccp_type;
+	uint32_t	option_value;
+	uint8_t		option_type;
+	uint8_t		option_length;
+	int		len;
+	int		i;
+	uchar_t		*value;
+	boolean_t	mandatory = B_FALSE;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp_features.c: dccp_parse_options");
+
+	dccp_type = dccpha->dha_type;
+
+	up = (uchar_t *)dccpha;
+	end = up + DCCP_HDR_LENGTH(dccpha);
+	up += 20;
+
+	while (up != end) {
+		option_length = 0;
+		option_type = *up++;
+
+		if (option_type > 31) {
+			if (up == end) {
+				goto length_error;
+			}
+
+			option_length = *up++;
+			if (option_length < 2) {
+				goto length_error;
+			}
+
+			option_length -= 2;
+			value = up;
+
+			up += option_length;
+
+			/* Ignore options with greater length then header */
+			if (up > end) {
+				goto length_error;
+			}
+		} else {
+			value = up;
+		}
+
+		/* Single byte unknow option */
+		if (option_type >= 3 && option_type <=31) {
+			if (mandatory) {
+				error = DCCP_RESET_MANDATORY_ERROR;
+			} else {
+				error = DCCP_RESET_OPTION_ERROR;
+			}
+
+			dccp->dccp_reset_code = error;
+			/*
+			 * this should be correct:
+			 * dccp->dccp_reset_data[0] = option_type;
+			 * dccp->dccp_reset_data[1] = value[0];
+			 *
+			 * error in the test suit?
+			 */
+			dccp->dccp_reset_data[0] = value[0];
+			dccp->dccp_reset_data[1] = 0;
+			dccp->dccp_reset_data[2] = 0;
+
+			return (-1);
+		}
+
+		if (option_type >= 45 && option_type <=127)
+			break;
+
+
+		switch (option_type) {
+		case DCCP_OPTION_PADDING:
+			cmn_err(CE_NOTE, "PADDING");
+			break;
+		case DCCP_OPTION_MANDATORY:
+			cmn_err(CE_NOTE, "MANDATORY");
+			if (mandatory)
+				goto option_error;
+
+			if (dccp_type != DCCP_PKT_DATA)
+				mandatory = B_TRUE;
+			break;
+		case DCCP_OPTION_SLOW_RECEIVER:
+			cmn_err(CE_NOTE, "SLOW RECEIVER");
+			break;
+		case DCCP_OPTION_CHANGE_L:
+		case DCCP_OPTION_CONFIRM_L:
+		case DCCP_OPTION_CHANGE_R:
+		case DCCP_OPTION_CONFIRM_R:
+			if (dccp_type == DCCP_PACKET_DATA)
+				break;
+
+			if (option_length == 0)
+				goto option_error;
+
+			error = dccp_parse_feature(dccp, option_type, option_length,
+			    value, mandatory);
+			if (error != 0)
+				goto feature_error;
+
+			break;
+		case DCCP_OPTION_INIT_COOKIE:
+			cmn_err(CE_NOTE, "INIT COOKIE");
+			break;
+		case DCCP_OPTION_NDP_COUNT:
+			cmn_err(CE_NOTE, "NDP COUNT");
+			if (option_length > 6)
+				goto option_error;
+			break;
+		case DCCP_OPTION_ACK_VECTOR_1:
+			cmn_err(CE_NOTE, "ACK VECTOR 1");
+			break;
+		case DCCP_OPTION_ACK_VECTOR_2:
+			cmn_err(CE_NOTE, "ACK VECTOR 2");
+			break;
+		case DCCP_OPTION_DATA_DROPPED:
+			cmn_err(CE_NOTE, "DATA DROPPED");
+			break;
+		case DCCP_OPTION_TIMESTAMP:
+			cmn_err(CE_NOTE, "TIMESTAMP");
+			if (option_length != 4)
+				goto option_error;
+
+			option_value = BE32_TO_U32(value);
+			if (option_value == 0) {
+				cmn_err(CE_NOTE, "Zero timestamp");
+				break;
+			}
+
+			dccp->dccp_timestamp_echo = ntohs(option_value);
+			dccp->dccp_timestamp = TICK_TO_MSEC(LBOLT_FASTPATH);
+			break;
+		case DCCP_OPTION_TIMESTAMP_ECHO:
+			cmn_err(CE_NOTE, "TIMESTAMP ECHO");
+			if (option_length != 4 && option_length != 6 &&
+			    option_length != 8) {
+				goto option_error;
+			}
+
+			option_value = BE32_TO_U32(value);
+
+			option_length -= 4;
+			break;
+		case DCCP_OPTION_ELAPSED_TIME:
+			cmn_err(CE_NOTE, "ELAPSES TIME");
+			switch (option_length) {
+			case 2:
+				break;
+			case 4:
+				break;
+			default:
+				goto option_error;
+			}
+			break;
+		case DCCP_OPTION_DATA_CHECKSUM:
+			cmn_err(CE_NOTE, "DATA CHECKSUM");
+			break;
+
+		default:
+			cmn_err(CE_NOTE, "unknow option");
+			break;
+		}
+
+		if (option_type != DCCP_OPTION_MANDATORY) {
+			mandatory = B_FALSE;
+		}
+	}
+
+	if (mandatory)
+		goto option_error;
+
+length_error:
+	return (0);
+
+option_error:
+	if (mandatory) {
+		error = DCCP_RESET_MANDATORY_ERROR;
+	} else {
+		error = DCCP_RESET_OPTION_ERROR;
+	}
+
+	cmn_err(CE_NOTE, "setting error code");
+
+feature_error:
+	dccp->dccp_reset_code = error;
+	dccp->dccp_reset_data[0] = option_type;
+	dccp->dccp_reset_data[1] = option_length > 0 ? value[0] : 0;
+	dccp->dccp_reset_data[2] = option_length > 1 ? value[1] : 0;
+
+	return (-1);
+}
+
+int
+dccp_process_options(dccp_t *dccp, dccpha_t *dccpha)
+{
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp_features.c: dccp_process_features");
+
+	error = dccp_parse_options(dccp, dccpha);
+
+	return (error);
+}
+
+int
+dccp_generate_options(dccp_t *dccp, void **opt, size_t *opt_len)
+{
+	dccp_feature_t	*feature = NULL;
+	uint8_t		buf[1024];	/* XXX */
+	uint8_t		option_type;
+	uint_t		len = 0;
+	uint_t		total_len = 0;
+	void		*options = NULL;
+	int		rest;
+
+	cmn_err(CE_NOTE, "dccp_features.c: dccp_generate_options");
+
+	for (feature = list_head(&dccp->dccp_features); feature;
+	    feature = list_next(&dccp->dccp_features, feature)) {
+		if (feature->df_option == DCCP_OPTION_CHANGE_L) {
+			option_type = DCCP_OPTION_CONFIRM_R;
+		} else {
+			option_type = DCCP_OPTION_CONFIRM_L;
+		}
+/*
+		if (feature->df_mandatory == B_TRUE) {
+			buf[len] = DCCP_OPTION_MANDATORY;
+			len++;
+		}
+*/
+		if (feature->df_type == DCCP_FEATURE_CCID) {
+			cmn_err(CE_NOTE, "FOUND DCCP_FEATURE_CCID");
+
+			buf[len] = option_type;
+			len++;
+			buf[len] = 4;
+			len++;
+			buf[len] = DCCP_FEATURE_CCID;
+			len++;
+			buf[len] = 2;
+			len++;
+		}
+
+		if (feature->df_type == DCCP_FEATURE_ALLOW_SHORT_SEQNOS) {
+			buf[len] = option_type;
+			len++;
+			buf[len] = 4;
+			len++;
+			buf[len] = feature->df_type;
+			len++;
+			buf[len] = 0;
+			len++;
+		}
+
+		if (feature->df_type == DCCP_FEATURE_ECN_INCAPABLE) {
+			buf[len] = option_type;
+			len++;
+			buf[len] = 4;
+			len++;
+			buf[len] = feature->df_type;
+			len++;
+			buf[len] = 1;
+			len++;
+		}
+	}
+
+	if (dccp->dccp_timestamp_echo != 0) {
+		uint32_t	elapsed;
+		int		elapsed_length;
+		clock_t		now;
+
+		buf[len] = DCCP_OPTION_TIMESTAMP_ECHO;
+		len++;
+		buf[len] = 10;
+		len++;
+
+		now = TICK_TO_MSEC(LBOLT_FASTPATH);
+		elapsed =  now - dccp->dccp_timestamp;
+
+
+		dccp->dccp_timestamp_echo = 0;
+	}
+
+	if (len != 0) {
+		total_len = ((len + (4 - 1)) / 4) * 4;
+		options = kmem_zalloc(total_len, KM_SLEEP);
+		if (options == NULL) {
+			cmn_err(CE_NOTE, "kmem_zalloc failed");
+			return (ENOMEM);
+		}
+		memcpy(options, buf, len);
+	}
+
+	*opt = options;
+	*opt_len = len;
+
+	return (0);
+}
--- /dev/null	2012-08-18 10:37:10.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_output.c	2012-08-18 10:37:10.659456059 +0000
@@ -0,0 +1,1034 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * Functions related to the output path.
+ */
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/stropts.h>
+#include <sys/strlog.h>
+#define	_SUN_TPI_VERSION 2
+#include <sys/tihdr.h>
+#include <sys/suntpi.h>
+#include <sys/xti_inet.h>
+#include <sys/squeue_impl.h>
+#include <sys/squeue.h>
+#include <sys/tsol/tnet.h>
+
+#include <inet/common.h>
+#include <inet/dccp_impl.h>
+#include <inet/dccp_stack.h>
+#include <inet/ip.h>
+#include <inet/ipsec_impl.h>
+
+#include <sys/cmn_err.h>
+
+static void	dccp_xmit_early_reset(char *, mblk_t *, uint32_t, uint32_t,
+		    int, ip_recv_attr_t *, ip_stack_t *, conn_t *);
+static boolean_t	dccp_send_rst_chk(dccp_stack_t *);
+static int	dccp_xmit_end(dccp_t *);
+static mblk_t	*dccp_generate_common(conn_t *, uint8_t, uint_t);
+
+/*
+ * STREAMS
+ */
+void
+dccp_wput(queue_t *q, mblk_t *mp)
+{
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_wput");
+}
+
+/*
+ * Fast path write put.
+ */
+void
+dccp_wput_data(dccp_t *dccp, mblk_t *mp, boolean_t urgent)
+{
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_wput_data");
+}
+
+/*
+ *
+ */
+void
+dccp_wput_sock(queue_t *wq, mblk_t *mp)
+{
+	conn_t	*connp = Q_TO_CONN(wq);
+	dccp_t	*dccp = connp->conn_dccp;
+	struct T_capability_req	*car = (struct T_capability_req *)mp->b_rptr;
+
+	cmn_err(CE_NOTE, "dccp_wput_sock");
+
+	ASSERT(wq->q_qinfo == &dccp_sock_winit);
+	wq->q_qinfo = &dccp_winit;
+
+	ASSERT(IPCL_IS_TCP(connp));
+	ASSERT(DCCP_IS_SOCKET(dccp));
+
+	if (DB_TYPE(mp) == M_PCPROTO &&
+	    MBLKL(mp) == sizeof (struct T_capability_req) &&
+	    car->PRIM_type == T_CAPABILITY_REQ) {
+		dccp_capability_req(dccp, mp);
+		return;
+	}
+
+	dccp_wput(wq, mp);
+}
+
+/* ARGSUSED */
+void
+dccp_wput_fallback(queue_t *eq, mblk_t *mp)
+{
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_wput_fallback");
+
+#ifdef DEBUG
+	cmn_err(CE_CONT, "tcp_wput_fallback: Message during fallback \n");
+#endif /* DEBUG */
+
+	freemsg(mp);
+}
+
+/*
+ * Initiate closedown sequence on an active connection.
+ */
+static int
+dccp_xmit_end(dccp_t *dccp)
+{
+	conn_t	*connp = dccp->dccp_connp;
+	mblk_t	*mp;
+
+	/* XXX */
+
+	return (0);
+}
+
+/*
+ * Output fast path.
+ */
+void
+dccp_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
+{
+	conn_t		*connp = (conn_t *)arg;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	dccpha_t	*dccpha;
+	mblk_t		*mp1;
+	ip_xmit_attr_t	*ixa;
+	struct datab	*db;
+	uchar_t		*rptr;
+	uint32_t	msize;
+	uint32_t	sum;
+	int		len;
+	int		plen;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_output");
+
+	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
+	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
+
+	ASSERT(DB_TYPE(mp) == M_DATA);
+	msize = (mp->b_cont == NULL) ? MBLKL(mp) : msgdsize(mp);
+
+	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
+	len = (int)(mp->b_wptr - mp->b_rptr);
+
+	if ((mp->b_cont != NULL) ||
+	    (dccp->dccp_state != DCCPS_OPEN) ||
+	    (len == 0)) {
+		dccp_wput_data(dccp, mp, B_FALSE);
+		return;
+	}
+
+	mp1 = dupb(mp);
+	if (mp1 == NULL) {
+		goto no_memory;
+	}
+
+	/* Adjust header information */
+	dccpha = dccp->dccp_dccpha;
+
+	sum = len + connp->conn_ht_ulp_len + connp->conn_sum;
+	sum = (sum >> 16) + (sum & 0xffff);
+	dccpha->dha_sum = htons(sum);
+
+	DCCPS_BUMP_MIB(dccps, dccpOutDataSegs);
+	DCCPS_UPDATE_MIB(dccps, dccpOutDataBytes, len);
+	BUMP_LOCAL(dccp->dccp_obsegs);
+
+	plen = len + connp->conn_ht_iphc_len;
+
+	ixa = connp->conn_ixa;
+	ixa->ixa_pktlen = plen;
+
+	if (ixa->ixa_flags & IXAF_IS_IPV4) {
+		dccp->dccp_ipha->ipha_length = htons(plen);
+	} else {
+		dccp->dccp_ip6h->ip6_plen = htons(plen - IPV6_HDR_LEN);
+	}
+
+	rptr = mp1->b_rptr;
+	bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
+
+	dccp_send_data(dccp, mp1);
+
+	return;
+
+no_memory:
+	return;
+}
+
+void
+dccp_output_urgent(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
+{
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_output_urgent");
+}
+
+void
+dccp_close_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
+{
+	conn_t		*connp = (conn_t *)arg;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	char		*msg;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_close_output");
+
+	/*
+	 * When a non-STREAMS socket is being closed, it does not always
+	 * stick around waiting for tcp_close_output to run and can therefore
+	 * have dropped a reference already. So adjust the asserts accordingly.
+	 */
+	ASSERT((connp->conn_fanout != NULL &&
+	    connp->conn_ref >= (IPCL_IS_NONSTR(connp) ? 3 : 4)) ||
+	    (connp->conn_fanout == NULL &&
+	    connp->conn_ref >= (IPCL_IS_NONSTR(connp) ? 2 : 3)));
+
+	msg = NULL;
+	switch (dccp->dccp_state) {
+	case DCCPS_CLOSED:
+		break;
+	case DCCPS_BOUND:
+		break;
+	case DCCPS_REQUEST:
+		msg = "dccp_close, during connect";
+		break;
+	case DCCPS_RESPOND:
+		/* FALLTHRU */
+	default:
+		/*
+		 * If SO_LINGER has set a zero linger time, abort the
+		 * connection with a reset.
+		 */
+		if (connp->conn_linger && connp->conn_lingertime == 0) {
+			msg = "dccp_close, zero lingertime";
+			break;
+		}
+	}
+}
+
+/* ARGSUSED */
+void
+dccp_shutdown_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
+{
+	conn_t	*connp = (conn_t *)arg;
+	dccp_t	*dccp = connp->conn_dccp;
+
+	freemsg(mp);
+
+	if (dccp_xmit_end(dccp) != 0) {
+		/*
+		 * We were crossing FINs and got a reset from
+		 * the other side. Just ignore it.
+		 */
+		if (connp->conn_debug) {
+			(void) strlog(DCCP_MOD_ID, 0, 1,
+			    SL_ERROR|SL_TRACE,
+			    "dccp_shutdown_output() out of state %s",
+			    dccp_display(dccp, NULL, DISP_ADDR_AND_PORT));
+		}
+	}
+}
+
+#pragma inline(dccp_send_data)
+
+void
+dccp_send_data(dccp_t *dccp, mblk_t *mp)
+{
+	conn_t	*connp = dccp->dccp_connp;
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_sent_data");
+
+	/* XXX zcopy aware */
+
+	DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa,
+	    __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, dccp,
+	    __dtrace_dccp_dccph_t *,
+	    &mp->b_rptr[connp->conn_ixa->ixa_ip_hdr_length]);
+
+	ASSERT(connp->conn_ixa->ixa_notify_cookie == connp->conn_tcp);
+	error = conn_ip_output(mp, connp->conn_ixa);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "conn_ip_output failed with code %d\n", error);
+	}
+}
+
+/*
+ * Send a reset as response to an incoming packet or
+ * reset a connection.
+ */
+void
+dccp_xmit_listeners_reset(mblk_t *mp, ip_recv_attr_t *ira, ip_stack_t *ipst,
+    conn_t *connp)
+{
+	netstack_t	*ns = ipst->ips_netstack;
+	dccp_stack_t	*dccps = ns->netstack_dccp;
+	ipsec_stack_t	*ipss = dccps->dccps_netstack->netstack_ipsec;
+	dccpha_t	*dccpha;
+	ipha_t		*ipha;
+	ip6_t		*ip6h;
+	uchar_t		*rptr;
+	uint32_t	seq_len;
+	uint_t		ip_hdr_len = ira->ira_ip_hdr_length;
+	boolean_t	policy_present;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_listeners_reset");
+
+	DCCP_STAT(dccps, dccp_no_listener);
+
+	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
+		policy_present = ipss->ipsec_inbound_v4_policy_present;
+		ipha = (ipha_t *)mp->b_rptr;
+		ip6h = NULL;
+	} else {
+		policy_present = ipss->ipsec_inbound_v6_policy_present;
+		ipha = NULL;
+		ip6h = (ip6_t *)mp->b_rptr;
+	}
+
+	if (policy_present) {
+		mp = ipsec_check_global_policy(mp, (conn_t *)NULL, ipha, ip6h,
+		    ira, ns);
+		if (mp == NULL) {
+			return;
+		}
+	}
+
+	rptr = mp->b_rptr;
+
+	dccpha = (dccpha_t *)&rptr[ip_hdr_len];
+
+	seq_len = msgdsize(mp) - (ip_hdr_len);
+
+	dccp_xmit_early_reset("no dccp, reset", mp, 0,
+	    0, 0, ira, ipst, connp);
+}
+
+/*
+ * RFC 4340, Section 8.1.3
+ */
+static void
+dccp_xmit_early_reset(char *str, mblk_t *mp, uint32_t seq, uint32_t ack, int ctl,
+    ip_recv_attr_t *ira, ip_stack_t *ipst, conn_t *connp)
+{
+	dccpha_t	*dccpha;
+	dccpha_t	*nmp_dccpha;
+	dccpha_ack_t	*nmp_dccpha_ack;
+	dccpha_reset_t	*dccpha_reset;
+	dccpha_reset_t	*nmp_dccpha_reset;
+	dccpha_ext_t	*dccpha_ext;
+	dccpha_ext_t	*nmp_dccpha_ext;
+	netstack_t	*ns = ipst->ips_netstack;
+	dccp_stack_t	*dccps = ns->netstack_dccp;
+	ip6_t		*ip6h;
+	ipha_t		*ipha;
+	ipha_t		*nmp_ipha;
+	ip_xmit_attr_t	ixas;
+	ip_xmit_attr_t	*ixa;
+	in6_addr_t	v6addr;
+	ipaddr_t	v4addr;
+	mblk_t		*nmp;
+	uint64_t	pkt_ack;
+	uint_t		ip_hdr_len = ira->ira_ip_hdr_length;
+	ushort_t	port;
+	ushort_t	len;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_early_reset");
+
+	if (!dccp_send_rst_chk(dccps)) {
+		cmn_err(CE_NOTE, "dccp_output.c: not sending reset packet");
+		DCCP_STAT(dccps, dccp_rst_unsent);
+		freemsg(mp);
+		return;
+	}
+
+		bzero(&ixas, sizeof (ixas));
+		ixa = &ixas;
+
+		ixa->ixa_flags |= IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE;
+		ixa->ixa_protocol = IPPROTO_DCCP;
+		ixa->ixa_zoneid = ira->ira_zoneid;
+		ixa->ixa_ifindex = 0;
+		ixa->ixa_ipst = ipst;
+		ixa->ixa_cred = kcred;
+		ixa->ixa_cpid = NOPID;
+
+	if (str && dccps->dccps_dbg) {
+		(void) strlog(DCCP_MOD_ID, 0, 1, SL_TRACE,
+		    "dccp_xmit_early_reset: '%s', seq 0x%x, ack 0x%x, "
+		    "flags 0x%x",
+		    str, seq, ack, ctl);
+	}
+
+	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
+		ipha = (ipha_t *)mp->b_rptr;
+
+	} else {
+		/* XXX */
+	}
+
+	/*
+	 * Allocate a new DCCP reset message
+	 */
+	len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t);
+	nmp = allocb(len, BPRI_MED);
+	if (nmp == NULL) {
+		cmn_err(CE_NOTE, "alloc failed");
+		return;
+	}
+	bcopy(mp->b_rptr, nmp->b_wptr, ip_hdr_len + sizeof (dccpha_t));
+
+	nmp_dccpha = (dccpha_t *)&nmp->b_rptr[ip_hdr_len];
+	nmp_dccpha->dha_offset = 7;
+
+	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
+		nmp_ipha = (ipha_t *)nmp->b_rptr;
+
+		nmp_ipha->ipha_length = htons(len);
+		nmp_ipha->ipha_src = ipha->ipha_dst;
+		nmp_ipha->ipha_dst = ipha->ipha_src;
+
+		ixa->ixa_flags |= IXAF_IS_IPV4;
+		ixa->ixa_ip_hdr_length = ip_hdr_len;
+	} else {
+		cmn_err(CE_NOTE, "not v4");
+	}
+
+	dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
+
+	nmp->b_wptr = &nmp->b_rptr[len];
+
+	ixa->ixa_pktlen = len; // ?
+
+	nmp_dccpha->dha_fport = dccpha->dha_lport;
+	nmp_dccpha->dha_lport = dccpha->dha_fport;
+	nmp_dccpha->dha_type = DCCP_PKT_RESET;
+	nmp_dccpha->dha_x = 1;
+	nmp_dccpha->dha_res_seq = 0;
+	nmp_dccpha->dha_seq = 0;
+
+	nmp_dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t));
+
+	dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
+	nmp_dccpha_ext = (dccpha_ext_t *)&nmp->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
+	nmp_dccpha_ext->dha_ext_seq = 0;
+
+	len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t);
+	nmp_dccpha_ack = (dccpha_ack_t *)&nmp->b_rptr[len];
+	nmp_dccpha_ack->dha_ack_high = dccpha->dha_seq;
+	nmp_dccpha_ack->dha_ack_low = dccpha_ext->dha_ext_seq;
+	nmp_dccpha_ack->dha_ack_reserved = 0;
+
+	len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t);
+	nmp_dccpha_reset = (dccpha_reset_t *)&nmp->b_rptr[len];
+
+	if (connp != NULL) {
+		nmp_dccpha_reset->dha_reset_code =
+		    connp->conn_dccp->dccp_reset_code;
+	} else {
+		nmp_dccpha_reset->dha_reset_code =
+		    DCCP_RESET_CONNECTION_REFUSED;
+	}
+	nmp_dccpha_reset->dha_reset_data[0] = 0;
+	nmp_dccpha_reset->dha_reset_data[1] = 0;
+	nmp_dccpha_reset->dha_reset_data[2] = 0;
+
+	(void) ip_output_simple(nmp, ixa);
+
+	ixa_cleanup(ixa);
+}
+
+/*
+ *
+ */
+static boolean_t
+dccp_send_rst_chk(dccp_stack_t *dccps)
+{
+	int64_t	now;
+
+	if (dccps->dccps_rst_sent_rate_enabled != 0) {
+		now = ddi_get_lbolt64();
+		if (TICK_TO_MSEC(now - dccps->dccps_last_rst_intrvl) >
+		    1 * SECONDS) {
+			dccps->dccps_last_rst_intrvl = now;
+			dccps->dccps_rst_cnt = 1;
+		} else if (++dccps->dccps_rst_cnt > dccps->dccps_rst_sent_rate) {
+			return (B_FALSE);
+		}
+	}
+
+	return (B_TRUE);
+}
+
+/* ARGSUSED2 */
+void
+dccp_send_synack(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
+{
+	conn_t		*econnp = (conn_t *)arg;
+	dccp_t		*dccp = econnp->conn_dccp;
+	ip_xmit_attr_t	*ixa = econnp->conn_ixa;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_send_synack");
+
+	/*
+	 * Guard against a RESET having blown it away while on the
+	 * squeue.
+	 */
+	if (dccp->dccp_state == DCCPS_CLOSED) {
+		freemsg(mp);
+		return;
+	}
+
+	ixa->ixa_pktlen = msgdsize(mp);
+	(void) conn_ip_output(mp, ixa);
+}
+
+mblk_t *
+dccp_xmit_mp(dccp_t *dccp, mblk_t *mp, int32_t max_to_send, int32_t *offset,
+    mblk_t **end_mp, uint32_t seq, boolean_t sendall, uint32_t *seg_len,
+    boolean_t rexmit)
+{
+	conn_t		*connp = dccp->dccp_connp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	dccpha_t	*dccpha;
+	dccpha_ext_t	*dccpha_ext;
+	dccpha_ack_t	*dccpha_ack;
+	dccpha_srv_t	*dccpha_srv;
+	ip_xmit_attr_t	*ixa = connp->conn_ixa;
+	mblk_t		*mp1;
+	uchar_t		*rptr;
+	ushort_t	len;
+	int		data_length;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_mp");
+
+	// dccpha_t already in iphc_len?
+	len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4;
+
+	mp1 = allocb(len, BPRI_MED);
+	if (mp1 == NULL) {
+		cmn_err(CE_NOTE, "allocb failed");
+		return (NULL);
+	}
+
+	data_length = 0;
+
+	rptr = mp1->b_rptr;
+	mp1->b_wptr = &mp1->b_rptr[len];
+	bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
+	dccpha = (dccpha_t *)&rptr[ixa->ixa_ip_hdr_length];
+	dccpha->dha_type = DCCP_PKT_RESPONSE;
+	dccpha->dha_offset = 8;
+	dccpha->dha_x = 1;
+	dccpha->dha_ccval = 0;
+	dccpha->dha_cscov = 0;
+	dccpha->dha_reserved = 0;
+	dccpha->dha_res_seq = 0;
+	dccpha->dha_seq = 0;
+
+	dccpha_ext = (dccpha_ext_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t)];
+	dccpha_ext->dha_ext_seq = 0;
+
+	dccpha_ack = (dccpha_ack_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t) + sizeof (dccpha_ext_t)];
+	dccpha_ack->dha_ack_reserved = 0;
+	dccpha_ack->dha_ack_high = 0;
+	dccpha_ack->dha_ack_low = 0;
+
+	dccpha_srv = (dccpha_srv_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t)];
+	dccpha_srv->dha_srv_code = 0;
+
+	return (mp1);
+}
+
+/*
+ * Generate a DCCP-Response packet.
+ */
+mblk_t *
+dccp_generate_response(conn_t *connp, mblk_t *mp)
+{
+	dccpha_t	*dccpha;
+	dccpha_ext_t	*dccpha_ext;
+	dccpha_ack_t	*dccpha_ack;
+	dccpha_srv_t	*dccpha_srv;
+	mblk_t		*mp1;
+	uint64_t	seq;
+	uint64_t	ack;
+	uint16_t	ack_high;
+	uint32_t	ack_low;
+//	uint_t          ip_hdr_len = ira->ira_ip_hdr_length;
+	ip_xmit_attr_t  *ixa = connp->conn_ixa;
+	uint_t		ip_hdr_len;
+	uint_t		len;
+	uint_t		total_hdr_len;
+	uchar_t		*rptr;
+	dccp_t		*dccp = connp->conn_dccp;
+	void		*options;
+	size_t		opt_len;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_packet");
+
+	ip_hdr_len = ixa->ixa_ip_hdr_length;
+
+	if (mp == NULL) {
+		cmn_err(CE_NOTE, "NULL pointer mp");
+		return (NULL);
+	}
+
+	dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
+	dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
+
+	ack_high = dccpha->dha_seq;
+	ack_low = dccpha_ext->dha_ext_seq;
+
+	seq = ntohs(ack_high) << 31;
+	seq |= ntohl(ack_low);
+
+	dccp->dccp_isr = seq;
+	dccp->dccp_gsr = seq;
+	dccp->dccp_swl = seq;
+	dccp->dccp_swh = seq;
+	dccp->dccp_gss++;
+
+	error = dccp_generate_options(dccp, &options, &opt_len);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_options failed");
+	}
+	cmn_err(CE_NOTE, "generated options len: %d", (int) opt_len);
+
+
+	/*
+	 * conn_ht_iphc_len = ip_hdr_length (20) + ulp_hdr_length
+	 * (20) simple ip header (without vtag or options)
+	 */
+	total_hdr_len = len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4 + opt_len;
+	mp1 = allocb(len, BPRI_MED);
+	if (mp1 == NULL) {
+		cmn_err(CE_NOTE, "allocb failed");
+		return (NULL);
+	}
+
+        rptr = mp1->b_rptr;
+        mp1->b_wptr = &mp1->b_rptr[len];
+
+	bcopy(options, &mp1->b_rptr[len-opt_len], opt_len);
+        bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
+        dccpha = (dccpha_t *)&rptr[ip_hdr_len];
+
+        dccpha->dha_type = DCCP_PKT_RESPONSE;
+        dccpha->dha_offset = 7 + (opt_len / 4);
+        dccpha->dha_x = 1;
+        dccpha->dha_ccval = 0;
+        dccpha->dha_cscov = 0;
+        dccpha->dha_reserved = 0;
+	dccpha->dha_res_seq = 0;
+	dccpha->dha_seq = htons(dccp->dccp_gss >> 32);;
+	dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4 + opt_len);
+
+
+	dccpha_ext = (dccpha_ext_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
+	dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff);
+
+	dccpha_ack = (dccpha_ack_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t)];
+	dccpha_ack->dha_ack_high = ack_high;
+	dccpha_ack->dha_ack_low = ack_low;
+	dccpha_ack->dha_ack_reserved = 0;
+
+	dccpha_srv = (dccpha_srv_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t)];
+	dccpha_srv->dha_srv_code = 0;
+
+	ixa->ixa_pktlen = total_hdr_len;
+
+	if (ixa->ixa_flags & IXAF_IS_IPV4) {
+		((ipha_t *)rptr)->ipha_length = htons(total_hdr_len);
+	} else {
+		ip6_t *ip6 = (ip6_t *)rptr;
+
+		ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN);
+	}
+
+	cmn_err(CE_NOTE, "IPHC LEN: %d", connp->conn_ht_iphc_len);
+	cmn_err(CE_NOTE, "TOTAL LEN: %d", total_hdr_len);
+
+	kmem_free(options, opt_len);
+
+	return (mp1);
+}
+
+/*
+ * Generate a request packet. Must use 48-bit sequence
+ * numbers.
+ */
+mblk_t *
+dccp_generate_request(conn_t *connp)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccpha_t	*dccpha;
+	dccpha_ext_t	*dccpha_ext;
+	dccpha_srv_t	*dccpha_srv;
+	ip_xmit_attr_t	*ixa = connp->conn_ixa;
+	mblk_t		*mp;
+	uchar_t		*rptr;
+	uint_t		total_hdr_len;
+	uint_t		len;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_request");
+
+	total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_srv_t);
+	mp = allocb(total_hdr_len, BPRI_MED);
+	if (mp == NULL) {
+		cmn_err(CE_NOTE, "allocb failed");
+		return (NULL);
+	}
+
+	rptr = mp->b_rptr;
+	mp->b_wptr = &mp->b_rptr[total_hdr_len];
+
+	/* Copy in the template header */
+	bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
+
+	len = ixa->ixa_ip_hdr_length;
+	dccpha = (dccpha_t *)&rptr[len];
+	dccpha->dha_type = DCCP_PKT_REQUEST;
+	dccpha->dha_offset = (sizeof (dccpha_t) + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_srv_t)) / 4;
+	dccpha->dha_x = 1;
+	dccpha->dha_ccval = 0;
+	dccpha->dha_cscov = 0;
+	dccpha->dha_reserved = 0;
+	dccpha->dha_res_seq = 0;
+	dccpha->dha_seq = 0;
+	dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_srv_t));
+
+	/* Extended sequence number */
+	len += sizeof (dccpha_t);
+	dccpha_ext = (dccpha_ext_t *)&rptr[len];
+
+	/* Service number */
+	len += sizeof (dccpha_ext_t);
+	dccpha_srv = (dccpha_srv_t *)&rptr[len];
+	dccpha_srv->dha_srv_code = 0;
+
+	ixa->ixa_pktlen = total_hdr_len;
+
+	if (ixa->ixa_flags & IXAF_IS_IPV4) {
+		((ipha_t *)rptr)->ipha_length = htons(total_hdr_len);
+	} else {
+		ip6_t *ip6 = (ip6_t *)rptr;
+
+		ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN);
+	}
+
+	return (mp);
+}
+
+/*
+ * Close packet.
+ */
+mblk_t *
+dccp_generate_reset(conn_t *connp)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccpha_t	*dccpha;
+	dccpha_ext_t	*dccpha_ext;
+	dccpha_ack_t	*dccpha_ack;
+	dccpha_reset_t	*dccpha_reset;
+	ip_xmit_attr_t	*ixa = connp->conn_ixa;
+	mblk_t		*mp;
+	uint64_t	gss;
+	uchar_t		*rptr;
+	uint_t		total_hdr_len;
+	uint_t		len = ixa->ixa_ip_hdr_length;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_reset");
+
+	/* XXX */
+	dccp->dccp_gss++;
+
+	/*
+	 * Allocate a new DCCP reset message
+	 */
+	total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t);
+	mp = allocb(total_hdr_len, BPRI_MED);
+	if (mp == NULL) {
+		cmn_err(CE_NOTE, "allocb failed");
+		return(NULL);
+	}
+
+	rptr = mp->b_rptr;
+	mp->b_wptr = &mp->b_rptr[total_hdr_len];
+
+	bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
+
+	len = ixa->ixa_ip_hdr_length;
+	dccpha = (dccpha_t *)&mp->b_rptr[len];
+	dccpha->dha_type = DCCP_PKT_RESET;
+	dccpha->dha_offset = 7;
+	dccpha->dha_x = 1;
+	dccpha->dha_ccval = 0;
+	dccpha->dha_cscov = 0;
+	dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t));
+	dccpha->dha_seq = htons(dccp->dccp_gss >> 32);
+	dccpha->dha_res_seq = 0;
+
+	len += sizeof (dccpha_t);
+	dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[len];
+	dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff);
+
+	/* Set ack */
+	len += sizeof (dccpha_ext_t);
+	dccpha_ack = (dccpha_ack_t *)&mp->b_rptr[len];
+	dccpha_ack->dha_ack_high = htons(dccp->dccp_gsr >> 32);
+	dccpha_ack->dha_ack_low = htonl(dccp->dccp_gsr & 0xffffffff);
+	dccpha_ack->dha_ack_reserved = 0;
+
+	len += sizeof (dccpha_ack_t);
+	dccpha_reset = (dccpha_reset_t *)&mp->b_rptr[len];
+	dccpha_reset->dha_reset_code = dccp->dccp_reset_code;
+	dccpha_reset->dha_reset_data[0] = dccp->dccp_reset_data[0];
+	dccpha_reset->dha_reset_data[1] = dccp->dccp_reset_data[1];
+	dccpha_reset->dha_reset_data[2] = dccp->dccp_reset_data[2];
+
+	ixa->ixa_pktlen = total_hdr_len;
+
+	if (ixa->ixa_flags & IXAF_IS_IPV4) {
+		cmn_err(CE_NOTE, "setting ip len for ipv4: %d", total_hdr_len);
+		((ipha_t *)rptr)->ipha_length = htons(total_hdr_len);
+	} else {
+		ip6_t *ip6 = (ip6_t *)rptr;
+
+		ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN);
+	}
+
+	return (mp);
+}
+
+/*
+ * Acknowledgement packet.
+ */
+mblk_t *
+dccp_generate_ack(conn_t *connp)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccpha_t	*dccpha;
+	dccpha_ext_t	*dccpha_ext;
+	dccpha_ack_t	*dccpha_ack;
+	ip_xmit_attr_t	*ixa = connp->conn_ixa;
+	mblk_t		*mp;
+	uint64_t	gss;
+	uchar_t		*rptr;
+	uint_t		total_hdr_len;
+	uint_t		len = ixa->ixa_ip_hdr_length;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_ack");
+
+	/* XXX */
+	dccp->dccp_gss++;
+
+	/*
+	 * Allocate a new DCCP reset message
+	 */
+	total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_ack_t);
+	mp = allocb(total_hdr_len, BPRI_MED);
+	if (mp == NULL) {
+		cmn_err(CE_NOTE, "allocb failed");
+		return(NULL);
+	}
+
+	rptr = mp->b_rptr;
+	mp->b_wptr = &mp->b_rptr[total_hdr_len];
+
+	bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
+
+	len = ixa->ixa_ip_hdr_length;
+	dccpha = (dccpha_t *)&mp->b_rptr[len];
+	dccpha->dha_type = DCCP_PKT_ACK;
+	dccpha->dha_offset = 6;
+	dccpha->dha_x = 1;
+	dccpha->dha_ccval = 0;
+	dccpha->dha_cscov = 0;
+	dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_ack_t));
+	dccpha->dha_seq = htons(dccp->dccp_gss >> 32);
+	dccpha->dha_res_seq = 0;
+
+	len += sizeof (dccpha_t);
+	dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[len];
+	dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff);
+
+	len += sizeof (dccpha_ext_t);
+	dccpha_ack = (dccpha_ack_t *)&mp->b_rptr[len];
+	dccpha_ack->dha_ack_high = htons(dccp->dccp_gsr >> 32);
+	dccpha_ack->dha_ack_low = htonl(dccp->dccp_gsr & 0xffffffff);
+	dccpha_ack->dha_ack_reserved = 0;
+
+	ixa->ixa_pktlen = total_hdr_len;
+
+	if (ixa->ixa_flags & IXAF_IS_IPV4) {
+		((ipha_t *)rptr)->ipha_length = htons(total_hdr_len);
+	} else {
+		ip6_t *ip6 = (ip6_t *)rptr;
+
+		ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN);
+	}
+
+	return (mp);
+}
+
+/*
+ * Common to all packet generating functions.
+ */
+static mblk_t *
+dccp_generate_common(conn_t *connp, uint8_t packet_type,
+    uint_t total_hdr_len)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccpha_t	*dccpha;
+	dccpha_ext_t	*dccpha_ext;
+	dccpha_ack_t	*dccpha_ack;
+	ip_xmit_attr_t	*ixa = connp->conn_ixa;
+	mblk_t		*mp;
+	uchar_t		*rptr;
+	uint_t		len;
+	boolean_t	extended;
+
+	/*
+	 * Allocate a new DCCP reset message
+	 */
+	mp = allocb(total_hdr_len, BPRI_MED);
+	if (mp == NULL) {
+		return(NULL);
+	}
+
+	dccp->dccp_gss++;
+
+	rptr = mp->b_rptr;
+	mp->b_wptr = &mp->b_rptr[total_hdr_len];
+
+	bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
+
+	/* Basic header */
+	len = ixa->ixa_ip_hdr_length;
+	dccpha = (dccpha_t *)&mp->b_rptr[len];
+	dccpha->dha_type = packet_type;
+	dccpha->dha_offset = 6;
+	dccpha->dha_x = 1;
+	dccpha->dha_ccval = 0;
+	dccpha->dha_cscov = 0;
+	dccpha->dha_sum = htons(total_hdr_len - len);
+	dccpha->dha_seq = htons(dccp->dccp_gss >> 32);
+	dccpha->dha_res_seq = 0;
+
+	/* Extended sequence number */
+	len += sizeof (dccpha_t);
+	dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[len];
+	dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff);
+
+	/* Acknowledgement number */
+	len += sizeof (dccpha_ext_t);
+	dccpha_ack = (dccpha_ack_t *)&mp->b_rptr[len];
+	dccpha_ack->dha_ack_high = htons(dccp->dccp_gsr >> 32);
+	dccpha_ack->dha_ack_low = htonl(dccp->dccp_gsr & 0xffffffff);
+	dccpha_ack->dha_ack_reserved = 0;
+
+	ixa->ixa_pktlen = total_hdr_len;
+
+	if (ixa->ixa_flags & IXAF_IS_IPV4) {
+		((ipha_t *)rptr)->ipha_length = htons(total_hdr_len);
+	} else {
+		ip6_t *ip6 = (ip6_t *)rptr;
+
+		ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN);
+	}
+
+	return (mp);
+}
+
+/*
+ * Acknowledgement packet.
+ */
+mblk_t *
+dccp_generate_sync(conn_t *connp)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccpha_t	*dccpha;
+	dccpha_ext_t	*dccpha_ext;
+	dccpha_ack_t	*dccpha_ack;
+	ip_xmit_attr_t	*ixa = connp->conn_ixa;
+	mblk_t		*mp;
+	uchar_t		*rptr;
+	uint_t		total_hdr_len;
+	uint_t		len = ixa->ixa_ip_hdr_length;
+
+	cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_ack");
+
+	total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) +
+	    sizeof (dccpha_ack_t);
+	mp = dccp_generate_common(connp, DCCP_PACKET_SYNC, total_hdr_len);
+	if (mp == NULL) {
+		cmn_err(CE_NOTE, "allocb failed");
+		return(NULL);
+	}
+
+	rptr = mp->b_rptr;
+	mp->b_wptr = &mp->b_rptr[total_hdr_len];
+
+	return (mp);
+}
--- /dev/null	2012-08-18 10:37:10.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_socket.c	2012-08-18 10:37:10.803003516 +0000
@@ -0,0 +1,806 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * This file contains all DCCP kernel socket related functions.
+ */
+
+#include <sys/types.h>
+#include <sys/strlog.h>
+#include <sys/policy.h>
+#include <sys/sockio.h>
+#include <sys/strsubr.h>
+#include <sys/strsun.h>
+#define	_SUN_TPI_VERSION 2
+#include <sys/tihdr.h>
+#include <sys/timod.h>
+#include <sys/squeue_impl.h>
+#include <sys/squeue.h>
+#include <sys/socketvar.h>
+
+#include <inet/common.h>
+#include <inet/dccp_impl.h>
+#include <inet/dccp_stack.h>
+#include <inet/proto_set.h>
+#include <inet/ip.h>
+
+#include <sys/cmn_err.h>
+
+static void	dccp_activate(sock_lower_handle_t, sock_upper_handle_t,
+		    sock_upcalls_t *, int, cred_t *);
+static int	dccp_accept(sock_lower_handle_t, sock_lower_handle_t,
+		    sock_upper_handle_t, cred_t *);
+static int	dccp_bind(sock_lower_handle_t, struct sockaddr *,
+		    socklen_t, cred_t *);
+static int	dccp_listen(sock_lower_handle_t, int, cred_t *);
+static int	dccp_connect(sock_lower_handle_t, const struct sockaddr *,
+		    socklen_t, sock_connid_t *, cred_t *);
+static int	dccp_getpeername(sock_lower_handle_t, struct sockaddr *,
+		    socklen_t *, cred_t *);
+static int	dccp_getsockname(sock_lower_handle_t, struct sockaddr *,
+		    socklen_t *, cred_t *);
+static int	dccp_getsockopt(sock_lower_handle_t, int, int, void *,
+		    socklen_t *, cred_t *);
+static int	dccp_setsockopt(sock_lower_handle_t, int, int, const void *,
+		    socklen_t, cred_t *);
+static int	dccp_send(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
+		    cred_t *);
+static int	dccp_shutdown(sock_lower_handle_t, int, cred_t *);
+static void	dccp_clr_flowctrl(sock_lower_handle_t);
+static int	dccp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
+		    cred_t *);
+static int	dccp_close(sock_lower_handle_t, int, cred_t *);
+
+sock_downcalls_t sock_dccp_downcalls = {
+	dccp_activate,		/* sd_activate */
+	dccp_accept,		/* sd_accept */
+	dccp_bind,		/* sd_bind */
+	dccp_listen,		/* sd_listen */
+	dccp_connect,		/* sd_connect */
+	dccp_getpeername,	/* sd_getpeername */
+	dccp_getsockname,	/* sd_getsockname */
+	dccp_getsockopt,	/* sd_getsockopt */
+	dccp_setsockopt,	/* sd_setsockopt */
+	dccp_send,		/* sd_send */
+	NULL,			/* sd_send_uio */
+	NULL,			/* sd_recv_uio */
+	NULL,			/* sd_poll */
+	dccp_shutdown,		/* sd_shutdown */
+	dccp_clr_flowctrl,	/* sd_setflowctrl */
+	dccp_ioctl,		/* sd_ioctl */
+	dccp_close,		/* sd_close */
+};
+
+/* ARGSUSED */
+static void
+dccp_activate(sock_lower_handle_t proto_handle, sock_upper_handle_t sock_handle,
+    sock_upcalls_t *sock_upcalls, int flags, cred_t *cr)
+{
+	conn_t *connp = (conn_t *)proto_handle;
+	struct sock_proto_props		sopp;
+	extern struct module_info	dccp_rinfo;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_activate");
+
+	ASSERT(connp->conn_upper_handle == NULL);
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	sopp.sopp_flags = SOCKOPT_RCVHIWAT | SOCKOPT_RCVLOWAT |
+	    SOCKOPT_MAXPSZ | SOCKOPT_MAXBLK | SOCKOPT_RCVTIMER |
+	    SOCKOPT_RCVTHRESH | SOCKOPT_MAXADDRLEN | SOCKOPT_MINPSZ;
+
+	sopp.sopp_rxhiwat = SOCKET_RECVHIWATER;
+	sopp.sopp_rxlowat = SOCKET_RECVLOWATER;
+	sopp.sopp_maxpsz = INFPSZ;
+	sopp.sopp_maxblk = INFPSZ;
+	sopp.sopp_rcvtimer = SOCKET_TIMER_INTERVAL;
+	sopp.sopp_rcvthresh = SOCKET_RECVHIWATER >> 3;
+	sopp.sopp_maxaddrlen = sizeof (sin6_t);
+	sopp.sopp_minpsz = (dccp_rinfo.mi_minpsz == 1) ? 0 :
+	    dccp_rinfo.mi_minpsz;
+
+	connp->conn_upcalls = sock_upcalls;
+	connp->conn_upper_handle = sock_handle;
+
+	/* XXX  conn_rcvbuf */
+	(*connp->conn_upcalls->su_set_proto_props)(connp->conn_upper_handle,
+	    &sopp);
+}
+
+/*ARGSUSED*/
+static int
+dccp_accept(sock_lower_handle_t lproto_handle,
+    sock_lower_handle_t eproto_handle, sock_upper_handle_t sock_handle,
+    cred_t *cr)
+{
+	conn_t	*lconnp, *econnp;
+	dccp_t	*listener, *eager;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_accept");
+
+	econnp = (conn_t *)eproto_handle;
+	eager = econnp->conn_dccp;
+	ASSERT(IPCL_IS_NONSTR(econnp));
+	ASSERT(eager->dccp_listener != NULL);
+	listener = eager->dccp_listener;
+	lconnp = (conn_t *)listener->dccp_connp;
+	ASSERT(listener->dccp_state == DCCPS_LISTEN);
+	ASSERT(lconnp->conn_upper_handle != NULL);
+
+	ASSERT(econnp->conn_upper_handle == NULL ||
+	    econnp->conn_upper_handle == sock_handle);
+	ASSERT(econnp->conn_upcalls == NULL ||
+	    econnp->conn_upcalls == lconnp->conn_upcalls);
+	econnp->conn_upper_handle = sock_handle;
+	econnp->conn_upcalls = lconnp->conn_upcalls;
+
+	ASSERT(econnp->conn_netstack ==
+	    listener->dccp_connp->conn_netstack);
+	ASSERT(eager->dccp_dccps == listener->dccp_dccps);
+
+	ASSERT(econnp->conn_ref >= 2);
+	eager->dccp_listener = NULL; /* XXX */
+	CONN_DEC_REF(listener->dccp_connp);
+
+	return ((eager->dccp_state < DCCPS_OPEN) ? ECONNABORTED : 0);
+}
+
+static int
+dccp_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa,
+    socklen_t len, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_bind");
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	error = squeue_synch_enter(connp, NULL);
+	if (error != 0) {
+		/* Failed to enter */
+		return (ENOSR);
+	}
+
+	/* Binding to NULL address means unbind */
+	if (sa == NULL) {
+		if (connp->conn_dccp->dccp_state < DCCPS_LISTEN) {
+			error = dccp_do_unbind(connp);
+		} else {
+			error = EINVAL;
+		}
+	} else {
+		error = dccp_do_bind(connp, sa, len, cr, B_TRUE);
+	}
+
+	squeue_synch_exit(connp);
+
+	if (error < 0) {
+		if (error == -TOUTSTATE) {
+			error = EINVAL;
+		} else {
+			error = proto_tlitosyserr(-error);
+		}
+	}
+
+	return (error);
+}
+
+/* ARGSUSED */
+static int
+dccp_listen(sock_lower_handle_t proto_handle, int backlog, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	dccp_t	*dccp = connp->conn_dccp;
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_listen");
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	error = squeue_synch_enter(connp, NULL);
+	if (error != 0) {
+		/* Failed to enter */
+		return (ENOBUFS);
+	}
+
+	error = dccp_do_listen(connp, NULL, 0, backlog, cr, B_FALSE);
+	if (error == 0) {
+		/* XXX dccps->dccps_conn_req_max_q0 */
+		(*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
+		    SOCK_OPCTL_ENAB_ACCEPT,
+		    (uintptr_t)(dccp->dccp_conn_req_max));
+	} else if (error < 0) {
+		if (error == -TOUTSTATE) {
+			error = EINVAL;
+		} else {
+			error = proto_tlitosyserr(-error);
+		}
+	}
+
+	squeue_synch_exit(connp);
+
+	return (error);
+}
+
+/*
+ * Socket connect.
+ */
+static int
+dccp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa,
+    socklen_t len, sock_connid_t *id, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_connect");
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	error = proto_verify_ip_addr(connp->conn_family, sa, len);
+	if (error != 0) {
+		return (error);
+	}
+
+	error = squeue_synch_enter(connp, NULL);
+	if (error != 0) {
+		/* Failed to enter */
+		return (ENOSR);
+	}
+
+	/*
+	 * DCCP supports quick connect, so no need to do an implicit bind.
+	 */
+	error = dccp_do_connect(connp, sa, len, cr, curproc->p_pid);
+	if (error == 0) {
+		*id = connp->conn_dccp->dccp_connid;
+	} else if (error < 0) {
+		if (error == -TOUTSTATE) {
+			switch (connp->conn_dccp->dccp_state) {
+			case DCCPS_REQUEST:
+				error = EALREADY;
+				break;
+			case DCCPS_PARTOPEN:
+				error = EISCONN;
+				break;
+			case DCCPS_LISTEN:
+				error = EOPNOTSUPP;
+				break;
+			default:
+				error = EINVAL;
+				break;
+			}
+		} else {
+			error = proto_tlitosyserr(-error);
+		}
+	}
+
+	/* XXX loopback */
+
+	squeue_synch_exit(connp);
+
+	return ((error == 0) ? EINPROGRESS : error);
+}
+
+/* ARGSUSED3 */
+static int
+dccp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
+    socklen_t *addrlenp, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	dccp_t	*dccp = connp->conn_dccp;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_getpeername");
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	ASSERT(dccp != NULL);
+	if (dccp->dccp_state < DCCPS_OPEN) {
+		return (ENOTCONN);
+	}
+
+	return (conn_getpeername(connp, addr, addrlenp));
+}
+
+/* ARGSUSED3 */
+static int
+dccp_getsockname(sock_lower_handle_t proto_handle, struct sockaddr *addr,
+    socklen_t *addrlenp, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_getsockname");
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	/* XXX UDP has locks here, TCP not */
+	mutex_enter(&connp->conn_lock);
+	error = conn_getsockname(connp, addr, addrlenp);
+	mutex_exit(&connp->conn_lock);
+
+	return (error);
+}
+
+static int
+dccp_getsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
+    void *optvalp, socklen_t *optlen, cred_t *cr)
+{
+	conn_t		*connp = (conn_t *)proto_handle;
+	void		*optvalp_buf;
+	t_uscalar_t	max_optbuf_len;
+	int		len;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_getsockopt");
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	error = proto_opt_check(level, option_name, *optlen, &max_optbuf_len,
+	    dccp_opt_obj.odb_opt_des_arr,
+	    dccp_opt_obj.odb_opt_arr_cnt,
+	    B_FALSE, B_TRUE, cr);
+	if (error != 0) {
+		if (error < 0) {
+			error = proto_tlitosyserr(-error);
+		}
+		return (error);
+	}
+
+	optvalp_buf = kmem_alloc(max_optbuf_len, KM_SLEEP);
+	if (optvalp_buf == NULL) {
+		return (ENOMEM);
+	}
+
+	error = squeue_synch_enter(connp, NULL);
+	if (error == ENOMEM) {
+		kmem_free(optvalp_buf, max_optbuf_len);
+		return (ENOMEM);
+	}
+
+	len = dccp_opt_get(connp, level, option_name, optvalp_buf);
+	squeue_synch_exit(connp);
+
+	if (len == -1) {
+		kmem_free(optvalp_buf, max_optbuf_len);
+		return (EINVAL);
+	}
+
+	/*
+	 * Update optlen and copy option value.
+	 */
+	t_uscalar_t size = MIN(len, *optlen);
+
+	bcopy(optvalp_buf, optvalp, size);
+	bcopy(&size, optlen, sizeof (size));
+
+	kmem_free(optvalp_buf, max_optbuf_len);
+
+	return (0);
+}
+
+static int
+dccp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
+    const void *optvalp, socklen_t optlen, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_setsockopt");
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	error = squeue_synch_enter(connp, NULL);
+	if (error == ENOMEM) {
+		return (ENOMEM);
+	}
+
+	error = proto_opt_check(level, option_name, optlen, NULL,
+	    dccp_opt_obj.odb_opt_des_arr,
+	    dccp_opt_obj.odb_opt_arr_cnt,
+	    B_TRUE, B_FALSE, cr);
+
+	if (error != 0) {
+		if (error < 0) {
+			error = proto_tlitosyserr(-error);
+		}
+		squeue_synch_exit(connp);
+		return (error);
+	}
+
+	error = dccp_opt_set(connp, SETFN_OPTCOM_NEGOTIATE, level, option_name,
+	    optlen, (uchar_t *)optvalp, (uint_t *)&optlen, (uchar_t *)optvalp,
+	    NULL, cr);
+	squeue_synch_exit(connp);
+
+	ASSERT(error >= 0);
+
+	return (error);
+}
+
+/* ARGSUSED */
+static int
+dccp_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg,
+    cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	dccp_t	*dccp;
+	uint32_t msize;
+	int32_t	dccpstate;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_send");
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	ASSERT(connp->conn_ref >= 2);
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	if (msg->msg_controllen != 0) {
+		freemsg(mp);
+		return (EOPNOTSUPP);
+	}
+
+	switch (DB_TYPE(mp)) {
+	case M_DATA:
+		dccp = connp->conn_dccp;
+		ASSERT(dccp != NULL);
+
+		dccpstate = dccp->dccp_state;
+		if (dccpstate < DCCPS_OPEN) {
+			freemsg(mp);
+
+			/*
+			 * We return ENOTCONN if the endpoint is trying to
+			 * connect or has never been connected, and EPIPE if it
+			 * has been disconnected. The connection id helps us
+			 * distinguish between the last two cases.
+			 */
+			return ((dccpstate == DCCPS_REQUEST) ? ENOTCONN :
+			    ((dccp->dccp_connid > 0) ? EPIPE : ENOTCONN));
+		} else if (dccpstate > DCCPS_CLOSING) {
+			freemsg(mp);
+			return (EPIPE);
+		}
+
+		/* XXX */
+
+		msize = msgdsize(mp);
+
+		CONN_INC_REF(connp);
+
+		if (msg->msg_flags & MSG_OOB) {
+			SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_output_urgent,
+			    connp, NULL, dccp_squeue_flag, SQTAG_DCCP_OUTPUT); 
+		} else {
+			SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_output,
+			    connp, NULL, dccp_squeue_flag, SQTAG_DCCP_OUTPUT);
+		}
+
+		return (0);
+
+	default:
+		ASSERT(0);
+	}
+
+	freemsg(mp);
+
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+dccp_shutdown(sock_lower_handle_t proto_handle, int how, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	dccp_t	*dccp = connp->conn_dccp;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_shutdown");
+
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	/*
+	 * X/Open requires that we check the connected state.
+	 */
+	if (dccp->dccp_state < DCCPS_REQUEST)
+		return (ENOTCONN);
+
+	/* Shutdown the send side */
+	if (how != SHUT_RD) {
+		mblk_t	*bp;
+
+		bp = allocb_wait(0, BPRI_HI, STR_NOSIG, NULL);
+		CONN_INC_REF(connp);
+		SQUEUE_ENTER_ONE(connp->conn_sqp, bp, dccp_shutdown_output,
+		    connp, NULL, SQ_NODRAIN, SQTAG_DCCP_SHUTDOWN_OUTPUT);
+
+		(*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
+		    SOCK_OPCTL_SHUT_SEND, 0);
+	}
+
+	/* Shutdown the recv side */
+	if (how != SHUT_WR) {
+		(*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
+		    SOCK_OPCTL_SHUT_RECV, 0);
+	}
+
+	return (0);
+}
+
+static void
+dccp_clr_flowctrl(sock_lower_handle_t proto_handle)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	dccp_t	*dccp = connp->conn_dccp;
+	mblk_t	*mp;
+	int	error;
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_clr_flowctrl");
+
+	error = squeue_synch_enter(connp, mp);
+	ASSERT(error == 0);
+
+	squeue_synch_exit(connp);
+}
+
+/* ARGSUSED */
+static int
+dccp_ioctl(sock_lower_handle_t proto_handle, int cmd, intptr_t arg,
+    int mode, int32_t *rvalp, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+	int	error;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_ioctl");
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	/* All Solaris components should pass a cred for this operation. */
+	ASSERT(cr != NULL);
+
+	/*
+	 * If we don't have a helper stream then create one.
+	 * ip_create_helper_stream takes care of locking the conn_t,
+	 * so this check for NULL is just a performance optimization.
+	 */
+	if (connp->conn_helper_info == NULL) {
+		dccp_stack_t	*dccps = connp->conn_dccp->dccp_dccps;
+
+		/*
+		 * Create a helper stream for non-STREAMS socket.
+		 */
+		error = ip_create_helper_stream(connp, dccps->dccps_ldi_ident);
+		if (error != 0) {
+			ip0dbg(("dccp_ioctl: create of IP helper stream "
+			    "failed %d\n", error));
+			return (error);
+		}
+	}
+
+	switch (cmd) {
+	case ND_SET:
+	case ND_GET:
+	case _SIOCSOCKFALLBACK:
+	/* XXX  case DCCP_IOC_ABORT_CONN: */
+	case TI_GETPEERNAME:
+	case TI_GETMYNAME:
+		ip1dbg(("dccp_ioctl: cmd 0x%x on non streams socket", cmd));
+		error = EINVAL;
+		break;
+	default:
+		/*
+		 * If the conn is not closing, pass on to IP using
+		 * helper stream. Bump the ioctlref to prevent dccp_close
+		 * from closing the rq/wq out from underneath the ioctl
+		 * if it ends up queued or aborted/interrupted.
+		 */
+		mutex_enter(&connp->conn_lock);
+		if (connp->conn_state_flags & (CONN_CLOSING)) {
+			mutex_exit(&connp->conn_lock);
+			error = EINVAL;
+			break;
+		}
+		CONN_INC_IOCTLREF_LOCKED(connp);
+		error = ldi_ioctl(connp->conn_helper_info->iphs_handle,
+		    cmd, arg, mode, cr, rvalp);
+		CONN_DEC_IOCTLREF(connp);
+		break;
+	}
+
+	return (error);
+}
+
+/* ARGSUSED */
+static int
+dccp_close(sock_lower_handle_t proto_handle, int flags, cred_t *cr)
+{
+	conn_t	*connp = (conn_t *)proto_handle;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_close\n");
+
+	ASSERT(connp->conn_upper_handle != NULL);
+
+	/* All Solaris components should pass a cred for this operation */
+	ASSERT(cr != NULL);
+
+	dccp_close_common(connp, flags);
+
+	ip_free_helper_stream(connp);
+
+	CONN_DEC_REF(connp);
+
+	/*
+	 * EINPROGRESS tells sockfs to wait for a 'closed' upcall before
+	 * freeing the socket.
+	 */
+	return (EINPROGRESS);
+}
+
+
+/*
+ * Socket create function.
+ */
+sock_lower_handle_t
+dccp_create(int family, int type, int proto, sock_downcalls_t **sockdowncalls,
+    uint_t *smodep, int *errorp, int flags, cred_t *credp)
+{
+	conn_t		*connp;
+	boolean_t	isv6;
+
+	/* XXX (type != SOCK_STREAM */
+	if ((family != AF_INET && family != AF_INET6) ||
+	    (proto != 0 && proto != IPPROTO_DCCP)) {
+		*errorp = EPROTONOSUPPORT;
+		return (NULL);
+	}
+
+	cmn_err(CE_NOTE, "dccp_socket: dccp_create\n");
+
+	isv6 = family == AF_INET6 ? B_TRUE: B_FALSE;
+	connp = dccp_create_common(credp, isv6, B_TRUE, errorp);
+	if (connp == NULL) {
+		return (NULL);
+	}
+
+	/*
+	 * Increment ref for DCCP connection.
+	 */
+	mutex_enter(&connp->conn_lock);
+	CONN_INC_REF_LOCKED(connp);
+	ASSERT(connp->conn_ref == 2);
+	connp->conn_state_flags &= ~CONN_INCIPIENT;
+	connp->conn_flags |= IPCL_NONSTR;
+	mutex_exit(&connp->conn_lock);
+
+	ASSERT(errorp != NULL);
+	*errorp = 0;
+	*sockdowncalls = &sock_dccp_downcalls;
+	*smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP |
+	    SM_SENDFILESUPP;
+
+	return ((sock_lower_handle_t)connp);
+}
+
+int
+dccp_fallback(sock_lower_handle_t proto_handle, queue_t *q,
+    boolean_t issocket, so_proto_quiesced_cb_t quiesced_cb,
+    sock_quiesce_arg_t *arg)
+{
+	cmn_err(CE_NOTE, "dccp_socket: dccp_fallback\n");
+
+	return (0);
+}
+
+/*
+ * Notifies a non-STREAMS based listener about a new connection. This
+ * function is executed on the *eager*'s squeue once the 3 way handshake
+ * has completed. Note that the behavior differs from STREAMS, where the
+ * T_CONN_IND is sent up by tcp_send_conn_ind() while on the *listener*'s
+ * squeue.
+ *
+ * Returns B_TRUE if the notification succeeded and an upper handle was
+ * obtained. `tcp' should be closed on failure.
+ */
+boolean_t
+dccp_newconn_notify(dccp_t *dccp, ip_recv_attr_t *ira)
+{
+	dccp_t			*listener = dccp->dccp_listener;
+	dccp_t			*tail;
+	conn_t			*lconnp = listener->dccp_connp;
+	conn_t			*econnp = dccp->dccp_connp;
+	ipaddr_t		*addr_cache;
+	sock_upper_handle_t	upper;
+	struct sock_proto_props	sopp;
+
+	cmn_err(CE_NOTE, "dccp_socket.c: dccp_newconn_notify");
+
+/*
+	mutex_enter(&listener->dccp_eager_lock);
+	addr_cache = (ipaddr_t *)(listener->dccp_ip_addr_cache);
+	if (addr_cache != NULL) {
+		addr_cache[IP_ADDR_CACHE_HASH(dccp->dccp_connp->conn_faddr_v4)] =
+		    dccp->dccp_connp->conn_faddr_v4;
+	}
+	mutex_exit(&listener->dccp_eager_lock);
+*/
+
+	/*
+	 * Notify the ULP about the new connection.
+	 */
+	if ((upper = (*lconnp->conn_upcalls->su_newconn)
+		(lconnp->conn_upper_handle, (sock_lower_handle_t)econnp,
+		&sock_dccp_downcalls, ira->ira_cred, ira->ira_cpid,
+		&econnp->conn_upcalls)) == NULL) {
+			return (B_FALSE);
+	}
+	econnp->conn_upper_handle = upper;
+
+	dccp->dccp_detached = B_FALSE;
+	dccp->dccp_hard_binding = B_FALSE;
+	dccp->dccp_tconnind_started = B_TRUE;
+
+	if (econnp->conn_keepalive) {
+		dccp->dccp_ka_last_intrvl = 0;
+		dccp->dccp_ka_tid = DCCP_TIMER(dccp, dccp_keepalive_timer,
+		    dccp->dccp_ka_interval);
+	}
+
+	/* Update the necessary parameters */
+	dccp_get_proto_props(dccp, &sopp);
+
+	(*econnp->conn_upcalls->su_set_proto_props)
+	    (econnp->conn_upper_handle, &sopp);
+
+	return (B_TRUE);
+}
--- /dev/null	2012-08-18 10:37:11.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_stats.c	2012-08-18 10:37:10.983047463 +0000
@@ -0,0 +1,583 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * Functions related to MIB-II and kstat.
+ */
+
+#include <sys/types.h>
+#include <sys/tihdr.h>
+#include <sys/policy.h>
+#include <sys/tsol/tnet.h>
+
+#include <inet/common.h>
+#include <inet/dccp_impl.h>
+#include <inet/ip.h>
+#include <inet/kstatcom.h>
+#include <inet/snmpcom.h>
+
+#include <sys/cmn_err.h>
+
+static int	dccp_snmp_state(dccp_t *);
+static int	dccp_kstat_update(kstat_t *, int);
+static int	dccp_kstat2_update(kstat_t *, int);
+static void	dccp_add_mib(mib2_dccp_t *, mib2_dccp_t *);
+static void	dccp_sum_mib(dccp_stack_t *, mib2_dccp_t *);
+static void	dccp_clr_stats(dccp_stat_t *);
+static void	dccp_add_stats(dccp_stat_counter_t *, dccp_stat_t *);
+
+/*
+ * Translate DCCP state to MIB2 state.
+ */
+static int
+dccp_snmp_state(dccp_t *dccp)
+{
+	if (dccp == NULL) {
+		return (0);
+	}
+
+	switch(dccp->dccp_state) {
+	case DCCPS_CLOSED:
+		return (MIB2_DCCP_closed);
+	default:
+		return (0);
+	}
+}
+
+/*
+ * Get the MIB-II stats.
+ */
+mblk_t *
+dccp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
+{
+	conn_t		*connp = Q_TO_CONN(q);
+	connf_t		*connfp;
+	ip_stack_t	*ipst;
+	dccp_stack_t	*dccps;
+	struct opthdr	*optp;
+	mblk_t		*mp2ctl;
+	mblk_t		*mpdata;
+	mblk_t		*mp_conn_ctl = NULL;
+	mblk_t		*mp_conn_tail;
+	mblk_t		*mp_attr_ctl = NULL;
+	mblk_t		*mp_attr_tail;
+	mblk_t		*mp6_conn_ctl = NULL;
+	mblk_t		*mp6_conn_tail;
+	mblk_t		*mp6_attr_ctl = NULL;
+	mblk_t		*mp6_attr_tail;
+	size_t		dccp_mib_size;
+	size_t		dce_size;
+	size_t		dce6_size;
+	boolean_t	ispriv;
+	zoneid_t	zoneid;
+	int		v4_conn_idx;
+	int		v6_conn_idx;
+	int		i;
+	mib2_dccp_t		dccp_mib;
+	mib2_dccpConnEntry_t	dce;
+	mib2_dccp6ConnEntry_t	dce6;
+	mib2_transportMLPEntry_t mlp;
+
+	/*
+	 * Make a copy of the original message.
+	 */
+	mp2ctl = copymsg(mpctl);
+
+	cmn_err(CE_NOTE, "dccp_stats.c: dccp_snmp_get");
+
+	if (mpctl == NULL ||
+	    (mpdata = mpctl->b_cont) == NULL ||
+	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
+	    (mp_attr_ctl = copymsg(mpctl)) == NULL ||
+	    (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
+	    (mp6_attr_ctl = copymsg(mpctl)) == NULL) {
+		freemsg(mp_conn_ctl);
+		freemsg(mp_attr_ctl);
+		freemsg(mp6_conn_ctl);
+		freemsg(mp6_attr_ctl);
+		freemsg(mpctl);
+		freemsg(mp2ctl);
+		return (NULL);
+	}
+
+	ipst = connp->conn_netstack->netstack_ip;
+	dccps = connp->conn_netstack->netstack_dccp;
+
+	if (legacy_req) {
+		dccp_mib_size = LEGACY_MIB_SIZE(&dccp_mib, mib2_dccp_t);
+		dce_size = LEGACY_MIB_SIZE(&dce, mib2_dccpConnEntry_t);
+		dce6_size = LEGACY_MIB_SIZE(&dce6, mib2_dccp6ConnEntry_t);
+	} else {
+		dccp_mib_size = sizeof (mib2_dccp_t);
+		dce_size = sizeof (mib2_dccpConnEntry_t);
+		dce6_size = sizeof (mib2_dccp6ConnEntry_t);
+	}
+
+	bzero(&dccp_mib, sizeof (dccp_mib));
+
+	ispriv = secpolicy_ip_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
+	zoneid = Q_TO_CONN(q)->conn_zoneid;
+
+	v4_conn_idx = v6_conn_idx = 0;
+	mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
+
+	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
+		ipst = dccps->dccps_netstack->netstack_ip;
+
+		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
+		connp = NULL;
+
+		while ((connp = ipcl_get_next_conn(connfp, connp,
+		    IPCL_DCCPCONN)) != NULL) {
+			dccp_t		*dccp;
+			boolean_t	needattr;
+
+			if (connp->conn_zoneid != zoneid) {
+				continue;	/* Not in this zone */
+			}
+
+			dccp = connp->conn_dccp;
+			DCCPS_UPDATE_MIB(dccps, dccpHCInSegs, dccp->dccp_ibsegs);
+			dccp->dccp_ibsegs = 0;
+			DCCPS_UPDATE_MIB(dccps, dccpHCOutSegs, dccp->dccp_obsegs);
+			dccp->dccp_obsegs = 0;
+
+			dce.dccpConnState = dccp_snmp_state(dccp);
+
+			needattr = B_FALSE;
+			bzero(&mlp, sizeof (mlp));
+			if (connp->conn_mlp_type != mlptSingle) {
+				if (connp->conn_mlp_type == mlptShared ||
+				    connp->conn_mlp_type == mlptBoth) {
+					mlp.tme_flags |= MIB2_TMEF_SHARED;
+				}
+
+				if (connp->conn_mlp_type == mlptPrivate ||
+				    connp->conn_mlp_type == mlptBoth) {
+					mlp.tme_flags |= MIB2_TMEF_PRIVATE;
+				}
+
+				needattr = B_TRUE;
+			}
+
+			if (connp->conn_anon_mlp) {
+				mlp.tme_flags |= MIB2_TMEF_ANONMLP;
+				needattr = B_TRUE;
+			}
+
+			switch (connp->conn_mac_mode) {
+			case CONN_MAC_DEFAULT:
+				break;
+			case CONN_MAC_AWARE:
+				mlp.tme_flags |= MIB2_TMEF_MACEXEMPT;
+				needattr = B_TRUE;
+				break;
+			case CONN_MAC_IMPLICIT:
+				mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT;
+				needattr = B_TRUE;
+				break;
+			}
+
+			if (connp->conn_ixa->ixa_tsl != NULL) {
+				ts_label_t	*tsl;
+
+				tsl = connp->conn_ixa->ixa_tsl;
+				mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
+				mlp.tme_doi = label2doi(tsl);
+				mlp.tme_label = *label2bslabel(tsl);
+				needattr = B_TRUE;
+			}
+
+			/* Create a message to report on IPv6 entries */
+			if (connp->conn_ipversion == IPV6_VERSION) {
+				dce6.dccp6ConnLocalAddress =
+				    connp->conn_laddr_v6;
+				dce6.dccp6ConnRemAddress =
+				    connp->conn_faddr_v6;
+				dce6.dccp6ConnLocalPort =
+				    ntohs(connp->conn_lport);
+				dce6.dccp6ConnRemPort =
+				    ntohs(connp->conn_fport);
+
+				if (connp->conn_ixa->ixa_flags &
+				    IXAF_SCOPEID_SET) {
+					dce6.dccp6ConnIfIndex =
+					    connp->conn_ixa->ixa_scopeid;
+				} else {
+					dce6.dccp6ConnIfIndex =
+					    connp->conn_bound_if;
+				}
+
+				/* XXX */
+
+				dce6.dccp6ConnEntryInfo.ce_state =
+				    dccp->dccp_state;
+
+				dce6.dccp6ConnCreationProcess =
+				    (connp->conn_cpid < 0) ?
+				    MIB2_UNKNOWN_PROCESS : connp->conn_cpid;
+				dce6.dccp6ConnCreationTime =
+				    connp->conn_open_time;
+
+				(void) snmp_append_data2(mp6_conn_ctl->b_cont,
+				    &mp6_conn_tail, (char *)&dce6, dce6_size);
+
+				mlp.tme_connidx = v6_conn_idx++;
+				if (needattr) {
+					(void) snmp_append_data2(
+					    mp6_attr_ctl->b_cont,
+					    &mp6_attr_tail, (char *)&mlp,
+					    sizeof (mlp));
+				}
+			}
+
+			if (connp->conn_ipversion == IPV4_VERSION ||
+			    (dccp->dccp_state <= DCCPS_LISTEN &&
+			    !connp->conn_ipv6_v6only &&
+			    IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
+
+				if (connp->conn_ipversion == IPV6_VERSION) {
+					dce.dccpConnRemAddress = INADDR_ANY;
+					dce.dccpConnLocalAddress = INADDR_ANY;
+				} else {
+					dce.dccpConnRemAddress =
+					    connp->conn_faddr_v4;
+					dce.dccpConnLocalAddress =
+					    connp->conn_laddr_v4;
+				}
+
+				dce.dccpConnLocalPort =
+				    ntohs(connp->conn_lport);
+				dce.dccpConnRemPort =
+				    ntohs(connp->conn_fport);
+
+				/* XXX */
+
+				dce.dccpConnEntryInfo.ce_state =
+				    dccp->dccp_state;
+
+				dce.dccpConnCreationProcess =
+				    (connp->conn_cpid < 0) ?
+				    MIB2_UNKNOWN_PROCESS : connp->conn_cpid;
+				dce.dccpConnCreationTime =
+				    connp->conn_open_time;
+
+				(void) snmp_append_data2(mp_conn_ctl->b_cont,
+				    &mp_conn_tail, (char *)&dce, dce_size);
+
+				mlp.tme_connidx = v4_conn_idx++;
+				if (needattr) {
+					(void) snmp_append_data2(
+					    mp_attr_ctl->b_cont,
+					    &mp_attr_tail, (char *)&mlp,
+					    sizeof (mlp));
+				}
+			}
+		}
+	}
+
+	/* Sum up per CPU stats */
+	dccp_sum_mib(dccps, &dccp_mib);
+
+	/* Fixed length structure for IPv4 and IPv6 counters */
+	SET_MIB(dccp_mib.dccpConnTableSize, dce_size);
+	SET_MIB(dccp_mib.dccp6ConnTableSize, dce6_size);
+
+	/* Synchronize 32- and 64-bit counters */
+	SYNC32_MIB(&dccp_mib, dccpInSegs, dccpHCInSegs);
+	SYNC32_MIB(&dccp_mib, dccpOutSegs, dccpHCOutSegs);
+
+	optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_DCCP;
+	optp->name = 0;
+	(void) snmp_append_data(mpdata, (char *)&dccp_mib, dccp_mib_size);
+	optp->len = msgdsize(mpdata);
+	qreply(q, mpctl);
+
+	optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
+	    sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_DCCP;
+	optp->name = MIB2_DCCP_CONN;
+	optp->len = msgdsize(mp_conn_ctl->b_cont);
+	qreply(q, mp_conn_ctl);
+
+	optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
+	    sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_DCCP;
+	optp->name = EXPER_XPORT_MLP;
+	optp->len = msgdsize(mp_attr_ctl->b_cont);
+	if (optp->len == 0) {
+		freemsg(mp_attr_ctl);
+	} else {
+		qreply(q, mp_attr_ctl);
+	}
+
+	optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
+	    sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_DCCP6;
+	optp->name = MIB2_DCCP6_CONN;
+	optp->len = msgdsize(mp6_conn_ctl->b_cont);
+	qreply(q, mp6_conn_ctl);
+
+	optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
+	    sizeof (struct T_optmgmt_ack)];
+	optp->level = MIB2_DCCP6;
+	optp->name = EXPER_XPORT_MLP;
+	optp->len = msgdsize(mp6_attr_ctl->b_cont);
+	if (optp->len == 0) {
+		freemsg(mp6_attr_ctl);
+	} else {
+		qreply(q, mp6_attr_ctl);
+	}
+
+	return (mp2ctl);
+}
+
+/*
+ * DCCP kernel statistics.
+ */
+void *
+dccp_kstat_init(netstackid_t stackid)
+{
+	kstat_t	*ksp;
+
+	dccp_named_kstat_t template = {
+		{ "activeOpens",	KSTAT_DATA_UINT32, 0 },
+		{ "passiveOpens",	KSTAT_DATA_UINT32, 0 },
+		{ "inSegs",		KSTAT_DATA_UINT64, 0 },
+		{ "outSegs",		KSTAT_DATA_UINT64, 0 },
+	};
+
+	ksp = kstat_create_netstack(DCCP_MOD_NAME, 0, DCCP_MOD_NAME, "mib2",
+	    KSTAT_TYPE_NAMED, NUM_OF_FIELDS(dccp_named_kstat_t), 0, stackid);
+	if (ksp == NULL) {
+		return (NULL);
+	}
+
+	bcopy(&template, ksp->ks_data, sizeof (template));
+	ksp->ks_update = dccp_kstat_update;
+	ksp->ks_private = (void *)(uintptr_t)stackid;
+
+	kstat_install(ksp);
+
+	return (ksp);
+}
+
+/*
+ * Destroy DCCP kernel statistics.
+ */
+void
+dccp_kstat_fini(netstackid_t stackid, kstat_t *ksp)
+{
+
+	if (ksp != NULL) {
+		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
+		kstat_delete_netstack(ksp, stackid);
+	}
+}
+
+/*
+ * Update DCCP kernel statistics.
+ */
+static int
+dccp_kstat_update(kstat_t *kp, int rw)
+{
+	conn_t			*connp;
+	connf_t			*connfp;
+	dccp_named_kstat_t	*dccpkp;
+	dccp_t			*dccp;
+	dccp_stack_t		*dccps;
+	ip_stack_t		*ipst;
+	netstack_t		*ns;
+	netstackid_t		stackid;
+	mib2_dccp_t		dccp_mib;
+
+	if (rw == KSTAT_WRITE) {
+		return (EACCES);
+	}
+
+	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
+	ns = netstack_find_by_stackid(stackid);
+	if (ns == NULL) {
+		return (-1);
+	}
+
+	dccps = ns->netstack_dccp;
+	if (dccps == NULL) {
+		netstack_rele(ns);
+		return (-1);
+	}
+
+	dccpkp = (dccp_named_kstat_t *)kp->ks_data;
+	ipst = ns->netstack_ip;
+
+	bzero(&dccp_mib, sizeof (dccp_mib));
+	dccp_sum_mib(dccps, &dccp_mib);
+
+	/* Fixed length structure for IPv4 and IPv6 counters */
+	SET_MIB(dccp_mib.dccpConnTableSize, sizeof (mib2_dccpConnEntry_t));
+	SET_MIB(dccp_mib.dccp6ConnTableSize, sizeof (mib2_dccp6ConnEntry_t));
+
+	dccpkp->activeOpens.value.ui32 = dccp_mib.dccpActiveOpens;
+	dccpkp->passiveOpens.value.ui32 = dccp_mib.dccpPassiveOpens;
+	dccpkp->inSegs.value.ui64 = dccp_mib.dccpHCInSegs;
+	dccpkp->outSegs.value.ui64 = dccp_mib.dccpHCOutSegs;
+
+	return (0);
+}
+
+/*
+ *
+ */
+void *
+dccp_kstat2_init(netstackid_t stackid)
+{
+	kstat_t	*ksp;
+
+	dccp_stat_t template = {
+		{ "dccp_sock_fallback",		KSTAT_DATA_UINT64, 0 },
+	};
+
+	ksp = kstat_create_netstack(DCCP_MOD_NAME, 0, "dccpstat", "net",
+	    KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 0,
+	    stackid);
+	if (ksp == NULL) {
+		return (NULL);
+	}
+
+	bcopy(&template, ksp->ks_data, sizeof (template));
+	ksp->ks_private = (void *)(uintptr_t)stackid;
+	ksp->ks_update = dccp_kstat2_update;
+
+	kstat_install(ksp);
+
+	return (ksp);
+}
+
+/*
+ * Destroy DCCP kernel statistics.
+ */
+void
+dccp_kstat2_fini(netstackid_t stackid, kstat_t *ksp)
+{
+	if (ksp != NULL) {
+		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
+		kstat_delete_netstack(ksp, stackid);
+	}
+}
+
+/*
+ * Update routine for .
+ */
+static int
+dccp_kstat2_update(kstat_t *kp, int rw)
+{
+	dccp_stack_t	*dccps;
+	dccp_stat_t	*stats;
+	netstack_t	*ns;
+	netstackid_t	stackid;
+	int		i;
+	int		cnt;
+
+	if (rw == KSTAT_WRITE) {
+		return (EACCES);
+	}
+
+	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
+	ns = netstack_find_by_stackid(stackid);
+	if (ns == NULL) {
+		return (-1);
+	}
+
+	dccps = ns->netstack_dccp;
+	if (dccps == NULL) {
+		netstack_rele(ns);
+		return (-1);
+	}
+
+	stats = (dccp_stat_t *)kp->ks_data;
+	dccp_clr_stats(stats);
+
+	/* Sum up all stats */
+	cnt = dccps->dccps_sc_cnt;
+	for (i = 0; i < cnt; i++) {
+		dccp_add_stats(&dccps->dccps_sc[i]->dccp_sc_stats, stats);
+	}
+
+	netstack_rele(ns);
+
+	return (0);
+}
+
+/*
+ * Add stats from one to another.
+ */
+static void
+dccp_add_mib(mib2_dccp_t *from, mib2_dccp_t *to)
+{
+	to->dccpActiveOpens += from->dccpActiveOpens;
+	to->dccpPassiveOpens += from->dccpPassiveOpens;
+	to->dccpInSegs += from->dccpInSegs;
+	to->dccpOutSegs += from->dccpOutSegs;
+}
+
+/*
+ * Sum up all MIB-II stats for a dccp_stack_t from all per CPU stats.
+ */
+static void
+dccp_sum_mib(dccp_stack_t *dccps, mib2_dccp_t *dccp_mib)
+{
+	int	i;
+	int	cnt;
+
+	cnt = dccps->dccps_sc_cnt;
+	for (i = 0; i < cnt; i++) {
+		dccp_add_mib(&dccps->dccps_sc[i]->dccp_sc_mib, dccp_mib);
+	}
+}
+
+/*
+ * Set all dccp_stat_t counters to zero.
+ */
+static void
+dccp_clr_stats(dccp_stat_t *stats)
+{
+	stats->dccp_sock_fallback.value.ui64 = 0;
+}
+
+/*
+ * Add counters from the per CPU stats.
+ */
+static void
+dccp_add_stats(dccp_stat_counter_t *from, dccp_stat_t *to)
+{
+	to->dccp_sock_fallback.value.ui64 +=
+	    from->dccp_sock_fallback;
+}
--- /dev/null	2012-08-18 10:37:11.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_timers.c	2012-08-18 10:37:11.160576772 +0000
@@ -0,0 +1,340 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * This file contains function related to setting and deleting timers.
+ */
+
+#include <sys/types.h>
+#include <sys/strlog.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/squeue_impl.h>
+#include <sys/squeue.h>
+#include <sys/callo.h>
+
+#include <inet/common.h>
+#include <inet/ip.h>
+#include <inet/ip_ire.h>
+#include <inet/ip_rts.h>
+#include <inet/dccp_impl.h>
+
+#include <sys/cmn_err.h>
+
+kmem_cache_t	*dccp_timercache;
+
+static void	dccp_timer_callback(void *);
+static void	dccp_timer_handler(void *, mblk_t *, void *, ip_recv_attr_t *);
+static void	dccp_timer_free(dccp_t *, mblk_t *);
+
+/*
+ * Allocate a new timer.
+ */
+timeout_id_t
+dccp_timeout(conn_t *connp, void (*f)(void *), hrtime_t tim)
+{
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_timer_t	*dccpt;
+	mblk_t		*mp;
+
+	cmn_err(CE_NOTE, "dccp_timers.c: dccp_timeout");
+
+	ASSERT(connp->conn_sqp != NULL);
+
+	if (dccp->dccp_timercache == NULL) {
+		mp = dccp_timermp_alloc(KM_NOSLEEP | KM_PANIC);
+	} else {
+		mp = dccp->dccp_timercache;
+		dccp->dccp_timercache = mp->b_next;
+		mp->b_next = NULL;
+		ASSERT(mp->b_wptr == NULL);
+	}
+
+	CONN_INC_REF(connp);
+	dccpt = (dccp_timer_t *)mp->b_rptr;
+	dccpt->connp = connp;
+	dccpt->dccpt_proc = f;
+	dccpt->dccpt_tid = timeout_generic(CALLOUT_NORMAL, dccp_timer_callback,
+	    mp, tim * MICROSEC, CALLOUT_TCP_RESOLUTION, CALLOUT_FLAG_ROUNDUP);
+	/* CALLOUT_DCCP_RESOLUTION */
+	VERIFY(!(dccpt->dccpt_tid & CALLOUT_ID_FREE));
+
+	return ((timeout_id_t)mp);
+}
+
+/*
+ * Callback function.
+ */
+static void
+dccp_timer_callback(void *arg)
+{
+	conn_t		*connp;
+	dccp_timer_t	*dccpt;
+	mblk_t		*mp = (mblk_t *)arg;
+
+	dccpt = (dccp_timer_t *)mp->b_rptr;
+	connp = dccpt->connp;
+	SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_timer_handler, connp,
+	    NULL, SQ_FILL, SQTAG_DCCP_TIMER);
+}
+
+/*
+ * Fires the timer callback function.
+ */
+/* ARGSUSED */
+static void
+dccp_timer_handler(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
+{
+	conn_t		*connp = (conn_t *)arg;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_timer_t	*dccpt;
+
+	cmn_err(CE_NOTE, "dccp_timers.c: dccp_timer_handler");
+
+	dccpt = (dccp_timer_t *)mp->b_rptr;
+
+	ASSERT(connp == dccpt->connp);
+	ASSERT((squeue_t *)arg2 == connp->conn_sqp);
+
+	if (dccpt->dccpt_tid & CALLOUT_ID_FREE) {
+		dccp_timer_free(connp->conn_dccp, mp);
+		return;
+	}
+
+	if (dccp->dccp_state != DCCPS_CLOSED) {
+		(*dccpt->dccpt_proc)(connp);
+	} else {
+		dccp->dccp_timer_tid = 0;
+	}
+
+	dccp_timer_free(connp->conn_dccp, mp);
+}
+
+clock_t
+dccp_timeout_cancel(conn_t *connp, timeout_id_t id)
+{
+	dccp_timer_t	*dccpt;
+	mblk_t		*mp = (mblk_t *)id;
+	clock_t		delta;
+
+	if (mp == NULL) {
+		return (-1);
+	}
+
+	dccpt = (dccp_timer_t *)mp->b_rptr;
+	ASSERT(dccpt->connp == connp);
+
+	delta = untimeout_default(dccpt->dccpt_tid, 0);
+
+	if (delta >= 0) {
+		dccp_timer_free(connp->conn_dccp, mp);
+		CONN_DEC_REF(connp);
+	} else {
+		dccpt->dccpt_tid |= CALLOUT_ID_FREE;
+		delta = 0;
+	}
+
+	return (TICK_TO_MSEC(delta));
+}
+
+/*
+ * Allocate per-dccp timer cache.
+ */
+mblk_t *
+dccp_timermp_alloc(int kmflags)
+{
+	mblk_t	*mp;
+
+	mp = (mblk_t *)kmem_cache_alloc(dccp_timercache, kmflags & ~KM_PANIC);
+	if (mp != NULL) {
+		mp->b_next = mp->b_prev = NULL;
+		mp->b_rptr = (uchar_t *)(&mp[1]);
+		mp->b_wptr = NULL;
+		mp->b_datap = NULL;
+		mp->b_queue = NULL;
+		mp->b_cont = NULL;
+	} else if (kmflags & KM_PANIC) {
+		/* XXX */
+	}
+
+	return (mp);
+}
+
+/*
+ * Free per-dccp timer cache.
+ */
+void
+dccp_timermp_free(dccp_t *dccp)
+{
+	mblk_t	*mp;
+
+	while ((mp = dccp->dccp_timercache) != NULL) {
+		ASSERT(mp->b_wptr == NULL);
+		dccp->dccp_timercache = dccp->dccp_timercache->b_next;
+		kmem_cache_free(dccp_timercache, mp);
+	}
+}
+
+/*
+ * Free timer event.
+ */
+static void
+dccp_timer_free(dccp_t *dccp, mblk_t *mp)
+{
+	mblk_t	*mp1 = dccp->dccp_timercache;
+
+	if (mp->b_wptr != NULL) {
+		if (mp->b_wptr != (uchar_t *)-1) {
+			freeb(mp);
+		} else {
+			kmem_free(mp, (size_t)mp->b_datap);
+		}
+	} else if (mp1 == NULL || mp1->b_next == NULL) {
+		mp->b_rptr = (uchar_t *)(&mp[1]);
+		mp->b_next = mp1;
+		dccp->dccp_timercache = mp;
+	} else {
+		kmem_cache_free(dccp_timercache, mp);
+	}
+}
+
+/*
+ * Stop all DCCP timers.
+ */
+void
+dccp_timers_stop(dccp_t *dccp)
+{
+	if (dccp->dccp_timer_tid != 0) {
+		(void) DCCP_TIMER_CANCEL(dccp, dccp->dccp_timer_tid);
+		dccp->dccp_timer_tid = 0;
+	}
+
+	if (dccp->dccp_ka_tid != 0) {
+		(void) DCCP_TIMER_CANCEL(dccp, dccp->dccp_ka_tid);
+		dccp->dccp_ka_tid = 0;
+	}
+}
+
+/*
+ * Keepalive timer.
+ */
+void
+dccp_keepalive_timer(void *arg)
+{
+	conn_t		*connp = (conn_t *)arg;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	int32_t		firetime;
+	int32_t		idletime;
+	int32_t		ka_intrvl;
+
+	cmn_err(CE_NOTE, "dccp_timers.c: dccp_keepalive_timer");
+
+	dccp->dccp_ka_tid = 0;
+
+	DCCPS_BUMP_MIB(dccps, dccpTimKeepalive);
+	ka_intrvl = dccp->dccp_ka_interval;
+
+	if (dccp->dccp_state > DCCPS_CLOSING) {
+		return;
+	}
+
+	if (dccp->dccp_state < DCCPS_OPEN) {
+		dccp->dccp_ka_tid = DCCP_TIMER(dccp, dccp_keepalive_timer,
+		    ka_intrvl);
+		return;
+	}
+
+	idletime = TICK_TO_MSEC(ddi_get_lbolt() - dccp->dccp_last_recv_time);
+
+	/* XXX */
+
+	if ((firetime = ka_intrvl - idletime) < 0) {
+		firetime = ka_intrvl;
+	}
+
+	dccp->dccp_ka_tid = DCCP_TIMER(dccp, dccp_keepalive_timer, firetime);
+}
+
+/*
+ * Timer service routine.
+ */
+void
+dccp_timer(void *arg)
+{
+	conn_t		*connp = (conn_t *)arg;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	mblk_t		*mp;
+	clock_t		first_threshold;
+	clock_t		second_threshold;
+	clock_t		ms;
+	uint32_t	mss;
+	boolean_t	dont_timeout = B_FALSE;
+
+	cmn_err(CE_NOTE, "dccp_timers.c: dccp_timer");
+
+	dccp->dccp_timer_tid = 0;
+
+	first_threshold = dccp->dccp_first_timer_threshold;
+	second_threshold = dccp->dccp_second_timer_threshold;
+	switch (dccp->dccp_state) {
+	case DCCPS_REQUEST:
+		first_threshold = dccp->dccp_first_ctimer_threshold;
+		second_threshold = dccp->dccp_second_ctimer_threshold;
+
+		if (second_threshold == 0) {
+			second_threshold = dccps->dccps_ip_abort_linterval;
+			if (dccp->dccp_active_open) {
+				dont_timeout = B_TRUE;
+			}
+		}
+		break;
+	case DCCPS_CLOSING:
+		(void) dccp_clean_death(dccp, 0);
+		return;
+	default:
+		if (connp->conn_debug) {
+			(void) strlog(DCCP_MOD_ID, 0, 1, SL_TRACE|SL_ERROR,
+			    "dccp_timer: strange state (%d) %s",
+			    dccp->dccp_state, dccp_display(dccp, NULL,
+			    DISP_PORT_ONLY));
+		}
+		return;
+	}
+
+	ASSERT(second_threshold != 0);
+
+	ms = 900;
+
+	DCCP_TIMER_RESTART(dccp, ms);
+
+	DCCPS_BUMP_MIB(dccps, dccpRetransSegs);
+}
--- /dev/null	2012-08-18 10:37:11.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_tpi.c	2012-08-18 10:37:11.357947486 +0000
@@ -0,0 +1,434 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Functions related to TPI.
+ */
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/stropts.h>
+#include <sys/strlog.h>
+#define _SUN_TPI_VERSION 2
+#include <sys/tihdr.h>
+#include <sys/suntpi.h>
+#include <sys/xti_inet.h>
+#include <sys/squeue_impl.h>
+#include <sys/squeue.h>
+#include <sys/tsol/tnet.h>
+
+#include <inet/common.h>
+#include <inet/dccp_impl.h>
+#include <inet/ip.h>
+#include <inet/proto_set.h>
+
+#include <sys/cmn_err.h>
+
+
+/*
+ * This file contains functions related to the TPI interface.
+ */
+
+/*
+ * XXX
+ */
+static void
+dccp_copy_info(struct T_info_ack *tia, dccp_t *dccp)
+{
+	conn_t		*connp = dccp->dccp_connp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	extern struct T_info_ack dccp_g_t_info_ack;
+	extern struct T_info_ack dccp_g_t_info_ack_v6;
+
+	if (connp->conn_family == AF_INET6) {
+		*tia = dccp_g_t_info_ack_v6;
+	} else {
+		*tia = dccp_g_t_info_ack;
+	}
+
+	/* XXX */
+}
+
+/*
+ * XXX
+ */
+void
+dccp_do_capability_ack(dccp_t *dccp, struct T_capability_ack *tcap,
+    t_uscalar_t cap_bits1)
+{
+	tcap->CAP_bits1 = 0;
+
+	if (cap_bits1 & TC1_INFO) {
+		dccp_copy_info(&tcap->INFO_ack, dccp);
+		tcap->CAP_bits1 |= TC1_INFO;
+	}
+
+	if (cap_bits1 & TC1_ACCEPTOR_ID) {
+		tcap->ACCEPTOR_id = dccp->dccp_acceptor_id;
+		tcap->CAP_bits1 |= TC1_ACCEPTOR_ID;
+	}
+}
+
+/*
+ * This routine responds to T_CAPABILITY_REQ messages.
+ */
+void
+dccp_capability_req(dccp_t *dccp, mblk_t *mp)
+{
+	struct T_capability_ack	*tcap;
+	t_uscalar_t		cap_bits1;
+
+	if (MBLKL(mp) < sizeof (struct T_capability_req)) {
+		freemsg(mp);
+		return;
+	}
+
+	cap_bits1 = ((struct T_capability_req *)mp->b_rptr)->CAP_bits1;
+
+	mp = tpi_ack_alloc(mp, sizeof (struct T_capability_ack),
+	    mp->b_datap->db_type, T_CAPABILITY_ACK);
+	if (mp == NULL) {
+		return;
+	}
+
+	tcap = (struct T_capability_ack *)mp->b_rptr;
+	dccp_do_capability_ack(dccp, tcap, cap_bits1);
+
+	putnext(dccp->dccp_connp->conn_rq, mp);
+}
+
+/*
+ * This routine responds to T_INFO_REQ messages.
+ */
+void
+dccp_info_req(dccp_t *dccp, mblk_t *mp)
+{
+	mp = tpi_ack_alloc(mp, sizeof (struct T_info_ack), M_PCPROTO,
+	    T_INFO_ACK);
+	if (mp == NULL) {
+		dccp_err_ack(dccp, mp, TSYSERR, ENOMEM);
+		return;
+	}
+
+	dccp_copy_info((struct T_info_ack *)mp->b_rptr, dccp);
+	putnext(dccp->dccp_connp->conn_rq, mp);
+}
+
+/*
+ * This routine responds to T_ADDR_REQ messages.
+ */
+void
+dccp_addr_req(dccp_t *dccp, mblk_t *mp)
+{
+	conn_t	*connp = dccp->dccp_connp;
+	mblk_t	*ackmp;
+	uint_t	addrlen;
+	struct sockaddr		*sa;
+	struct T_addr_ack	*taa;
+
+	/* XXX */
+}
+
+/*
+ * Helper function to generate TPI errors acks.
+ */
+void
+dccp_err_ack(dccp_t *dccp, mblk_t *mp, int t_error, int sys_error)
+{
+	if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL) {
+		putnext(dccp->dccp_connp->conn_rq, mp);
+	}
+}
+
+void
+dccp_tpi_connect(dccp_t *dccp, mblk_t *mp)
+{
+	conn_t			*connp = dccp->dccp_connp;
+	queue_t			*q = connp->conn_wq;
+	struct sockaddr		*sa;
+	struct T_conn_req	*tcr;
+	sin_t			*sin;
+	sin6_t			*sin6;
+	cred_t			*cr;
+	pid_t			cpid;
+	socklen_t		len;
+	int			error;
+
+	cmn_err(CE_NOTE, "dccp_tpi.c: dccp_tpi_connect");
+
+	cr = msg_getcred(mp, &cpid);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		dccp_err_ack(dccp, mp, TSYSERR, EINVAL);
+		return;
+	}
+
+	tcr = (struct T_conn_req *)mp->b_rptr;
+
+	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
+	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tcr)) {
+		dccp_err_ack(dccp, mp, TPROTO, 0);
+		return;
+	}
+
+	error = proto_verify_ip_addr(connp->conn_family, sa, len);
+	if (error != 0) {
+		dccp_err_ack(dccp, mp, TSYSERR, 0);
+		return;
+	}
+
+	error = dccp_do_connect(dccp->dccp_connp, sa, len, cr, cpid);
+	if (error < 0) {
+		mp = mi_tpi_err_ack_alloc(mp, -error, 0);
+	} else if (error > 0) {
+		mp = mi_tpi_err_ack_alloc(mp, TSYSERR, error);
+	} else {
+		mp = mi_tpi_ok_ack_alloc(mp);
+	}
+}
+
+int
+dccp_tpi_close(queue_t *q, int flags)
+{
+	conn_t	*connp;
+
+	ASSERT(WR(q)->q_next == NULL);
+
+	connp = Q_TO_CONN(q);
+
+	dccp_close_common(connp, flags);
+
+	qprocsoff(q);
+	inet_minor_free(connp->conn_minor_arena, connp->conn_dev);
+
+	return (0);
+}
+
+int
+dccp_tpi_close_accept(queue_t *q)
+{
+	vmem_t	*minor_arena;
+	dev_t	conn_dev;
+
+	cmn_err(CE_NOTE, "dccp_tpi.c: dccp_tpi_close_accept");
+
+	return (0);
+}
+
+boolean_t
+dccp_conn_con(dccp_t *dccp, uchar_t *iphdr, mblk_t *idmp,
+    mblk_t **defermp, ip_recv_attr_t *ira)
+{
+	conn_t	*connp = dccp->dccp_connp;
+	sin_t	sin;
+	sin6_t	sin6;
+	mblk_t	*mp;
+	char	*optp = NULL;
+	int	optlen = 0;
+
+	cmn_err(CE_NOTE, "dccp_tpi.c: dccp_conn_con");
+
+	if (defermp != NULL) {
+		*defermp = NULL;
+	}
+
+	if (IPH_HDR_VERSION(iphdr) == IPV4_VERSION) {
+		/* Packet is IPv4 */
+		if (connp->conn_family == AF_INET) {
+			sin = sin_null;
+			sin.sin_addr.s_addr = connp->conn_faddr_v4;
+			sin.sin_port = connp->conn_fport;
+			sin.sin_family = AF_INET;
+			mp = mi_tpi_conn_con(NULL, (char *)&sin,
+			    (int)sizeof (sin_t), optp, optlen);
+		} else {
+			sin6 = sin6_null;
+			sin6.sin6_addr = connp->conn_faddr_v6;
+			sin6.sin6_port = connp->conn_fport;
+			sin6.sin6_family = AF_INET6;
+			mp = mi_tpi_conn_con(NULL, (char *)&sin6,
+			    (int)sizeof (sin6_t), optp, optlen);
+		}
+	} else {
+		ip6_t	*ip6h = (ip6_t *)iphdr;
+
+		ASSERT(IPH_HDR_VERSION(iphdr) == IPV6_VERSION);
+		ASSERT(connp->conn_family == AF_INET6);
+
+		sin6 = sin6_null;
+		sin6.sin6_addr = connp->conn_faddr_v6;
+		sin6.sin6_port = connp->conn_fport;
+		sin6.sin6_family = AF_INET6;
+		sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK;
+		mp = mi_tpi_conn_con(NULL, (char *)&sin6,
+		    (int)sizeof (sin6_t), optp, optlen);
+	}
+
+	if (!mp) {
+		return (B_FALSE);
+	}
+
+	mblk_copycred(mp, idmp);
+
+	if (defermp == NULL) {
+		if (IPCL_IS_NONSTR(connp)) {
+			cmn_err(CE_NOTE, "calling su_connected");
+			(*connp->conn_upcalls->su_connected)
+			    (connp->conn_upper_handle, dccp->dccp_connid,
+			    ira->ira_cred, ira->ira_cpid);
+			freemsg(mp);
+		} else {
+			if (ira->ira_cred != NULL) {
+				/* So that getpeerucred works for TPI sockfs */
+				mblk_setcred(mp, ira->ira_cred, ira->ira_cpid);
+			}
+			putnext(connp->conn_rq, mp);
+		}
+	} else {
+		*defermp = mp;
+	}
+
+	/* XXX */
+	return (B_TRUE);
+}
+
+/*
+ * Routine to get the values of options.
+ */
+int
+dccp_tpi_opt_get(queue_t *q, int level, int name, uchar_t *ptr)
+{
+	return (dccp_opt_get(Q_TO_CONN(q), level, name, ptr));
+}
+
+/*
+ * Routine to set the values of options.
+ */
+/* ARGSUSED */
+int
+dccp_tpi_opt_set(queue_t *q, uint_t optset_context, int level, int name,
+    uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp,
+    void *thisdg_attrs, cred_t *cr)
+{
+	conn_t	*connp =  Q_TO_CONN(q);
+
+	return (dccp_opt_set(connp, optset_context, level, name, inlen, invalp,
+	    outlenp, outvalp, thisdg_attrs, cr));
+}
+
+void
+dccp_tpi_accept(queue_t *q, mblk_t *mp)
+{
+	struct T_ok_ack		*ok;
+	struct T_conn_res	*conn_res;
+	conn_t			*econnp;
+	dccp_t			*eager;
+	dccp_t			*listener;
+	queue_t			*rq = RD(q);
+	mblk_t			*discon_mp;
+	cred_t			*cr;
+
+	cmn_err(CE_NOTE, "dccp_tpi.c: dccp_tpi_accept");
+
+	ASSERT(DB_TYPE(mp) == M_PROTO);
+
+	cr = msg_getcred(mp, NULL);
+	ASSERT(cr != NULL);
+	if (cr == NULL) {
+		mp = mi_tpi_err_ack_alloc(mp, TSYSERR, EINVAL);
+		if (mp != NULL) {
+			putnext(rq, mp);
+		}
+		return;
+	}
+
+	conn_res = (struct T_conn_res *)mp->b_rptr;
+	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
+	if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_conn_res)) {
+		mp = mi_tpi_err_ack_alloc(mp, TPROTO, 0);
+		if (mp != NULL) {
+			putnext(rq, mp);
+		}
+		return;
+	}
+
+	switch (conn_res->PRIM_type) {
+	case O_T_CONN_RES:
+	case T_CONN_RES:
+		putnext(rq, mp);
+		return;
+	default:
+		mp = mi_tpi_err_ack_alloc(mp, TNOTSUPPORT, 0);
+		if (mp != NULL) {
+			putnext(rq, mp);
+		}
+		return;
+	}
+}
+
+static void
+dccp_accept_swap(dccp_t *listener, dccp_t *acceptor, dccp_t *eager)
+{
+	conn_t	*econnp;
+	conn_t	*aconnp;
+}
+
+/*
+ * This runs at the tail end of accept processing on the squeue of the
+ * new connection.
+ */
+static void
+dccp_accept_finish(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
+{
+	conn_t		*connp = (conn_t *)arg;
+	dccp_t		*dccp = connp->conn_dccp;
+	dccp_stack_t	*dccps = dccp->dccp_dccps;
+	queue_t		*q = connp->conn_rq;
+	struct stroptions	*stropt;
+	struct sock_proto_props	sopp;
+
+	/* Should never be called for non-STREAMS sockets */
+	ASSERT(!IPCL_IS_NONSTR(connp));
+
+	/* We should just receive a single mblk that fits a T_discon_ind */
+	ASSERT(mp->b_cont == NULL);
+
+	/* XXX */
+
+	dccp_get_proto_props(dccp, &sopp);
+
+	ASSERT(DB_REF(mp) == 1);
+	ASSERT(MBLKSIZE(mp) >= sizeof (struct stroptions));
+
+	DB_TYPE(mp) = M_SETOPTS;
+
+	/* XXX */
+
+	dccp->dccp_hard_binding = B_FALSE;
+
+	if (connp->conn_keepalive) {
+		dccp->dccp_ka_last_intrvl = 0;
+		dccp->dccp_ka_tid = DCCP_TIMER(dccp, dccp_keepalive_timer,
+		    dccp->dccp_ka_interval);
+	}
+}
--- /dev/null	2012-08-18 10:37:11.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_tunables.c	2012-08-18 10:37:11.523731195 +0000
@@ -0,0 +1,87 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * This file contains tunable properties for DCCP.
+ */
+#include <inet/ip.h>
+#include <inet/ip6.h>
+#include <inet/dccp_impl.h>
+#include <sys/sunddi.h>
+
+mod_prop_info_t dccp_propinfo_tbl[] = {
+	/* tunable - 0 */
+	{ "smallest_nonpriv_port", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {1024, (32 * 1024), 1024}, {1024} },
+
+	{ "smallest_anon_port", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {1024, ULP_MAX_PORT, 32*1024}, {32*1024} },
+
+	{ "largest_anon_port", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {1024, ULP_MAX_PORT, ULP_MAX_PORT}, {ULP_MAX_PORT} },
+
+	{ "_xmit_lowat", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {0, (1<<30), DCCP_XMIT_LOWATER},
+	    {DCCP_XMIT_LOWATER} },
+
+	{ "_debug", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {0, 10, 0}, {0} },
+
+	{ "_rst_sent_rate_enabled", MOD_PROTO_DCCP,
+	    mod_set_boolean, mod_get_boolean,
+	    {B_TRUE}, {B_TRUE} },
+
+	{ "_rst_sent_rate", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {0, UINT32_MAX, 40}, {40} },
+
+	{ "_ip_abort_cinterval", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {1*SECONDS, UINT32_MAX, 3*MINUTES}, {3*MINUTES} },
+
+	{ "_ip_abort_linterval", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {1*SECONDS, UINT32_MAX, 3*MINUTES}, {3*MINUTES} },
+
+	{ "_ip_abort_interval", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {500*MS, UINT32_MAX, 5*MINUTES}, {5*MINUTES} },
+
+	/* tunable - 10 */
+	{ "_ip_notify_cinterval", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {1*SECONDS, UINT32_MAX, 10*SECONDS}, {10*SECONDS} },
+
+	{ "_ip_notify_interval", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {500*MS, UINT32_MAX, 10*SECONDS}, {10*SECONDS} },
+
+	{ "_keepalive_interval", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {10*SECONDS, 10*DAYS, 2*HOURS}, {2*HOURS} },
+
+	{ "_keepalive_abort_interval", MOD_PROTO_DCCP,
+	    mod_set_uint32, mod_get_uint32,
+	    {0, UINT32_MAX, 8*MINUTES}, {8*MINUTES} },
+
+	{ NULL, 0, NULL, NULL, {0}, {0} }
+};
+
+int dccp_propinfo_count = A_CNT(dccp_propinfo_tbl);
--- /dev/null	2012-08-18 10:37:11.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccpddi.c	2012-08-18 10:37:11.742640611 +0000
@@ -0,0 +1,59 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/modctl.h>
+#include <inet/common.h>
+#include <inet/ip.h>
+#include <sys/strsubr.h>
+#include <sys/socketvar.h>
+#include <inet/dccp.h>
+#include <inet/dccp_impl.h>
+
+#define	INET_NAME	"dccp"
+#define	INET_MODDESC	"DCCP dummy STREAMS module"
+#define	INET_DEVDESC	"DCCP STREAMS driver"
+#define	INET_SOCKDESC	"DCCP socket module"
+#define	INET_MODSTRTAB	dummymodinfo
+#define	INET_DEVSTRTAB	dccpinfov4
+#define	INET_MODMTFLAGS	D_MP
+#define	INET_SOCK_PROTO_CREATE_FUNC	(*dccp_create)
+#define	INET_SOCK_PROTO_FB_FUNC		(*dccp_fallback)
+#define	INET_SOCK_FALLBACK_DEV_V4	"/dev/dccp"
+#define	INET_SOCK_FALLBACK_DEV_V6	"/dev/dccp6"
+#define	INET_DEVMINOR	0
+#define INET_MODMTFLAGS	D_MP
+#define	INET_DEVMTFLAGS (D_MP|_D_DIRECT)
+
+#include "../inetddi.c"
+
+int
+_init(void)
+{
+	return (mod_install(&modlinkage));
+}
+
+int
+_fini(void)
+{
+	return (mod_remove(&modlinkage));
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+	return (mod_info(&modlinkage, modinfop));
+}
--- /dev/null	2012-08-18 10:37:11.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp_impl.h	2012-08-18 10:37:11.937118819 +0000
@@ -0,0 +1,379 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner. All rights reserved.
+ */
+
+#ifndef	_INET_DCCP_IMPL_H
+#define	_INET_DCCP_IMPL_H
+
+#include <sys/int_types.h>
+#include <sys/netstack.h>
+#include <sys/socket.h>
+#include <sys/socket_proto.h>
+#include <sys/clock_impl.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/dccp.h>
+
+#include <inet/common.h>
+#include <inet/dccp.h>
+#include <inet/ip.h>
+#include <inet/ip6.h>
+#include <inet/optcom.h>
+#include <inet/tunables.h>
+
+#include <inet/dccp_stack.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#ifdef	_KERNEL
+
+#define	DCCP_MOD_ID		5999 /* XXX */
+
+extern struct qinit	dccp_sock_winit;
+extern struct qinit	dccp_winit;
+
+extern sock_downcalls_t	sock_dccp_downcalls;
+
+#define	DCCP_XMIT_LOWATER	(4 * 1024)
+#define	DCCP_XMIT_HIWATER	49152
+#define	DCCP_RECV_LOWATER	(2 * 1024)
+#define	DCCP_RECV_HIWATER	128000
+
+#define	TIDUSZ	4096	/* transport interface data unit size */
+
+/*
+ * Format arguments passed to dccp_display.
+ */
+#define	DISP_PORT_ONLY		1
+#define	DISP_ADDR_AND_PORT	2
+
+/*
+ * Bind hash array size and hash function.
+ */
+#define	DCCP_BIND_FANOUT_SIZE		128
+#define	DCCP_BIND_HASH(lport, size)	((ntohs((uint16_t)lport)) & (size - 1))
+
+/*
+ * Was this tcp created via socket() interface?
+ */
+#define	DCCP_IS_SOCKET(dccp)	((dccp)->dccp_issocket)
+
+/*
+ * Is this dccp not attached to any upper client?
+ */
+#define	DCCP_IS_DETACHED(dccp)	((dccp)->dccp_detached)
+
+/* Packet types (RFC 4340, Section 5.1.) */
+#define	DCCP_PKT_REQUEST	0
+#define	DCCP_PKT_RESPONSE	1
+#define	DCCP_PKT_DATA		2
+#define	DCCP_PKT_ACK		3
+#define	DCCP_PKT_DATAACK	4
+#define	DCCP_PKT_CLOSEREQ	5
+#define	DCCP_PKT_CLOSE		6
+#define	DCCP_PKT_RESET		7
+#define	DCCP_PKT_SYNC		8
+#define	DCCP_PKT_SYNCACK	9
+
+#define	DCCP_PACKET_REQUEST	0
+#define	DCCP_PACKET_RESPONSE	1
+#define	DCCP_PACKET_DATA	2
+#define	DCCP_PACKET_ACK		3
+#define	DCCP_PACKET_DATAACK	4
+#define	DCCP_PACKET_CLOSEREQ	5
+#define	DCCP_PACKET_CLOSE	6
+#define	DCCP_PACKET_RESET	7
+#define	DCCP_PACKET_SYNC	8
+#define	DCCP_PACKET_SYNCACK	9
+
+/*
+ * DCCP options and features.
+ */
+
+/*
+ * Options types (RFC 4340, Section 5.8.)
+ */
+#define	DCCP_OPTION_PADDING		0
+#define	DCCP_OPTION_MANDATORY		1
+#define	DCCP_OPTION_SLOW_RECEIVER	2
+#define	DCCP_OPTION_CHANGE_L		32
+#define	DCCP_OPTION_CONFIRM_L		33
+#define	DCCP_OPTION_CHANGE_R		34
+#define	DCCP_OPTION_CONFIRM_R		35
+#define	DCCP_OPTION_INIT_COOKIE		36
+#define	DCCP_OPTION_NDP_COUNT		37
+#define	DCCP_OPTION_ACK_VECTOR_1	38
+#define	DCCP_OPTION_ACK_VECTOR_2	39
+#define	DCCP_OPTION_DATA_DROPPED	40
+#define	DCCP_OPTION_TIMESTAMP		41
+#define	DCCP_OPTION_TIMESTAMP_ECHO	42
+#define	DCCP_OPTION_ELAPSED_TIME	43
+#define	DCCP_OPTION_DATA_CHECKSUM	44
+
+/*
+ * Feature types (RFC 4340, Section 6.4.)
+ */
+#define	DCCP_FEATURE_CCID			1
+#define	DCCP_FEATURE_ALLOW_SHORT_SEQNOS		2
+#define	DCCP_FEATURE_SEQUENCE_WINDOW		3
+#define	DCCP_FEATURE_ECN_INCAPABLE		4
+#define	DCCP_FEATURE_ACK_RATIO			5
+#define	DCCP_FEATURE_SEND_ACK_VECTOR		6
+#define	DCCP_FEATURE_SEND_NDP_COUNT		7
+#define	DCCP_FEATURE_MIN_CHECKSUM_COVERAGE	8
+#define	DCCP_FEATURE_CHECK_DATA_CHECKSUM	9
+
+/*
+ * Feature negotation states (RFC 4340, Section 6.6.2.)
+ */
+#define	DCCP_FEATURE_STATE_CHANGING		0
+#define	DCCP_FEATURE_STATE_UNSTABLE		1
+#define	DCCP_FEATURE_STATE_STABLE		2
+
+/*
+ * Reset types (RFC 4230, Section 5.6.)
+ */
+#define	DCCP_RESET_UNSPECIFIED			0
+#define	DCCP_RESET_CLOSED			1
+#define	DCCP_RESET_ABORTED			2
+#define	DCCP_RESET_NO_CONNECTION		3
+#define	DCCP_RESET_PACKET_ERROR			4
+#define	DCCP_RESET_OPTION_ERROR			5
+#define	DCCP_RESET_MANDATORY_ERROR		6
+#define	DCCP_RESET_CONNECTION_REFUSED		7
+#define	DCCP_RESET_BAD_SERVICE_CODE		8
+#define	DCCP_RESET_TOO_BUSY			9
+#define	DCCP_RESET_BAD_INIT_COOKIE		10
+#define	DCCP_RESET_AGGRESSION_PENALTY		11
+#define	DCCP_RESET_RESERVED			12
+
+typedef struct dccp_feature_s {
+	list_node_t	df_next;
+	uint8_t		df_option;
+	uint8_t		df_type;
+	uint8_t		df_state;
+	uint64_t	df_value;
+	boolean_t	df_mandatory;
+} dccp_feature_t;
+
+/* Options in DCCP header */
+typedef struct dccp_opt_s {
+	int		type;
+	boolean_t	mandatory;
+} dccp_opt_t;
+
+/*
+ * Tuneables.
+ */
+#define	dccps_smallest_nonpriv_port	dccps_propinfo_tbl[0].prop_cur_uval
+#define	dccps_smallest_anon_port	dccps_propinfo_tbl[1].prop_cur_uval
+#define	dccps_largest_anon_port		dccps_propinfo_tbl[2].prop_cur_uval
+
+#define	dccps_dbg			dccps_propinfo_tbl[4].prop_cur_uval
+#define	dccps_rst_sent_rate_enabled	dccps_propinfo_tbl[5].prop_cur_uval
+#define	dccps_rst_sent_rate		dccps_propinfo_tbl[6].prop_cur_uval
+
+#define	dccps_ip_abort_cinterval	dccps_propinfo_tbl[7].prop_cur_uval
+#define	dccps_ip_abort_linterval	dccps_propinfo_tbl[8].prop_cur_uval
+#define	dccps_ip_abort_interval		dccps_propinfo_tbl[9].prop_cur_uval
+#define	dccps_ip_notify_cinterval	dccps_propinfo_tbl[10].prop_cur_uval
+#define	dccps_ip_notify_interval	dccps_propinfo_tbl[11].prop_cur_uval
+#define	dccps_keepalive_interval_high	dccps_propinfo_tbl[12].prop_max_uval
+#define	dccps_keepalive_interval	dccps_propinfo_tbl[12].prop_cur_uval
+#define	dccps_keepalive_interval_low	dccps_propinfo_tbl[12].prop_min_uval
+#define	dccps_keepalive_abort_interval_high \
+					dccps_propinfo_tbl[13].prop_max_uval
+#define	dccps_keepalive_abort_interval	dccps_propinfo_tbl[13].prop_cur_uval
+#define	dccps_keepalive_abort_interval_low \
+					dccps_propinfo_tbl[13].prop_min_uval
+
+/*
+ * Timers.
+ */
+typedef struct dccp_timer_s {
+	conn_t	*connp;
+	void	(*dccpt_proc)(void *);
+	callout_id_t	dccpt_tid;
+} dccp_timer_t;
+
+extern kmem_cache_t	*dccp_timercache;
+
+#define	DCCP_TIMER(dccp, f, tim)	\
+	dccp_timeout(dccp->dccp_connp, f, tim)
+
+#define	DCCP_TIMER_CANCEL(dccp, id)	\
+	dccp_timeout_cancel(dccp->dccp_connp, id)
+
+#define	DCCP_TIMER_RESTART(dccp, intvl) {			\
+	if ((dccp)->dccp_timer_tid != 0)			\
+		(void) DCCP_TIMER_CANCEL((dccp), (dccp)->dccp_timer_tid); \
+	(dccp)->dccp_timer_tid = DCCP_TIMER((dccp), dccp_timer, (intvl)); \
+}
+
+extern struct qinit	dccp_rinitv4, dccp_rinitv6;
+
+extern optdb_obj_t	dccp_opt_obj;
+extern uint_t		dccp_max_optsize;
+
+extern int		dccp_squeue_flag;
+
+/*
+ * Functions in dccp.c
+ */
+extern int	dccp_build_hdrs(dccp_t *);
+extern conn_t	*dccp_create_common(cred_t *, boolean_t, boolean_t, int *);
+extern void	dccp_close_common(conn_t *, int);
+extern int	dccp_do_bind(conn_t *, struct sockaddr *, socklen_t, cred_t *,
+		    boolean_t);
+extern int	dccp_do_unbind(conn_t *);
+extern int	dccp_do_listen(conn_t *, struct sockaddr *, socklen_t, int,
+		    cred_t *, boolean_t);
+extern int	dccp_do_connect(conn_t *, const struct sockaddr *, socklen_t,
+		    cred_t *, pid_t);
+extern void	dccp_init_values(dccp_t *, dccp_t *);
+extern void	dccp_free(dccp_t *);
+extern void	*dccp_get_conn(void *, dccp_stack_t *);
+extern void	dccp_get_proto_props(dccp_t *, struct sock_proto_props *);
+extern int	dccp_set_destination(dccp_t *);
+extern int	dccp_clean_death(dccp_t *, int);
+
+
+/*
+ * Functions in dccp_bind.c
+ */
+extern void	dccp_bind_hash_insert(dccp_df_t *, dccp_t *, int);
+extern void	dccp_bind_hash_remove(dccp_t *);
+extern int	dccp_bind_check(conn_t *, struct sockaddr *, socklen_t,
+		    cred_t *cr, boolean_t);
+extern in_port_t dccp_bindi(dccp_t *, in_port_t, const in6_addr_t *, int,
+		    boolean_t, boolean_t, boolean_t);
+extern in_port_t dccp_update_next_port(in_port_t, const dccp_t *, boolean_t);
+
+/*
+ * Functions in dccp_features.c
+ */
+extern int	dccp_parse_feature(dccp_t *, uint8_t, uint8_t, uchar_t *,
+		    boolean_t);
+
+/*
+ * Functions in dccp_stats.c
+ */
+extern mblk_t	*dccp_snmp_get(queue_t *, mblk_t *, boolean_t);
+extern void	*dccp_kstat_init(netstackid_t);
+extern void	dccp_kstat_fini(netstackid_t, kstat_t *);
+extern void	*dccp_kstat2_init(netstackid_t);
+extern void	dccp_kstat2_fini(netstackid_t, kstat_t *);
+
+/*
+ * Functions in dccp_socket.c
+ */
+extern sock_lower_handle_t	dccp_create(int, int, int, sock_downcalls_t **,
+				    uint_t *, int *, int, cred_t *);
+extern int	dccp_fallback(sock_lower_handle_t, queue_t *, boolean_t,
+		    so_proto_quiesced_cb_t, sock_quiesce_arg_t *);
+extern boolean_t	dccp_newconn_notify(dccp_t *, ip_recv_attr_t *);
+
+/*
+ * Functions in dccp_input.c
+ */
+extern void	dccp_icmp_input(void *, mblk_t *, void *, ip_recv_attr_t *);
+extern void	dccp_input_data(void *, mblk_t *, void *, ip_recv_attr_t *);
+extern void	dccp_rsrv(queue_t *);
+extern void	dccp_input_listener_unbound(void *, mblk_t *, void *,
+		    ip_recv_attr_t *);
+extern boolean_t dccp_verifyicmp(conn_t *, void *, icmph_t *, icmp6_t *,
+		    ip_recv_attr_t *);
+
+/*
+ * Functions in dccp_misc.c
+ */
+extern void	dccp_stack_cpu_add(dccp_stack_t *, processorid_t);
+extern char	*dccp_display(dccp_t *, char *, char);
+
+/*
+ * Functions in dccp_options.c
+ */
+extern int	dccp_parse_options(dccp_t *, dccpha_t *);
+extern int	dccp_process_options(dccp_t *, dccpha_t *);
+extern int	dccp_generate_options(dccp_t *, void **, size_t *);
+
+/*
+ * Functions in dccp_output.c
+ */
+extern void	dccp_wput(queue_t *, mblk_t *);
+extern void	dccp_wput_data(dccp_t *, mblk_t *, boolean_t);
+extern void	dccp_wput_sock(queue_t *, mblk_t *);
+extern void	dccp_wput_fallback(queue_t *, mblk_t *);
+extern void	dccp_output(void *, mblk_t *, void *, ip_recv_attr_t *);
+extern void	dccp_output_urgent(void *, mblk_t *, void *, ip_recv_attr_t *);
+extern void	dccp_close_output(void *, mblk_t *, void *, ip_recv_attr_t *);
+extern void	dccp_shutdown_output(void *, mblk_t *, void *, ip_recv_attr_t *);
+extern void	dccp_send_data(dccp_t *, mblk_t *);
+extern void	dccp_xmit_listeners_reset(mblk_t *, ip_recv_attr_t *,
+		    ip_stack_t *, conn_t *);
+extern void	dccp_send_synack(void *, mblk_t *, void *, ip_recv_attr_t *);
+extern mblk_t	*dccp_xmit_mp(dccp_t *, mblk_t *, int32_t, int32_t *,
+		    mblk_t **, uint32_t, boolean_t, uint32_t *, boolean_t);
+/* XXX following functions should be redone */
+extern mblk_t	*dccp_generate_response(conn_t *, mblk_t *);
+extern mblk_t	*dccp_generate_request(conn_t *);
+extern mblk_t	*dccp_generate_reset(conn_t *);
+extern mblk_t	*dccp_generate_ack(conn_t *);
+extern mblk_t	*dccp_generate_sync(conn_t *);
+
+/*
+ * Functions in dccp_opt_data.c
+ */
+extern int	dccp_opt_get(conn_t *, int, int, uchar_t *);
+extern int	dccp_opt_set(conn_t *, uint_t, int, int, uint_t, uchar_t *,
+		    uint_t *, uchar_t *, void *, cred_t *);
+
+/*
+ * Functions in dccp_timers.c
+ */
+extern timeout_id_t	dccp_timeout(conn_t *, void (*)(void *), hrtime_t);
+extern clock_t	dccp_timeout_cancel(conn_t *, timeout_id_t);
+extern mblk_t	*dccp_timermp_alloc(int);
+extern void	dccp_timermp_free(dccp_t *);
+extern void	dccp_timers_stop(dccp_t *);
+extern void	dccp_keepalive_timer(void *);
+extern void	dccp_timer(void *);
+
+/*
+ * Functions in dccp_tpi.c
+ */
+extern void	dccp_do_capability_ack(dccp_t *, struct T_capability_ack *,
+		    t_uscalar_t);
+extern void	dccp_capability_req(dccp_t *, mblk_t *);
+extern void	dccp_err_ack(dccp_t *, mblk_t *, int, int);
+extern void	dccp_tpi_connect(dccp_t *, mblk_t *);
+extern int	dccp_tpi_close(queue_t *, int);
+extern int	dccp_tpi_close_accept(queue_t *);
+extern boolean_t	dccp_conn_con(dccp_t *, uchar_t *, mblk_t *, mblk_t **,
+			    ip_recv_attr_t *);
+extern int	dccp_tpi_opt_get(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
+extern int	dccp_tpi_opt_set(queue_t *, uint_t, int, int, uint_t, uchar_t *,
+		    uint_t *, uchar_t *, void *, cred_t *);
+extern void	dccp_tpi_accept(queue_t *, mblk_t *);
+
+#endif	/* _KERNEL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _INET_DCCP_IMPL_H */
--- /dev/null	2012-08-18 10:37:12.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp_ip.h	2012-08-18 10:37:12.137961758 +0000
@@ -0,0 +1,37 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner. All rights reserved.
+ */
+
+#ifndef	_INET_DCCP_DCCP_IP_H
+#define	_INET_DCCP_DCCP_IP_H
+
+#include <netinet/dccp.h>
+#include <inet/dccp_stack.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * DCCP functions for IP
+ */
+extern void	dccp_ddi_g_init(void);
+extern void	dccp_ddi_g_destroy(void);
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _INET_DCCP_DCCP_IP_H */
--- /dev/null	2012-08-18 10:37:12.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp_stack.h	2012-08-18 10:37:12.322788998 +0000
@@ -0,0 +1,73 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+#ifndef	_INET_DCCP_DCCP_STACK_H
+#define	_INET_DCCP_DCCP_STACK_H
+
+#include <sys/netstack.h>
+#include <sys/cpuvar.h>
+#include <sys/sunddi.h>
+#include <sys/sunldi.h>
+#include <inet/ip.h>
+#include <inet/ipdrop.h>
+#include <inet/dccp_stats.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * DCCP stack instances
+ */
+typedef struct dccp_stack {
+	netstack_t		*dccps_netstack;	/* Common netstack */
+
+	uint_t			dccps_bind_fanout_size;
+	struct dccp_df_s	*dccps_bind_fanout;
+
+	/*
+	 * Privileged ports.
+	 */
+#define	DCCP_NUM_EPRIV_PORTS	64
+	int			dccps_num_epriv_ports;
+	in_port_t		dccps_epriv_ports[DCCP_NUM_EPRIV_PORTS];
+	kmutex_t		dccps_epriv_port_lock;
+
+	in_port_t		dccps_min_anonpriv_port;
+	uint_t			dccps_next_port_to_try;
+
+	/* Reset rate control */
+	int64_t			dccps_last_rst_intrvl;
+	uint32_t		dccps_rst_cnt;
+
+	/* Tunables table */
+	struct mod_prop_info_s	*dccps_propinfo_tbl;
+
+	ldi_ident_t		dccps_ldi_ident;
+
+	/* MIB-II kernel statistics */
+	kstat_t			*dccps_mibkp;
+	kstat_t			*dccps_kstat;
+
+	/* CPU stats counter */
+	dccp_stats_cpu_t	**dccps_sc;
+	int			dccps_sc_cnt;
+} dccp_stack_t;
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _INET_DCCP_DCCP_STACK_H */
--- /dev/null	2012-08-18 10:37:12.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp_stats.h	2012-08-18 10:37:12.487495513 +0000
@@ -0,0 +1,61 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+#ifndef	_INET_DCCP_DCCP_STATS_H
+#define	_INET_DCCP_DCCP_STATS_H
+
+#include <sys/netstack.h>
+#include <sys/cpuvar.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* Kstats */
+typedef struct dccp_stat {
+	kstat_named_t	dccp_sock_fallback;
+} dccp_stat_t;
+
+typedef struct dccp_stat_counter_s {
+	uint64_t	dccp_no_listener;
+	uint64_t	dccp_listendrop;
+	uint64_t	dccp_wsrv_called;
+	uint64_t	dccp_sock_fallback;
+	uint64_t	dccp_rst_unsent;
+} dccp_stat_counter_t;
+
+typedef struct {
+	uint64_t		dccp_stats_cnt;
+	mib2_dccp_t		dccp_sc_mib;
+	dccp_stat_counter_t	dccp_sc_stats;
+} dccp_stats_cpu_t;
+
+/*
+ * MIB-II
+ */
+#define	DCCPS_BUMP_MIB(dccps, x) \
+	BUMP_MIB(&(dccps)->dccps_sc[CPU->cpu_seqid]->dccp_sc_mib, x)
+
+#define	DCCPS_UPDATE_MIB(dccps, x, y) \
+	UPDATE_MIB(&(dccps)->dccps_sc[CPU->cpu_seqid]->dccp_sc_mib, x, y)
+
+#define	DCCP_STAT(dccps, x)	\
+	((dccps)->dccps_sc[CPU->cpu_seqid]->dccp_sc_stats.x++)
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _INET_DCCP_DCCP_STATS_H */
--- old/usr/src/uts/common/inet/ip.h	2012-08-18 10:37:12.689029022 +0000
+++ new/usr/src/uts/common/inet/ip.h	2012-08-18 10:37:12.730507448 +0000
@@ -84,6 +84,10 @@
 
 #define	SCTP_MOD_NAME	"sctp"
 
+#define	DCCP_MOD_NAME	"dccp"
+#define	DCCP_DEV_NAME	"/dev/dccp"
+#define	DCCP6_DEV_NAME	"/dev/dccp6"
+
 #ifndef	_IPADDR_T
 #define	_IPADDR_T
 typedef uint32_t ipaddr_t;
@@ -217,6 +221,7 @@
 #define	Q_TO_UDP(q)	(Q_TO_CONN((q))->conn_udp)
 #define	Q_TO_ICMP(q)	(Q_TO_CONN((q))->conn_icmp)
 #define	Q_TO_RTS(q)	(Q_TO_CONN((q))->conn_rts)
+#define	Q_TO_DCCP(q)	(Q_TO_CONN((q))->conn_dccp)
 
 #define	CONNP_TO_WQ(connp)	((connp)->conn_wq)
 #define	CONNP_TO_RQ(connp)	((connp)->conn_rq)
@@ -3748,6 +3753,13 @@
 #define	SQTAG_TCP_SHUTDOWN_OUTPUT	43
 #define	SQTAG_TCP_IXA_CLEANUP		44
 #define	SQTAG_TCP_SEND_SYNACK		45
+#define	SQTAG_IP_DCCP_INPUT		46
+#define	SQTAG_DCCP_OUTPUT		47
+#define	SQTAG_DCCP_CONN_REQ_UNBOUND	48
+#define	SQTAG_DCCP_SEND_RESPONSE	49
+#define	SQTAG_IP_DCCP_CLOSE		50
+#define	SQTAG_DCCP_TIMER		51
+#define	SQTAG_DCCP_SHUTDOWN_OUTPUT	52
 
 extern sin_t	sin_null;	/* Zero address for quick clears */
 extern sin6_t	sin6_null;	/* Zero address for quick clears */
--- old/usr/src/uts/common/inet/ip/ip.c	2012-08-18 10:37:13.245774637 +0000
+++ new/usr/src/uts/common/inet/ip/ip.c	2012-08-18 10:37:13.581747168 +0000
@@ -111,6 +111,9 @@
 #include <ipp/ipgpc/ipgpc.h>
 
 #include <sys/pattr.h>
+#include <inet/dccp.h>
+#include <inet/dccp_impl.h>
+#include <inet/dccp_ip.h>
 #include <inet/ipclassifier.h>
 #include <inet/sctp_ip.h>
 #include <inet/sctp/sctp_impl.h>
@@ -1821,6 +1824,38 @@
 		    mp->b_wptr)
 			goto truncated;
 		break;
+	case IPPROTO_DCCP: {
+		dccpha_t	*dccpha;
+
+		/*
+		 * Verify we have at least ICMP_MIN_TP_HDR_LEN bytes of
+		 * transport header.
+		 */
+		if ((uchar_t *)ipha + hdr_length + ICMP_MIN_TP_HDR_LEN >
+		    mp->b_wptr)
+			goto truncated;
+
+		cmn_err(CE_NOTE, "icmp_inbound_verify_v4");
+
+		dccpha = (dccpha_t *)((uchar_t *)ipha + hdr_length);
+		/* XXX:DCCP */
+/*
+		connp = ipcl_dccp_lookup_reversed_ipv4(ipha, dccpha,
+		    DCCPS_LISTEN, ipst);
+		if (connp == NULL) {
+			goto discard_pkt;
+		}
+
+		if ((connp->conn_verifyicmp != NULL) &&
+		    !connp->conn_verifyicmp(connp, dccpha, icmph, NULL, ira)) {
+			CONN_DEC_REF(connp);
+			goto discard_pkt;
+		}
+
+		CONN_DEC_REF(connp);
+*/
+		break;
+	}
 	case IPPROTO_ESP:
 	case IPPROTO_AH:
 		break;
@@ -2169,6 +2204,10 @@
 		ira->ira_flags &= ~IRAF_ICMP_ERROR;
 		return;
 
+	case IPPROTO_DCCP:
+		cmn_err(CE_NOTE, "icmp_inbound_error_fanout_v4");
+		return;
+
 	case IPPROTO_ESP:
 	case IPPROTO_AH:
 		if (!ipsec_loaded(ipss)) {
@@ -4311,6 +4350,7 @@
 	icmp_ddi_g_destroy();
 	rts_ddi_g_destroy();
 	udp_ddi_g_destroy();
+	dccp_ddi_g_destroy();
 	sctp_ddi_g_destroy();
 	tcp_ddi_g_destroy();
 	ilb_ddi_g_destroy();
@@ -4547,6 +4587,7 @@
 	ipsec_policy_g_init();
 	tcp_ddi_g_init();
 	sctp_ddi_g_init();
+	dccp_ddi_g_init();
 	dce_g_init();
 
 	/*
@@ -9684,9 +9725,15 @@
 	if ((mpctl = sctp_snmp_get_mib2(q, mpctl, sctps)) == NULL) {
 		return (1);
 	}
+
 	if ((mpctl = ip_snmp_get_mib2_ip_dce(q, mpctl, ipst)) == NULL) {
 		return (1);
 	}
+
+	if ((mpctl = dccp_snmp_get(q, mpctl, legacy_req)) == NULL) {
+		return (1);
+	}
+
 	freemsg(mpctl);
 	return (1);
 }
@@ -15237,6 +15284,7 @@
 		cpu_seqid = cpu[id]->cpu_seqid;
 		netstack_next_init(&nh);
 		while ((ns = netstack_next(&nh)) != NULL) {
+			dccp_stack_cpu_add(ns->netstack_dccp, cpu_seqid);
 			tcp_stack_cpu_add(ns->netstack_tcp, cpu_seqid);
 			sctp_stack_cpu_add(ns->netstack_sctp, cpu_seqid);
 			udp_stack_cpu_add(ns->netstack_udp, cpu_seqid);
--- old/usr/src/uts/common/inet/ip/ip_if.c	2012-08-18 10:37:14.683210510 +0000
+++ new/usr/src/uts/common/inet/ip/ip_if.c	2012-08-18 10:37:14.997967749 +0000
@@ -104,6 +104,7 @@
 
 #include <inet/rawip_impl.h> /* needed for icmp_stack_t */
 #include <inet/udp_impl.h> /* needed for udp_stack_t */
+#include <inet/dccp_stack.h> /* needed for dccp_stack_t */
 
 /* The character which tells where the ill_name ends */
 #define	IPIF_SEPARATOR_CHAR	':'
@@ -8857,6 +8858,7 @@
 	icmp_stack_t	*is;
 	tcp_stack_t	*tcps;
 	sctp_stack_t	*sctps;
+	dccp_stack_t	*dccps;
 	udp_stack_t	*us;
 	netstack_t	*stack;
 	void		*cbarg;
@@ -8902,6 +8904,10 @@
 		ptbl = sctps->sctps_propinfo_tbl;
 		cbarg = sctps;
 		break;
+	case MOD_PROTO_DCCP:
+		dccps = stack->netstack_dccp;
+		ptbl = dccps->dccps_propinfo_tbl;
+		cbarg = dccps;
 	default:
 		miocnak(q, mp, 0, EINVAL);
 		return;
--- old/usr/src/uts/common/inet/ip/ip_input.c	2012-08-18 10:37:16.127929169 +0000
+++ new/usr/src/uts/common/inet/ip/ip_input.c	2012-08-18 10:37:16.138656527 +0000
@@ -116,6 +116,7 @@
 #include <inet/sctp_ip.h>
 #include <inet/sctp/sctp_impl.h>
 #include <inet/udp_impl.h>
+#include <inet/dccp_impl.h>
 #include <sys/sunddi.h>
 
 #include <sys/tsol/label.h>
@@ -2389,6 +2390,9 @@
 	case IPPROTO_ICMP:
 		min_ulp_header_length = ICMPH_SIZE;
 		break;
+	case IPPROTO_DCCP:
+		min_ulp_header_length = DCCP_MIN_HEADER_LENGTH;
+		break;
 	default:
 		min_ulp_header_length = 0;
 		break;
@@ -2714,6 +2718,69 @@
 		ira->ira_ill = ill;
 		ira->ira_rill = rill;
 		return;
+	case IPPROTO_DCCP:
+		/* For DCCP, discard broadcast and multicast packets */
+		if (iraflags & IRAF_MULTIBROADCAST) {
+			goto discard;
+		}
+
+		/* First mblk contains IP+DCCP headers per above check */
+		ASSERT(len >= ip_hdr_length + DCCP_MIN_HEADER_LENGTH);
+
+		/* Squeue hint */
+		if (ira->ira_sqp == NULL) {
+			ira->ira_sqp = ip_squeue_get(ira->ira_ring);
+		}
+
+		connp = ipcl_classify_v4(mp, IPPROTO_DCCP, ip_hdr_length,
+		    ira, ipst);
+		if (connp == NULL) {
+			cmn_err(CE_NOTE, "ip_input.c: ip_fanout_v4 connp not found");
+			/* Send the reset packet */
+			BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInDelivers);
+			dccp_xmit_listeners_reset(mp, ira, ipst, NULL);
+			return;
+		}
+
+		if (connp->conn_incoming_ifindex != 0 &&
+		    connp->conn_incoming_ifindex != ira->ira_ruifindex) {
+			cmn_err(CE_NOTE, "ip_input.c: ip_fanout_v4 ifindex problem");
+			/* Send the reset packet */
+			BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInDelivers);
+			dccp_xmit_listeners_reset(mp, ira, ipst, NULL);
+			return;
+		}
+
+		if (CONN_INBOUND_POLICY_PRESENT(connp, ipss) ||
+		    (iraflags & IRAF_IPSEC_SECURE)) {
+			mp = ipsec_check_inbound_policy(mp, connp,
+			    ipha, NULL, ira);
+			if (mp == NULL) {
+				BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
+				/* Note that mp is NULL */
+				ip_drop_input("ipIfStatsInDiscards", mp, ill);
+				CONN_DEC_REF(connp);
+				return;
+			}
+		}
+
+		/* Found a client; up it goes */
+		BUMP_MIB(ill->ill_ip_mib, ipIfStatsHCInDelivers);
+		ira->ira_ill = ira->ira_rill = NULL;
+
+		/* XXX SOCK_RAW for DCCP? */
+
+		if (iraflags & IRAF_TARGET_SQP) {
+			cmn_err(CE_NOTE, "IRAF_TARGET_SQP");
+		} else {
+			SQUEUE_ENTER_ONE(connp->conn_sqp, mp, connp->conn_recv,
+			    connp, ira, ip_squeue_flag, SQTAG_IP_DCCP_INPUT);
+		}
+
+		ira->ira_ill = ill;
+		ira->ira_rill = rill;
+		return;
+
 	default:
 		break;
 	}
--- old/usr/src/uts/common/inet/ip/ip_output.c	2012-08-18 10:37:16.594572839 +0000
+++ new/usr/src/uts/common/inet/ip/ip_output.c	2012-08-18 10:37:16.626507390 +0000
@@ -1648,6 +1648,9 @@
 #endif
 			sctph->sh_chksum = sctp_cksum(mp, ip_hdr_length);
 		goto ip_hdr_cksum;
+	} else if (protocol == IPPROTO_DCCP) {
+		cksump = IPH_DCCPH_CHECKSUMP(ipha, ip_hdr_length);
+		cksum = IP_DCCP_CSUM_COMP;
 	} else {
 		goto ip_hdr_cksum;
 	}
@@ -1737,6 +1740,9 @@
 #endif
 			sctph->sh_chksum = sctp_cksum(mp, ip_hdr_length);
 		goto ip_hdr_cksum;
+	} else if (protocol == IPPROTO_DCCP) {
+		cksump = IPH_DCCPH_CHECKSUMP(ipha, ip_hdr_length);
+		cksum = IP_DCCP_CSUM_COMP;
 	} else {
 	ip_hdr_cksum:
 		/* Calculate IPv4 header checksum */
--- old/usr/src/uts/common/inet/ip/ipclassifier.c	2012-08-18 10:37:17.022739851 +0000
+++ new/usr/src/uts/common/inet/ip/ipclassifier.c	2012-08-18 10:37:17.059476558 +0000
@@ -67,6 +67,8 @@
  *	ipcl_udp_fanout:	contains all UDP connections
  *	ipcl_iptun_fanout:	contains all IP tunnel connections
  *	ipcl_globalhash_fanout:	contains all connections
+ *`	ipcl_dccp_conn_fanout:	contains all DCCP connections in CONNECTED state
+ *	ipcl_dccp_bind_fanout:	contains all DCCP connections in BOUND state
  *
  * The ipcl_globalhash_fanout is used for any walkers (like snmp and Clustering)
  * which need to view all existing connections.
@@ -223,6 +225,7 @@
  *		IPCL_UDPCONN	indicates a UDP conn_t.
  *		IPCL_RAWIPCONN	indicates a RAWIP/ICMP conn_t.
  *		IPCL_RTSCONN	indicates a RTS conn_t.
+ *		IPCL_DCCPCONN	indicates a DCCP conn_t.
  *		IPCL_IPCCONN	indicates all other connections.
  *
  * void ipcl_conn_destroy(connp)
@@ -257,6 +260,7 @@
 #include <inet/ip_ndp.h>
 #include <inet/ip_impl.h>
 #include <inet/udp_impl.h>
+#include <inet/dccp_impl.h>
 #include <inet/sctp_ip.h>
 #include <inet/sctp/sctp_impl.h>
 #include <inet/rawip_impl.h>
@@ -284,6 +288,10 @@
 uint_t ipcl_bind_fanout_size = 512;
 uint_t ipcl_udp_fanout_size = 16384;
 
+/* Fanout table sizes for dccp */
+uint_t ipcl_dccp_conn_fanout_size = 512;
+uint_t ipcl_dccp_bind_fanout_size = 512;
+
 /* Raw socket fanout size.  Must be a power of 2. */
 uint_t ipcl_raw_fanout_size = 256;
 
@@ -319,6 +327,7 @@
 struct kmem_cache  *udp_conn_cache;
 struct kmem_cache  *rawip_conn_cache;
 struct kmem_cache  *rts_conn_cache;
+struct kmem_cache  *dccp_conn_cache;
 
 extern void	tcp_timermp_free(tcp_t *);
 extern mblk_t	*tcp_timermp_alloc(int);
@@ -338,6 +347,9 @@
 static int	rts_conn_constructor(void *, void *, int);
 static void	rts_conn_destructor(void *, void *);
 
+static int	dccp_conn_constructor(void *, void *, int);
+static void	dccp_conn_destructor(void *, void *);
+
 /*
  * Global (for all stack instances) init routine
  */
@@ -368,6 +380,12 @@
 	    sizeof (itc_t) + sizeof (rts_t), CACHE_ALIGN_SIZE,
 	    rts_conn_constructor, rts_conn_destructor,
 	    NULL, NULL, NULL, 0);
+
+	/* XXX:DCCP reclaim */
+	dccp_conn_cache = kmem_cache_create("dccp_conn_cache",
+	    sizeof (itc_t) + sizeof (dccp_t), CACHE_ALIGN_SIZE,
+	    dccp_conn_constructor, dccp_conn_destructor,
+	    NULL, NULL, NULL, 0);
 }
 
 /*
@@ -410,6 +428,8 @@
 
 	/* Take values from /etc/system */
 	ipst->ips_ipcl_bind_fanout_size = ipcl_bind_fanout_size;
+	ipst->ips_ipcl_dccp_conn_fanout_size = ipcl_dccp_conn_fanout_size;
+	ipst->ips_ipcl_dccp_bind_fanout_size = ipcl_dccp_bind_fanout_size;
 	ipst->ips_ipcl_udp_fanout_size = ipcl_udp_fanout_size;
 	ipst->ips_ipcl_raw_fanout_size = ipcl_raw_fanout_size;
 	ipst->ips_ipcl_iptun_fanout_size = ipcl_iptun_fanout_size;
@@ -477,6 +497,20 @@
 		mutex_init(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock,
 		    NULL, MUTEX_DEFAULT, NULL);
 	}
+
+	ipst->ips_ipcl_dccp_conn_fanout = kmem_zalloc(
+	    ipst->ips_ipcl_dccp_conn_fanout_size * sizeof (connf_t), KM_SLEEP);
+	for (i = 0; i < ipst->ips_ipcl_dccp_conn_fanout_size; i++) {
+		mutex_init(&ipst->ips_ipcl_dccp_conn_fanout[i].connf_lock, NULL,
+		    MUTEX_DEFAULT, NULL);
+	}
+
+	ipst->ips_ipcl_dccp_bind_fanout = kmem_zalloc(
+	    ipst->ips_ipcl_dccp_bind_fanout_size * sizeof (connf_t), KM_SLEEP);
+	for (i = 0; i < ipst->ips_ipcl_dccp_bind_fanout_size; i++) {
+		mutex_init(&ipst->ips_ipcl_dccp_bind_fanout[i].connf_lock, NULL,
+		    MUTEX_DEFAULT, NULL);
+	}
 }
 
 void
@@ -487,6 +521,7 @@
 	kmem_cache_destroy(udp_conn_cache);
 	kmem_cache_destroy(rawip_conn_cache);
 	kmem_cache_destroy(rts_conn_cache);
+	kmem_cache_destroy(dccp_conn_cache);
 }
 
 /*
@@ -562,6 +597,22 @@
 	    sizeof (connf_t) * CONN_G_HASH_SIZE);
 	ipst->ips_ipcl_globalhash_fanout = NULL;
 
+	for (i = 0; i < ipst->ips_ipcl_dccp_conn_fanout_size; i++) {
+		ASSERT(ipst->ips_ipcl_dccp_conn_fanout[i].connf_head == NULL);
+		mutex_destroy(&ipst->ips_ipcl_dccp_conn_fanout[i].connf_lock);
+	}
+	kmem_free(ipst->ips_ipcl_dccp_conn_fanout,
+	    ipst->ips_ipcl_dccp_conn_fanout_size * sizeof (connf_t));
+	ipst->ips_ipcl_dccp_conn_fanout = NULL;
+
+	for (i = 0; i < ipst->ips_ipcl_dccp_bind_fanout_size; i++) {
+		ASSERT(ipst->ips_ipcl_dccp_bind_fanout[i].connf_head == NULL);
+		mutex_destroy(&ipst->ips_ipcl_dccp_bind_fanout[i].connf_lock);
+	}
+	kmem_free(ipst->ips_ipcl_dccp_bind_fanout,
+	    ipst->ips_ipcl_dccp_bind_fanout_size * sizeof (connf_t));
+	ipst->ips_ipcl_dccp_bind_fanout = NULL;
+
 	ASSERT(ipst->ips_rts_clients->connf_head == NULL);
 	mutex_destroy(&ipst->ips_rts_clients->connf_lock);
 	kmem_free(ipst->ips_rts_clients, sizeof (connf_t));
@@ -610,6 +661,10 @@
 		conn_cache = ip_conn_cache;
 		break;
 
+	case IPCL_DCCPCONN:
+		conn_cache = dccp_conn_cache;
+		break;
+
 	default:
 		connp = NULL;
 		ASSERT(0);
@@ -720,6 +775,33 @@
 		return;
 	}
 
+	if (connp->conn_flags & IPCL_DCCPCONN) {
+		dccp_t	*dccp = connp->conn_dccp;
+
+		cmn_err(CE_NOTE, "ipclassifier: conn_flags DCCP cache_free");
+
+		dccp_free(dccp);
+		mp = dccp->dccp_timercache;
+
+		dccp->dccp_dccps = NULL;
+
+		ipcl_conn_cleanup(connp);
+		connp->conn_flags = IPCL_DCCPCONN;
+		if (ns != NULL) {
+			ASSERT(dccp->dccps == NULL);
+			connp->conn_netstack = NULL;
+			connp->conn_ixa->ixa_ipst = NULL;
+			netstack_rele(ns);
+		}
+
+		bzero(dccp, sizeof (dccp_t));
+
+		dccp->dccp_timercache = mp;
+		dccp->dccp_connp = connp;
+		kmem_cache_free(dccp_conn_cache, connp);
+		return;
+	}
+
 	ipcl_conn_cleanup(connp);
 	if (ns != NULL) {
 		connp->conn_netstack = NULL;
@@ -1236,8 +1318,21 @@
 	case IPPROTO_SCTP:
 		ret = ipcl_sctp_hash_insert(connp, lport);
 		break;
+
+	case IPPROTO_DCCP:
+		cmn_err(CE_NOTE, "ipclassifier.c: ipcl_bind_insert_v4");
+		ASSERT(connp->conn_zoneid != ALL_ZONES);
+		connfp = &ipst->ips_ipcl_dccp_bind_fanout[
+		    IPCL_DCCP_BIND_HASH(lport, ipst)];
+		if (connp->conn_laddr_v4 != INADDR_ANY) {
+			IPCL_HASH_INSERT_BOUND(connfp, connp);
+		} else {
+			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
+		}
+		break;
 	}
 
+
 	return (ret);
 }
 
@@ -1309,6 +1404,18 @@
 	case IPPROTO_SCTP:
 		ret = ipcl_sctp_hash_insert(connp, lport);
 		break;
+
+	case IPPROTO_DCCP:
+		cmn_err(CE_NOTE, "ipclassifier.c: ipcl_bind_insert_v6");
+		ASSERT(connp->conn_zoneid != ALL_ZONES);
+		connfp = &ipst->ips_ipcl_dccp_bind_fanout[
+		    IPCL_DCCP_BIND_HASH(lport, ipst)];
+		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
+			IPCL_HASH_INSERT_BOUND(connfp, connp);
+		} else {
+			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
+		}
+		break;
 	}
 
 	return (ret);
@@ -1393,6 +1500,32 @@
 		ret = ipcl_sctp_hash_insert(connp, lport);
 		break;
 
+	case IPPROTO_DCCP:
+		cmn_err(CE_NOTE, "ipclassifier.c: ipcl_conn_insert_v4");
+		connfp = &ipst->ips_ipcl_dccp_conn_fanout[IPCL_DCCP_CONN_HASH(
+		    connp->conn_faddr_v4, connp->conn_ports, ipst)];
+		mutex_enter(&connfp->connf_lock);
+		for (tconnp = connfp->connf_head; tconnp != NULL;
+		    tconnp = tconnp->conn_next) {
+			if (IPCL_CONN_MATCH(tconnp, connp->conn_proto,
+			    connp->conn_faddr_v4, connp->conn_laddr_v4,
+			    connp->conn_ports) &&
+			    IPCL_ZONE_MATCH(tconnp, connp->conn_zoneid)) {
+				/* Already have a conn. bail out */
+				mutex_exit(&connfp->connf_lock);
+				return (EADDRINUSE);
+			}
+		}
+
+		/* XXX:DCCP XTI/TLI application? */
+
+		ASSERT(connp->conn_recv != NULL);
+		ASSERT(connp->conn_recvicmp != NULL);
+
+		IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
+		mutex_exit(&connfp->connf_lock);
+		break;
+
 	default:
 		/*
 		 * Check for conflicts among MAC exempt bindings.  For
@@ -1488,6 +1621,32 @@
 		ret = ipcl_sctp_hash_insert(connp, lport);
 		break;
 
+	case IPPROTO_DCCP:
+		cmn_err(CE_NOTE, "ipclassifier.c: ipcl_conn_insert_v6");
+		connfp = &ipst->ips_ipcl_dccp_conn_fanout[
+		    IPCL_DCCP_CONN_HASH_V6(connp->conn_faddr_v6,
+		    connp->conn_ports, ipst)];
+		mutex_enter(&connfp->connf_lock);
+		for (tconnp = connfp->connf_head; tconnp != NULL;
+		    tconnp = tconnp->conn_next) {
+			/* NOTE: need to match zoneid. Bug in onnv-gate */
+			if (IPCL_CONN_MATCH_V6(tconnp, connp->conn_proto,
+			    connp->conn_faddr_v6, connp->conn_laddr_v6,
+			    connp->conn_ports) &&
+			    (tconnp->conn_bound_if == 0 ||
+			    tconnp->conn_bound_if == ifindex) &&
+			    IPCL_ZONE_MATCH(tconnp, connp->conn_zoneid)) {
+				/* Already have a conn. bail out */
+				mutex_exit(&connfp->connf_lock);
+				return (EADDRINUSE);
+			}
+		}
+
+		/* XXX:DCCP XTI/TLI? */
+		IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
+		mutex_exit(&connfp->connf_lock);
+		break;
+
 	default:
 		if (is_system_labeled() &&
 		    check_exempt_conflict_v6(connp, ipst))
@@ -1655,6 +1814,67 @@
 
 		break;
 
+	case IPPROTO_DCCP:
+		ports = *(uint32_t *)up;
+
+		/*
+		 * Search for fully-bound connection.
+		 */
+		connfp = &ipst->ips_ipcl_dccp_conn_fanout[IPCL_DCCP_CONN_HASH(
+		    ipha->ipha_src, ports, ipst)];
+		mutex_enter(&connfp->connf_lock);
+		for (connp = connfp->connf_head; connp != NULL;
+		    connp = connp->conn_next) {
+			/* XXX:DCCP */
+			if (IPCL_CONN_MATCH(connp, protocol,
+			    ipha->ipha_src, ipha->ipha_dst, ports)) {
+				/* XXX */
+				cmn_err(CE_NOTE, "ipclassifier.c: fully bound connection found");
+				break;
+			}
+		}
+
+		if (connp != NULL) {
+			/*
+			 * We have a fully-bound DCCP connection.
+			 */
+			CONN_INC_REF(connp);
+			mutex_exit(&connfp->connf_lock);
+			return (connp);
+		}
+
+		mutex_exit(&connfp->connf_lock);
+		lport = up[1];
+
+		/*
+		 * Fully-bound connection was not found, search for listener.
+		 */
+		bind_connfp = &ipst->ips_ipcl_dccp_bind_fanout[
+		    IPCL_DCCP_BIND_HASH(lport, ipst)];
+		mutex_enter(&bind_connfp->connf_lock);
+		for (connp = bind_connfp->connf_head; connp != NULL;
+		    connp = connp->conn_next) {
+			if (IPCL_BIND_MATCH(connp, protocol, ipha->ipha_dst,
+			    lport) &&
+			    (connp->conn_zoneid == zoneid ||
+			    connp->conn_allzones ||
+			    ((connp->conn_mac_mode != CONN_MAC_DEFAULT) &&
+			    (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE) &&
+			    (ira->ira_flags & IRAF_TX_SHARED_ADDR))))
+				break;
+		}
+
+		if (connp != NULL) {
+			cmn_err(CE_NOTE, "ipclassifier.c: half-bound bind listener");
+			/* Have a listener at least */
+			CONN_INC_REF(connp);
+			mutex_exit(&bind_connfp->connf_lock);
+			return (connp);
+		}
+
+		mutex_exit(&bind_connfp->connf_lock);
+		break;
+
 	case IPPROTO_ENCAP:
 	case IPPROTO_IPV6:
 		return (ipcl_iptun_classify_v4(&ipha->ipha_src,
@@ -2175,6 +2395,70 @@
 	}
 }
 
+/* ARGSUSED */
+static int
+dccp_conn_constructor(void *buf, void *cdrarg, int kmflags)
+{
+	itc_t	*itc = (itc_t *)buf;
+	conn_t	*connp = &itc->itc_conn;
+	dccp_t	*dccp = (dccp_t *)&itc[1];
+
+	bzero(connp, sizeof (conn_t));
+	bzero(dccp, sizeof (dccp_t));
+
+	mutex_init(&connp->conn_lock, NULL, MUTEX_DEFAULT, NULL);
+	cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL);
+	rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL);
+
+	dccp->dccp_timercache = dccp_timermp_alloc(kmflags);
+	if (dccp->dccp_timercache == NULL) {
+		return (ENOMEM);
+	}
+
+	connp->conn_dccp = dccp;
+	connp->conn_flags = IPCL_DCCPCONN;
+	connp->conn_proto = IPPROTO_DCCP;
+	dccp->dccp_connp = connp;
+
+	connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags);
+	if (connp->conn_ixa == NULL) {
+		return (NULL);
+	}
+
+	connp->conn_ixa->ixa_refcnt = 1;
+	connp->conn_ixa->ixa_protocol = connp->conn_proto;
+	connp->conn_ixa->ixa_xmit_hint = CONN_TO_XMIT_HINT(connp);
+
+	return (0);
+}
+
+/* ARGSUSED */
+static void
+dccp_conn_destructor(void *buf, void *cdrarg)
+{
+	itc_t	*itc = (itc_t *)buf;
+	conn_t	*connp = &itc->itc_conn;
+	dccp_t	*dccp = (dccp_t *)&itc[1];
+
+	ASSERT(connp->conn_flags & IPCL_DCCPCONN);
+	ASSERT(dccp->dccp_connp == connp);
+	ASSERT(connp->conn_dccp == dccp);
+
+	dccp_timermp_free(dccp);
+
+	mutex_destroy(&connp->conn_lock);
+	cv_destroy(&connp->conn_cv);
+	rw_destroy(&connp->conn_ilg_lock);
+
+	if (connp->conn_ixa != NULL) {
+		ASSERT(connp->conn_ixa->ixa_refcnt == 1);
+		ASSERT(connp->conn_ixa->ixa_ire == NULL);
+		ASSERT(connp->conn_ixa->ixa_nce == NULL);
+
+		ixa_refrele(connp->conn_ixa);
+	}
+}
+
 /*
  * Called as part of ipcl_conn_destroy to assert and clear any pointers
  * in the conn_t.
@@ -2554,6 +2838,82 @@
 }
 
 /*
+ * Same as ipcl_tcp_lookup_reversed_ipv4.
+ */
+conn_t *
+ipcl_dccp_lookup_reversed_ipv4(ipha_t *ipha, dccpha_t *dccpha, int min_state,
+    ip_stack_t *ipst)
+{
+	conn_t		*tconnp;
+	connf_t		*connfp;
+	uint16_t	*pports;
+	uint32_t	ports;
+
+	pports = (uint16_t *)&ports;
+	pports[0] = dccpha->dha_fport;
+	pports[1] = dccpha->dha_lport;
+
+	connfp = &ipst->ips_ipcl_dccp_conn_fanout[IPCL_DCCP_CONN_HASH(
+	    ipha->ipha_dst, ports, ipst)];
+
+	mutex_enter(&connfp->connf_lock);
+	for (tconnp = connfp->connf_head; tconnp != NULL;
+	    tconnp = tconnp->conn_next) {
+		if (IPCL_CONN_MATCH(tconnp, IPPROTO_DCCP,
+		    ipha->ipha_dst, ipha->ipha_src, ports) &&
+		    tconnp->conn_dccp->dccp_state >= min_state) {
+			CONN_INC_REF(tconnp);
+			mutex_exit(&connfp->connf_lock);
+			return (tconnp);
+		}
+	}
+	mutex_exit(&connfp->connf_lock);
+
+	return (NULL);
+}
+
+/*
+ * Same as ipcl_tcp_lookup_reversed_ipv6.
+ */
+conn_t *
+ipcl_dccp_lookup_reversed_ipv6(ip6_t *ip6h, dccpha_t *dccpha, int min_state,
+    uint_t ifindex, ip_stack_t *ipst)
+{
+	conn_t		*tconnp;
+	tcp_t		*tcp;
+	connf_t		*connfp;
+	uint32_t	 ports;
+	uint16_t	 *pports;
+
+	pports = (uint16_t *)&ports;
+	pports[0] = dccpha->dha_fport;
+	pports[1] = dccpha->dha_lport;
+/*
+	connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH_V6(ip6h->ip6_dst,
+	    ports, ipst)];
+
+	mutex_enter(&connfp->connf_lock);
+	for (tconnp = connfp->connf_head; tconnp != NULL;
+	    tconnp = tconnp->conn_next) {
+
+		tcp = tconnp->conn_tcp;
+		if (IPCL_CONN_MATCH_V6(tconnp, IPPROTO_TCP,
+		    ip6h->ip6_dst, ip6h->ip6_src, ports) &&
+		    tcp->tcp_state >= min_state &&
+		    (tconnp->conn_bound_if == 0 ||
+		    tconnp->conn_bound_if == ifindex)) {
+
+			CONN_INC_REF(tconnp);
+			mutex_exit(&connfp->connf_lock);
+			return (tconnp);
+		}
+	}
+	mutex_exit(&connfp->connf_lock);
+*/
+	return (NULL);
+}
+
+/*
  * Finds a TCP/IPv4 listening connection; called by tcp_disconnect to locate
  * a listener when changing state.
  */
--- old/usr/src/uts/common/inet/ip_impl.h	2012-08-18 10:37:17.551908274 +0000
+++ new/usr/src/uts/common/inet/ip_impl.h	2012-08-18 10:37:17.581212918 +0000
@@ -52,11 +52,13 @@
 #define	IP_TCP_CSUM_COMP	IPPROTO_TCP
 #define	IP_UDP_CSUM_COMP	IPPROTO_UDP
 #define	IP_ICMPV6_CSUM_COMP	IPPROTO_ICMPV6
+#define	IP_DCCP_CSUM_COMP	IPPROTO_DCCP
 #else
 #define	IP_HDR_CSUM_TTL_ADJUST	1
 #define	IP_TCP_CSUM_COMP	(IPPROTO_TCP << 8)
 #define	IP_UDP_CSUM_COMP	(IPPROTO_UDP << 8)
 #define	IP_ICMPV6_CSUM_COMP	(IPPROTO_ICMPV6 << 8)
+#define	IP_DCCP_CSUM_COMP	(IPPROTO_DCCP << 8)
 #endif
 
 #define	TCP_CHECKSUM_OFFSET	16
@@ -68,6 +70,9 @@
 #define	ICMPV6_CHECKSUM_OFFSET	2
 #define	ICMPV6_CHECKSUM_SIZE	2
 
+#define	DCCP_CHECKSUM_OFFSET	6
+#define	DCCP_CHECKSUM_SIZE	2
+
 #define	IPH_TCPH_CHECKSUMP(ipha, hlen)	\
 	((uint16_t *)(((uchar_t *)(ipha)) + ((hlen) + TCP_CHECKSUM_OFFSET)))
 
@@ -77,6 +82,9 @@
 #define	IPH_ICMPV6_CHECKSUMP(ipha, hlen)	\
 	((uint16_t *)(((uchar_t *)(ipha)) + ((hlen) + ICMPV6_CHECKSUM_OFFSET)))
 
+#define	IPH_DCCPH_CHECKSUMP(ipha, hlen)	\
+	((uint16_t *)(((uchar_t *)(ipha)) + ((hlen) + DCCP_CHECKSUM_OFFSET)))
+
 #define	ILL_HCKSUM_CAPABLE(ill)		\
 	(((ill)->ill_capabilities & ILL_CAPAB_HCKSUM) != 0)
 
--- old/usr/src/uts/common/inet/ip_stack.h	2012-08-18 10:37:17.903956817 +0000
+++ new/usr/src/uts/common/inet/ip_stack.h	2012-08-18 10:37:17.927105196 +0000
@@ -195,11 +195,15 @@
 	struct connf_s	*ips_ipcl_udp_fanout;
 	struct connf_s	*ips_ipcl_raw_fanout;		/* RAW SCTP sockets */
 	struct connf_s	*ips_ipcl_iptun_fanout;
+	struct connf_s	*ips_ipcl_dccp_conn_fanout;
+	struct connf_s	*ips_ipcl_dccp_bind_fanout;
 	uint_t		ips_ipcl_conn_fanout_size;
 	uint_t		ips_ipcl_bind_fanout_size;
 	uint_t		ips_ipcl_udp_fanout_size;
 	uint_t		ips_ipcl_raw_fanout_size;
 	uint_t		ips_ipcl_iptun_fanout_size;
+	uint_t		ips_ipcl_dccp_conn_fanout_size;
+	uint_t		ips_ipcl_dccp_bind_fanout_size;
 	struct connf_s	*ips_ipcl_globalhash_fanout;
 	int		ips_conn_g_index;
 
--- old/usr/src/uts/common/inet/ipclassifier.h	2012-08-18 10:37:18.307940574 +0000
+++ new/usr/src/uts/common/inet/ipclassifier.h	2012-08-18 10:37:18.342763040 +0000
@@ -34,6 +34,7 @@
 #include <inet/ip.h>
 #include <inet/mi.h>
 #include <inet/tcp.h>
+#include <inet/dccp.h>
 #include <inet/ip6.h>
 #include <netinet/in.h>		/* for IPPROTO_* constants */
 #include <sys/sdt.h>
@@ -84,7 +85,7 @@
 #define	IPCL_UDPCONN		0x00000008	/* From udp_conn_cache */
 #define	IPCL_RAWIPCONN		0x00000010	/* From rawip_conn_cache */
 #define	IPCL_RTSCONN		0x00000020	/* From rts_conn_cache */
-/* Unused			0x00000040 */
+#define	IPCL_DCCPCONN		0x00000040	/* From dccp_conn_cache */
 #define	IPCL_IPTUN		0x00000080	/* iptun module above us */
 
 #define	IPCL_NONSTR		0x00001000	/* A non-STREAMS socket */
@@ -121,6 +122,9 @@
 #define	IPCL_IS_IPTUN(connp)						\
 	((connp)->conn_flags & IPCL_IPTUN)
 
+#define	IPCL_IS_DCCP(connp)						\
+	((connp)->conn_flags & IPCL_DCCPCONN)
+
 #define	IPCL_IS_NONSTR(connp)	((connp)->conn_flags & IPCL_NONSTR)
 
 typedef struct connf_s connf_t;
@@ -237,6 +241,7 @@
 		struct rts_s	*cp_rts;	/* Pointer to rts struct */
 		struct iptun_s	*cp_iptun;	/* Pointer to iptun_t */
 		struct sctp_s	*cp_sctp;	/* For IPCL_SCTPCONN */
+		struct dccp_s	*cp_dccp;	/* Pointer to dccp struct */
 		void		*cp_priv;
 	} conn_proto_priv;
 #define	conn_tcp	conn_proto_priv.cp_tcp
@@ -245,6 +250,7 @@
 #define	conn_rts	conn_proto_priv.cp_rts
 #define	conn_iptun	conn_proto_priv.cp_iptun
 #define	conn_sctp	conn_proto_priv.cp_sctp
+#define	conn_dccp	conn_proto_priv.cp_dccp
 #define	conn_priv	conn_proto_priv.cp_priv
 
 	kcondvar_t	conn_cv;
@@ -651,6 +657,18 @@
 #define	IPCL_UDP_HASH(lport, ipst)	\
 	IPCL_PORT_HASH(lport, (ipst)->ips_ipcl_udp_fanout_size)
 
+#define	IPCL_DCCP_CONN_HASH(src, ports, ipst)				\
+	((unsigned)(ntohl((src)) ^ ((ports) >> 24) ^ ((ports) >> 16) ^	\
+	((ports) >> 8) ^ (ports)) % (ipst)->ips_ipcl_dccp_conn_fanout_size)
+
+#define	IPCL_DCCP_CONN_HASH_V6(src, ports, ipst)			\
+	IPCL_DCCP_CONN_HASH(V4_PART_OF_V6((src)), (ports), (ipst))
+
+#define	IPCL_DCCP_BIND_HASH(lport, ipst)				\
+	((unsigned)(((lport) >> 8) ^ (lport)) %				\
+	    (ipst)->ips_ipcl_dccp_bind_fanout_size)
+
+
 #define	CONN_G_HASH_SIZE	1024
 
 /* Raw socket hash function. */
@@ -710,6 +728,11 @@
 conn_t	*ipcl_tcp_lookup_reversed_ipv4(ipha_t *, tcpha_t *, int, ip_stack_t *);
 conn_t	*ipcl_tcp_lookup_reversed_ipv6(ip6_t *, tcpha_t *, int, uint_t,
 	    ip_stack_t *);
+/*
+conn_t	*ipcl_dccp_lookup_reversed_ipv4(ipha_t *, dccpha_t *, int, ip_stack_t *);
+conn_t	*ipcl_dccp_lookup_reversed_ipv6(ip6_t *, dccpha_t *, int, uint_t,
+	    ip_stack_t *);
+*/
 conn_t	*ipcl_lookup_listener_v4(uint16_t, ipaddr_t, zoneid_t, ip_stack_t *);
 conn_t	*ipcl_lookup_listener_v6(uint16_t, in6_addr_t *, uint_t, zoneid_t,
 	    ip_stack_t *);
--- old/usr/src/uts/common/inet/kstatcom.h	2012-08-18 10:37:18.629848192 +0000
+++ new/usr/src/uts/common/inet/kstatcom.h	2012-08-18 10:37:18.653441511 +0000
@@ -467,6 +467,12 @@
 	kstat_named_t outErrors;
 } rawip_named_kstat_t;
 
+typedef struct dccp_named_kstat {
+	kstat_named_t activeOpens;
+	kstat_named_t passiveOpens;
+	kstat_named_t inSegs;
+	kstat_named_t outSegs;
+} dccp_named_kstat_t;
 
 #define	NUM_OF_FIELDS(S)	(sizeof (S) / sizeof (kstat_named_t))
 
--- old/usr/src/uts/common/inet/mib2.h	2012-08-18 10:37:18.893817909 +0000
+++ new/usr/src/uts/common/inet/mib2.h	2012-08-18 10:37:18.919544870 +0000
@@ -96,12 +96,14 @@
 #define	MIB2_TCP6		(IPPROTO_MAX+14)
 #define	MIB2_UDP6		(IPPROTO_MAX+15)
 #define	MIB2_SCTP		(IPPROTO_MAX+16)
+#define	MIB2_DCCP		(IPPROTO_MAX+17)
+#define	MIB2_DCCP6		(IPPROTO_MAX+18)
 
 /*
  * Define range of levels for use with MIB2_*
  */
 #define	MIB2_RANGE_START	(IPPROTO_MAX+1)
-#define	MIB2_RANGE_END		(IPPROTO_MAX+16)
+#define	MIB2_RANGE_END		(IPPROTO_MAX+18)
 
 
 #define	EXPER			1024	/* experimental - not part of mib */
@@ -1786,6 +1788,134 @@
 #pragma pack()
 #endif
 
+/*
+ * the DCCP group
+ */
+#define	MIB2_DCCP_CONN		18
+#define	MIB2_DCCP6_CONN		19
+
+#define	MIB2_DCCP_closed	1
+#define	MIB2_DCCP_listen	2
+
+/* Pack data to make struct size the same for 32- and 64-bits */
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack(4)
+#endif
+
+typedef struct mib2_dccp {
+
+		/* # of direct transitions CLOSED -> ACK-SENT	{ dccp 5 } */
+	Counter	dccpActiveOpens;
+		/* # of direct transitions LISTEN -> ACK-RCVD	{ dccp 6 } */
+	Counter	dccpPassiveOpens;
+		/* # of direct SIN-SENT/RCVD -> CLOSED/LISTEN	{ dccp 7 } */
+	Counter	dccpAttemptFails;
+		/* # of direct ESTABLISHED/CLOSE-WAIT -> CLOSED	{ dccp 8 } */
+	Counter	dccpEstabResets;
+		/* # of connections ESTABLISHED or CLOSE-WAIT	{ dccp 9 } */
+	Gauge	dccpCurrEstab;
+		/* total # of segments recv'd			{ dccp 10 } */
+	Counter	dccpInSegs;
+		/* total # of segments sent			{ dccp 11 } */
+	Counter	dccpOutSegs;
+		/* total # of segments retransmitted		{ dccp 12 } */
+	Counter	dccpRetransSegs;
+
+	Counter dccpTimRetrans;
+	/* total # of retransmit timeouts dropping the connection */
+	Counter dccpTimRetransDrop;
+	/* total # of keepalive timeouts */
+	Counter dccpTimKeepalive;
+	/* total # of keepalive timeouts sending a probe */
+	Counter dccpTimKeepaliveProbe;
+	/* total # of keepalive timeouts dropping the connection */
+	Counter dccpTimKeepaliveDrop;
+
+	Counter	dccpOutDataSegs;
+	Counter dccpOutDataBytes;
+
+	int	dccpEntrySize;
+	int	dccp6EntrySize;
+
+	int	dccpConnTableSize;
+	int	dccp6ConnTableSize;
+
+	Counter64	dccpHCInDatagrams;
+	/* total # of segments recv'd				{ tcp 17 } */
+	Counter64	dccpHCInSegs;
+	/* total # of segments sent				{ tcp 18 } */
+	Counter64	dccpHCOutSegs;
+} mib2_dccp_t;
+#define	MIB_FIRST_NEW_ELM_mib2_dccp_t	dccpHCInDatagrams
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack()
+#endif
+
+/* Pack data to make struct size the same for 32- and 64-bits */
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack(4)
+#endif
+
+typedef struct mib2_dccpConnEntry {
+	int		dccpConnState;
+	IpAddress	dccpConnLocalAddress;
+	int		dccpConnLocalPort;
+	IpAddress	dccpConnRemAddress;
+	int		dccpConnRemPort;
+
+	struct dccpConnEntryInfo_s {
+				/* current rto (retransmit timeout) */
+		Gauge		ce_rto;
+				/* current max segment size */
+		Gauge		ce_mss;
+				/* actual internal state */
+		int		ce_state;
+	} dccpConnEntryInfo;
+
+	uint32_t	dccpConnCreationProcess;
+	uint64_t	dccpConnCreationTime;
+} mib2_dccpConnEntry_t;
+#define	MIB_FIRST_NEW_ELM_mib2_dccpConnEntry_t	dccpConnCreationProcess
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack()
+#endif
+
+/* Pack data to make struct size the same for 32- and 64-bits */
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack(4)
+#endif
+
+typedef struct mib2_dccp6ConnEntry {
+	Ip6Address	dccp6ConnLocalAddress;
+	int		dccp6ConnLocalPort;
+	Ip6Address	dccp6ConnRemAddress;
+	int		dccp6ConnRemPort;
+	/* Interface index or zero		{ ipv6DccpConnEntry 5 } */
+	DeviceIndex	dccp6ConnIfIndex;
+	/* State of dccp6 connection		{ ipv6DccpConnEntry 6 } RW */
+	int		dccp6ConnState;
+
+	struct dccp6ConnEntryInfo_s {
+				/* current rto (retransmit timeout) */
+		Gauge		ce_rto;
+				/* current max segment size */
+		Gauge		ce_mss;
+				/* actual internal state */
+		int		ce_state;
+	} dccp6ConnEntryInfo;
+
+	/* PID of the processes that created this connection */
+	uint32_t	dccp6ConnCreationProcess;
+	/* System uptime when the connection was created */
+	uint64_t	dccp6ConnCreationTime;
+} mib2_dccp6ConnEntry_t;
+#define	MIB_FIRST_NEW_ELM_mib2_dccp6ConnEntry_t	dccp6ConnCreationProcess
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack()
+#endif
 
 #ifdef	__cplusplus
 }
--- old/usr/src/uts/common/inet/sctp/sctp_impl.h	2012-08-18 10:37:19.254457184 +0000
+++ new/usr/src/uts/common/inet/sctp/sctp_impl.h	2012-08-18 10:37:19.302716445 +0000
@@ -445,6 +445,9 @@
 typedef struct sctp_tf_s {
 	struct sctp_s	*tf_sctp;
 	kmutex_t	tf_lock;
+#define	SF_CACHEL_PAD	64
+	uchar_t		tf_pad[SF_CACHEL_PAD - (sizeof (struct sctp_s *) +
+			    sizeof (kmutex_t))];
 } sctp_tf_t;
 
 /* Round up the value to the nearest mss. */
--- old/usr/src/uts/common/inet/tcp/tcp.c	2012-08-18 10:37:20.027896636 +0000
+++ new/usr/src/uts/common/inet/tcp/tcp.c	2012-08-18 10:37:20.082189031 +0000
@@ -2699,7 +2699,6 @@
 	connp->conn_zoneid = zoneid;
 	/* conn_allzones can not be set this early, hence no IPCL_ZONEID */
 	connp->conn_ixa->ixa_zoneid = zoneid;
-	connp->conn_mlp_type = mlptSingle;
 	ASSERT(connp->conn_netstack == tcps->tcps_netstack);
 	ASSERT(tcp->tcp_tcps == tcps);
 
--- old/usr/src/uts/common/inet/tcp/tcp_opt_data.c	2012-08-18 10:37:20.657939847 +0000
+++ new/usr/src/uts/common/inet/tcp/tcp_opt_data.c	2012-08-18 10:37:20.668722121 +0000
@@ -42,6 +42,8 @@
 #include <inet/proto_set.h>
 #include <inet/tcp_impl.h>
 
+static int      tcp_opt_default(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
+
 /*
  * Table of all known options handled on a TCP protocol stack.
  *
--- old/usr/src/uts/common/inet/tcp/tcp_socket.c	2012-08-18 10:37:20.984142351 +0000
+++ new/usr/src/uts/common/inet/tcp/tcp_socket.c	2012-08-18 10:37:21.005224879 +0000
@@ -54,12 +54,16 @@
 static int	tcp_listen(sock_lower_handle_t, int, cred_t *);
 static int	tcp_connect(sock_lower_handle_t, const struct sockaddr *,
 		    socklen_t, sock_connid_t *, cred_t *);
+static int	tcp_getpeername(sock_lower_handle_t, struct sockaddr *,
+		    socklen_t *, cred_t *);
+static int	tcp_getsockname(sock_lower_handle_t, struct sockaddr *,
+		    socklen_t *, cred_t *);
 static int	tcp_getsockopt(sock_lower_handle_t, int, int, void *,
 		    socklen_t *, cred_t *);
 static int	tcp_setsockopt(sock_lower_handle_t, int, int, const void *,
 		    socklen_t, cred_t *);
 static int	tcp_sendmsg(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
-		    cred_t *cr);
+		    cred_t *);
 static int	tcp_shutdown(sock_lower_handle_t, int, cred_t *);
 static void	tcp_clr_flowctrl(sock_lower_handle_t);
 static int	tcp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
@@ -327,7 +331,6 @@
 		(*connp->conn_upcalls->su_set_proto_props)(
 		    connp->conn_upper_handle, &sopp);
 	}
-done:
 	squeue_synch_exit(connp);
 
 	return ((error == 0) ? EINPROGRESS : error);
@@ -752,6 +755,7 @@
 {
 	conn_t		*connp;
 	boolean_t	isv6 = family == AF_INET6;
+
 	if (type != SOCK_STREAM || (family != AF_INET && family != AF_INET6) ||
 	    (proto != 0 && proto != IPPROTO_TCP)) {
 		*errorp = EPROTONOSUPPORT;
@@ -765,8 +769,8 @@
 
 	/*
 	 * Put the ref for TCP. Ref for IP was already put
-	 * by ipcl_conn_create. Also Make the conn_t globally
-	 * visible to walkers
+	 * by ipcl_conn_create. Also make the conn_t globally
+	 * visible to walkers.
 	 */
 	mutex_enter(&connp->conn_lock);
 	CONN_INC_REF_LOCKED(connp);
--- old/usr/src/uts/common/inet/tcp_impl.h	2012-08-18 10:37:21.303575831 +0000
+++ new/usr/src/uts/common/inet/tcp_impl.h	2012-08-18 10:37:21.320552141 +0000
@@ -546,10 +546,6 @@
 extern void	tcp_eager_cleanup(tcp_t *, boolean_t);
 extern void	tcp_eager_kill(void *, mblk_t *, void *, ip_recv_attr_t *);
 extern void	tcp_eager_unlink(tcp_t *);
-extern int	tcp_getpeername(sock_lower_handle_t, struct sockaddr *,
-		    socklen_t *, cred_t *);
-extern int	tcp_getsockname(sock_lower_handle_t, struct sockaddr *,
-		    socklen_t *, cred_t *);
 extern void	tcp_init_values(tcp_t *, tcp_t *);
 extern void	tcp_ipsec_cleanup(tcp_t *);
 extern int	tcp_maxpsz_set(tcp_t *, boolean_t);
@@ -679,7 +675,6 @@
 /*
  * TCP option processing related functions in tcp_opt_data.c
  */
-extern int	tcp_opt_default(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
 extern int	tcp_opt_get(conn_t *, int, int, uchar_t *);
 extern int	tcp_opt_set(conn_t *, uint_t, int, int, uint_t, uchar_t *,
 		    uint_t *, uchar_t *, void *, cred_t *);
--- old/usr/src/uts/common/inet/tcp_stats.h	2012-08-18 10:37:21.643901515 +0000
+++ new/usr/src/uts/common/inet/tcp_stats.h	2012-08-18 10:37:21.653079147 +0000
@@ -48,7 +48,7 @@
  *
  * TCP_DBGSTAT(name) does atomic increment of a named stat counter. It is
  * supposed to be used for DEBUG purposes and may be used on a hot path.
- * These counters are only available in a debugged kerel.  They are grouped
+ * These counters are only available in a debugged kernel.  They are grouped
  * under the TCP_DEBUG_COUNTER C pre-processor condition.
  *
  * Both TCP_STAT and TCP_DBGSTAT counters are available using kstat
--- old/usr/src/uts/common/inet/tunables.c	2012-08-18 10:37:21.966834655 +0000
+++ new/usr/src/uts/common/inet/tunables.c	2012-08-18 10:37:21.975440362 +0000
@@ -34,6 +34,8 @@
 #include <inet/tcp_stack.h>
 #include <inet/tcp_impl.h>
 #include <inet/udp_impl.h>
+#include <inet/dccp_stack.h>
+#include <inet/dccp_impl.h>
 #include <inet/sctp/sctp_stack.h>
 #include <inet/sctp/sctp_impl.h>
 #include <inet/tunables.h>
@@ -205,6 +207,7 @@
 	ip_stack_t	*ipst;
 	tcp_stack_t	*tcps;
 	sctp_stack_t	*sctps;
+	dccp_stack_t	*dccps;
 	udp_stack_t	*us;
 	icmp_stack_t	*is;
 	uint_t		size;
@@ -236,6 +239,10 @@
 		sctps = (sctp_stack_t *)cbarg;
 		ptbl = sctps->sctps_propinfo_tbl;
 		break;
+	case MOD_PROTO_DCCP:
+		dccps = (dccp_stack_t *)cbarg;
+		ptbl = dccps->dccps_propinfo_tbl;
+		break;
 	default:
 		return (EINVAL);
 	}
--- old/usr/src/uts/common/inet/tunables.h	2012-08-18 10:37:22.235610631 +0000
+++ new/usr/src/uts/common/inet/tunables.h	2012-08-18 10:37:22.246234697 +0000
@@ -79,6 +79,7 @@
 #define	MOD_PROTO_TCP		0x08	/* property is applicable to TCP */
 #define	MOD_PROTO_UDP		0x10	/* property is applicable to UDP */
 #define	MOD_PROTO_SCTP		0x20	/* property is applicable to SCTP */
+#define	MOD_PROTO_DCCP		0x40	/* property is applicable to DCCP */
 
 /* property is applicable to both IPV[4|6] */
 #define	MOD_PROTO_IP		(MOD_PROTO_IPV4|MOD_PROTO_IPV6)
--- old/usr/src/uts/common/netinet/Makefile	2012-08-18 10:37:22.556303399 +0000
+++ new/usr/src/uts/common/netinet/Makefile	2012-08-18 10:37:22.587821096 +0000
@@ -18,9 +18,6 @@
 #
 # CDDL HEADER END
 #
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
@@ -29,10 +26,10 @@
 # include global definitions
 include ../../../Makefile.master
 
-HDRS=	arp.h dhcp.h dhcp6.h icmp6.h icmp_var.h if_ether.h igmp.h igmp_var.h \
-	in.h inetutil.h in_pcb.h in_systm.h in_var.h ip.h ip6.h ip_icmp.h \
-	ip_mroute.h ip_var.h pim.h sctp.h tcp.h tcp_debug.h tcp_fsm.h \
-	tcp_seq.h tcp_timer.h tcp_var.h tcpip.h udp.h udp_var.h
+HDRS=	arp.h dccp.h dhcp.h dhcp6.h icmp6.h icmp_var.h if_ether.h igmp.h \
+	igmp_var.h in.h inetutil.h in_pcb.h in_systm.h in_var.h ip.h ip6.h \
+	ip_icmp.h ip_mroute.h ip_var.h pim.h sctp.h tcp.h tcp_debug.h \
+	tcp_fsm.h tcp_seq.h tcp_timer.h tcp_var.h tcpip.h udp.h udp_var.h
 
 ROOTDIRS= $(ROOT)/usr/include/netinet
 
--- /dev/null	2012-08-18 10:37:22.000000000 +0000
+++ new/usr/src/uts/common/netinet/dccp.h	2012-08-18 10:37:22.839094471 +0000
@@ -0,0 +1,89 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 David Hoeppner.  All rights reserved.
+ */
+
+#ifndef	_NETINET_DCCP_H
+#define	_NETINET_DCCP_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * DCCP header
+ */
+struct dccphdr {
+	uint16_t	dh_sport;
+	uint16_t	dh_dport;
+	uint8_t		dh_offset;
+#ifdef _BIT_FIELDS_LTOH
+	uint8_t		dh_cscov:4,
+			dh_ccval:4;
+#else
+	uint8_t		dh_ccval:4,
+			dh_cscov:4;
+#endif
+	uint16_t	dh_sum;
+#ifdef _BIT_FIELDS_LTOH
+	uint8_t		dh_x:1,
+			dh_type:4,
+			dh_reserved:3;
+#else
+	uint8_t		dh_reserved:3,
+			dh_type:4,
+			dh_x:1;
+#endif
+	uint8_t		dh_res_seq;
+	uint16_t	dh_seq;
+};
+
+#define	DCCPOPT_PADDING			0
+#define	DCCPOPT_MANDATORY		1
+#define	DCCPOPT_SLOW_RECEIVER		2
+#define	DCCPOPT_CHANGE_L		32
+#define	DCCPOPT_CONFIRM_L		33
+#define	DCCPOPT_CHANGE_R		34
+#define	DCCPOPT_CONFIRM_R		35
+#define	DCCPOPT_INIT_COOKIE		36
+#define	DCCPOPT_NDP_COUNT		37
+#define	DCCPOPT_ACK_VECTOR_1		38
+#define	DCCPOPT_ACK_VECTOR_2		39
+#define	DCCPOPT_DATA_DROPPED		40
+#define	DCCPOPT_TIMESTAMP		41
+#define	DCCPOPT_TIMESTAMP_ECHO		42
+#define	DCCPOPT_ELAPSED_TIME		43
+#define	DCCPOPT_DATA_CHECKSUM		44
+
+/*
+ * Options for use with getsockopt and setsockopt.
+ */
+
+#define	DCCP_KEEPALIVE			0x08
+#define	DCCP_NOTIFY_THRESHOLD		0x10
+#define	DCCP_ABORT_THRESHOLD		0x11
+#define	DCCP_CONN_NOTIFY_THRESHOLD	0x12
+#define	DCCP_CONN_ABORT_THRESHOLD	0x13
+
+#define	DCCP_KEEPALIVE_THRESHOLD	0x16
+#define	DCCP_KEEPALIVE_ABORT_THRESHOLD	0x17
+
+#define	DCCP_KEEPIDLE			0x22
+#define	DCCP_KEEPCNT			0x23
+#define	DCCP_KEEPINTVL			0x24
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _NETINET_DCCP_H */
--- old/usr/src/uts/common/netinet/in.h	2012-08-18 10:37:23.016547010 +0000
+++ new/usr/src/uts/common/netinet/in.h	2012-08-18 10:37:23.033284229 +0000
@@ -159,6 +159,7 @@
 #define	IPPROTO_PUP		12		/* pup */
 #define	IPPROTO_UDP		17		/* user datagram protocol */
 #define	IPPROTO_IDP		22		/* xns idp */
+#define	IPPROTO_DCCP		33		/* DCCP */
 #define	IPPROTO_IPV6		41		/* IPv6 encapsulated in IP */
 #define	IPPROTO_ROUTING		43		/* Routing header for IPv6 */
 #define	IPPROTO_FRAGMENT	44		/* Fragment header for IPv6 */
--- old/usr/src/uts/common/sys/netstack.h	2012-08-18 10:37:23.467888523 +0000
+++ new/usr/src/uts/common/sys/netstack.h	2012-08-18 10:37:23.501374174 +0000
@@ -81,7 +81,8 @@
 #define	NS_IPSECESP	16
 #define	NS_IPNET	17
 #define	NS_ILB		18
-#define	NS_MAX		(NS_ILB+1)
+#define	NS_DCCP		19
+#define	NS_MAX		(NS_DCCP+1)
 
 /*
  * State maintained for each module which tracks the state of
@@ -157,6 +158,7 @@
 			struct ipsecesp_stack	*nu_ipsecesp;
 			struct ipnet_stack	*nu_ipnet;
 			struct ilb_stack	*nu_ilb;
+			struct dccp_stack	*nu_dccp;
 		} nu_s;
 	} netstack_u;
 #define	netstack_modules	netstack_u.nu_modules
@@ -179,6 +181,7 @@
 #define	netstack_ipsecesp	netstack_u.nu_s.nu_ipsecesp
 #define	netstack_ipnet		netstack_u.nu_s.nu_ipnet
 #define	netstack_ilb		netstack_u.nu_s.nu_ilb
+#define	netstack_dccp		netstack_u.nu_s.nu_dccp
 
 	nm_state_t	netstack_m_state[NS_MAX]; /* module state */
 
--- old/usr/src/uts/common/sys/sdt.h	2012-08-18 10:37:23.912930339 +0000
+++ new/usr/src/uts/common/sys/sdt.h	2012-08-18 10:37:23.954185599 +0000
@@ -329,6 +329,33 @@
 	DTRACE_PROBE5(__udp_##name, type1, arg1, type2, arg2,		\
 	    type3, arg3, type4, arg4, type5, arg5);
 
+#define	DTRACE_DCCP(name)						\
+	DTRACE_PROBE(__dccp_##name);
+
+#define	DTRACE_DCCP1(name, type1, arg1)					\
+	DTRACE_PROBE1(__dccp_##name, type1, arg1);
+
+#define	DTRACE_DCCP2(name, type1, arg1, type2, arg2)			\
+	DTRACE_PROBE2(__dccp_##name, type1, arg1, type2, arg2);
+
+#define	DTRACE_DCCP3(name, type1, arg1, type2, arg2, type3, arg3)	\
+	DTRACE_PROBE3(__dccp_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define	DTRACE_DCCP4(name, type1, arg1, type2, arg2,			\
+    type3, arg3, type4, arg4)						\
+	DTRACE_PROBE4(__dccp_##name, type1, arg1, type2, arg2,		\
+	    type3, arg3, type4, arg4);
+
+#define	DTRACE_DCCP5(name, type1, arg1, type2, arg2,			\
+    type3, arg3, type4, arg4, type5, arg5)				\
+	DTRACE_PROBE5(__dccp_##name, type1, arg1, type2, arg2,		\
+	    type3, arg3, type4, arg4, type5, arg5);
+
+#define	DTRACE_DCCP6(name, type1, arg1, type2, arg2,			\
+    type3, arg3, type4, arg4, type5, arg5, type6, arg6)			\
+	DTRACE_PROBE6(__dccp_##name, type1, arg1, type2, arg2,		\
+	    type3, arg3, type4, arg4, type5, arg5, type6, arg6);
+
 
 #define	DTRACE_SYSEVENT2(name, type1, arg1, type2, arg2)		\
 	DTRACE_PROBE2(__sysevent_##name, type1, arg1, type2, arg2);
--- old/usr/src/uts/intel/Makefile.intel.shared	2012-08-18 10:37:24.323571667 +0000
+++ new/usr/src/uts/intel/Makefile.intel.shared	2012-08-18 10:37:24.383704246 +0000
@@ -230,6 +230,8 @@
 DRV_KMODS	+= crypto
 DRV_KMODS	+= cryptoadm
 DRV_KMODS	+= dca
+DRV_KMODS	+= dccp
+DRV_KMODS	+= dccp6
 DRV_KMODS	+= devinfo
 DRV_KMODS	+= dld
 DRV_KMODS	+= dlpistub
--- /dev/null	2012-08-18 10:37:24.000000000 +0000
+++ new/usr/src/uts/intel/dccp/Makefile	2012-08-18 10:37:24.900189523 +0000
@@ -0,0 +1,98 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# uts/intel/dccp/Makefile
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#	This makefile drives the production of the dccp driver kernel module.
+#
+#	intel implementation architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= dccp
+OBJECTS		= $(DCCP_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(DCCP_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
+ROOTLINK	= $(ROOT_STRMOD_DIR)/$(MODULE) $(ROOT_SOCK_DIR)/$(MODULE)
+CONF_SRCDIR	= $(UTSBASE)/common/inet/dccp
+
+#
+# Extra for $(MODULE).check target
+#
+# Need to remove ipddi.o since it has non-static defines for _init etc.
+IP_CHECK_OBJS	= $(IP_OBJS:ipddi.o=ip.o)
+EXTRA_CHECK_OBJS = $(IP_CHECK_OBJS:%=../ip/$(OBJS_DIR)/%)
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY) $(SRC_CONFILE)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
+
+#
+#	depends on ip and sockfs
+#
+LDFLAGS		+= -dy -Ndrv/ip -Nfs/sockfs
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+$(ROOTLINK):	$(ROOT_STRMOD_DIR) $(ROOT_SOCK_DIR) $(ROOTMODULE)
+	-$(RM) $@; ln $(ROOTMODULE) $@
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
--- /dev/null	2012-08-18 10:37:25.000000000 +0000
+++ new/usr/src/uts/intel/dccp6/Makefile	2012-08-18 10:37:25.036199708 +0000
@@ -0,0 +1,93 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License").  You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#	This makefile drives the production of the dccp6 driver kernel module.
+#
+#	intel implementation architecture dependent
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= dccp6
+OBJECTS		= $(TCP6_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(TCP6_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
+CONF_SRCDIR	= $(UTSBASE)/common/inet/dccp
+
+#
+# Extra for $(MODULE).check target
+#
+# Need to remove ipddi.o since it has non-static defines for _init etc.
+IP_CHECK_OBJS	= $(IP_OBJS:ipddi.o=ip.o)
+EXTRA_CHECK_OBJS = $(IP_CHECK_OBJS:%=../ip/$(OBJS_DIR)/%)
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
+
+#
+#	depends on tcp ip and ip6
+#
+LDFLAGS		+= -dy -Ndrv/tcp -Ndrv/ip -Ndrv/ip6
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
--- old/usr/src/uts/intel/ip/ip.global-objs.debug64	2012-08-18 10:37:25.185964038 +0000
+++ new/usr/src/uts/intel/ip/ip.global-objs.debug64	2012-08-18 10:37:25.209166237 +0000
@@ -48,6 +48,30 @@
 cl_sctp_listen
 cl_sctp_unlisten
 conn_drain_nthreads
+dccp_acceptor_rinit
+dccp_acceptor_winit
+dccp_bind_fanout_size
+dccp_conn_cache
+dccp_fallback_sock_winit
+dccp_g_t_info_ack
+dccp_g_t_info_ack_v6
+dccp_max_optsize
+dccp_opt_arr
+dccp_opt_obj
+dccp_propinfo_count
+dccp_propinfo_tbl
+dccp_random_anon_port
+dccp_rinfo
+dccp_rinitv4
+dccp_rinitv6
+dccp_sock_winit
+dccp_squeue_flag
+dccp_timercache
+dccp_valid_levels_arr
+dccp_winfo
+dccp_winit
+dccpinfov4
+dccpinfov6
 dce_cache
 default_ip6_asp_table
 do_tcp_fusion
@@ -144,6 +168,8 @@
 ipcl_conn_hash_maxsize
 ipcl_conn_hash_memfactor
 ipcl_conn_hash_size
+ipcl_dccp_bind_fanout_size
+ipcl_dccp_conn_fanout_size
 ipcl_iptun_fanout_size
 ipcl_raw_fanout_size
 ipcl_udp_fanout_size
@@ -236,6 +262,7 @@
 sin6_null
 sin_null
 skip_sctp_cksum
+sock_dccp_downcalls
 sock_rawip_downcalls
 sock_rts_downcalls
 sock_tcp_downcalls
--- old/usr/src/uts/intel/ip/ip.global-objs.obj64	2012-08-18 10:37:25.594355824 +0000
+++ new/usr/src/uts/intel/ip/ip.global-objs.obj64	2012-08-18 10:37:25.642252457 +0000
@@ -48,6 +48,30 @@
 cl_sctp_listen
 cl_sctp_unlisten
 conn_drain_nthreads
+dccp_acceptor_rinit
+dccp_acceptor_winit
+dccp_bind_fanout_size
+dccp_conn_cache
+dccp_fallback_sock_winit
+dccp_g_t_info_ack
+dccp_g_t_info_ack_v6
+dccp_max_optsize
+dccp_opt_arr
+dccp_opt_obj
+dccp_propinfo_count
+dccp_propinfo_tbl
+dccp_random_anon_port
+dccp_rinfo
+dccp_rinitv4
+dccp_rinitv6
+dccp_sock_winit
+dccp_squeue_flag
+dccp_timercache
+dccp_valid_levels_arr
+dccp_winfo
+dccp_winit
+dccpinfov4
+dccpinfov6
 dce_cache
 default_ip6_asp_table
 do_tcp_fusion
@@ -144,6 +168,8 @@
 ipcl_conn_hash_maxsize
 ipcl_conn_hash_memfactor
 ipcl_conn_hash_size
+ipcl_dccp_bind_fanout_size
+ipcl_dccp_conn_fanout_size
 ipcl_iptun_fanout_size
 ipcl_raw_fanout_size
 ipcl_udp_fanout_size
@@ -233,6 +259,7 @@
 sctpdebug
 sin6_null
 sin_null
+sock_dccp_downcalls
 sock_rawip_downcalls
 sock_rts_downcalls
 sock_tcp_downcalls
