--- /dev/null	2012-06-13 12:04:33.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_input.c	2012-06-13 12:04:33.609296820 +0000
@@ -0,0 +1,353 @@
+/*
+ * 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/ip.h>
+
+#include <sys/cmn_err.h>
+
+#include "dccp_impl.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 *);
+
+void
+dccp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
+{
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_input_data");
+}
+
+void
+dccp_icmp_input(void *arg1, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
+{
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_icmp_input");
+}
+
+void
+dccp_rsrv(queue_t *q)
+{
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_rsrv");
+}
+
+static mblk_t *
+dccp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp,
+    ip_recv_attr_t *ira)
+{
+	return (NULL);
+}
+
+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) 1); /* XXX */
+
+	} else {
+		tpi_mp = mi_tpi_conn_ind(NULL,
+		(char *)&sin, sizeof (sin_t),
+		(char *)&dccp, (t_scalar_t)sizeof (intptr_t),
+		(t_scalar_t) 1); /* XXX */
+	}
+
+	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;
+	squeue_t	*new_sqp;
+	mblk_t		*tpi_mp;
+	mblk_t		*mp1;
+	uint_t		ip_hdr_len;
+	uint_t		type;
+	int		error;
+
+	cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener");
+
+	ip_hdr_len = ira->ira_ip_hdr_length;
+	dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
+	type = (uint_t)dccpha->dha_type;
+
+	if (type != DCCP_PKT_REQUEST) {
+		cmn_err(CE_NOTE, "not request pkt");
+
+		/* XXX do something with a reset packet sent? */
+		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;
+	}
+
+	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_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);
+
+	SOCK_CONNID_BUMP(eager->dccp_connid);
+
+	error = dccp_set_destination(eager);
+	if (error != 0) {
+		cmn_err(CE_NOTE, "dccp_set_destination failed.");
+		dccp_bind_hash_remove(eager);
+		goto error3;
+	}
+
+	CONN_INC_REF(lconnp);
+
+/*
+	mp1 = dccp_xmit_mp(eager, eager->dccp_xmit_head, 0,
+	    NULL, NULL, 0, B_FALSE, NULL, B_FALSE);
+*/
+	mp1 = dccp_generate_packet(lconnp, mp);
+	if (mp1 == NULL) {
+		cmn_err(CE_NOTE, "dccp_xmit_mp failed");
+
+		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;
+	}
+
+	freemsg(mp);
+
+	if (econnp->conn_sqp == lconnp->conn_sqp) {
+		(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_TCP_SEND_SYNACK); /* XXX */
+	}
+
+	return;
+error:
+error2:
+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);
+}
