--- /dev/null	2012-07-09 14:38:14.000000000 +0000
+++ new/usr/src/uts/common/inet/dccp/dccp_tpi.c	2012-07-09 14:38:14.307881618 +0000
@@ -0,0 +1,233 @@
+/*
+ * 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/ip.h>
+#include <inet/proto_set.h>
+
+#include <sys/cmn_err.h>
+
+#include "dccp_impl.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);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * Options related functions.
+ */
+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));
+}
+
+/* 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)
+{
+	queue_t		*rq = RD(q);
+
+	cmn_err(CE_NOTE, "dccp_tpi.c: dccp_tpi_accept");
+}
