10f1702cYu Xiangning<Eric.Yu@Sun.COM>/*
20f1702cYu Xiangning<Eric.Yu@Sun.COM> * CDDL HEADER START
30f1702cYu Xiangning<Eric.Yu@Sun.COM> *
40f1702cYu Xiangning<Eric.Yu@Sun.COM> * The contents of this file are subject to the terms of the
50f1702cYu Xiangning<Eric.Yu@Sun.COM> * Common Development and Distribution License (the "License").
60f1702cYu Xiangning<Eric.Yu@Sun.COM> * You may not use this file except in compliance with the License.
70f1702cYu Xiangning<Eric.Yu@Sun.COM> *
80f1702cYu Xiangning<Eric.Yu@Sun.COM> * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90f1702cYu Xiangning<Eric.Yu@Sun.COM> * or http://www.opensolaris.org/os/licensing.
100f1702cYu Xiangning<Eric.Yu@Sun.COM> * See the License for the specific language governing permissions
110f1702cYu Xiangning<Eric.Yu@Sun.COM> * and limitations under the License.
120f1702cYu Xiangning<Eric.Yu@Sun.COM> *
130f1702cYu Xiangning<Eric.Yu@Sun.COM> * When distributing Covered Code, include this CDDL HEADER in each
140f1702cYu Xiangning<Eric.Yu@Sun.COM> * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150f1702cYu Xiangning<Eric.Yu@Sun.COM> * If applicable, add the following below this CDDL HEADER, with the
160f1702cYu Xiangning<Eric.Yu@Sun.COM> * fields enclosed by brackets "[]" replaced with your own identifying
170f1702cYu Xiangning<Eric.Yu@Sun.COM> * information: Portions Copyright [yyyy] [name of copyright owner]
180f1702cYu Xiangning<Eric.Yu@Sun.COM> *
190f1702cYu Xiangning<Eric.Yu@Sun.COM> * CDDL HEADER END
200f1702cYu Xiangning<Eric.Yu@Sun.COM> */
210f1702cYu Xiangning<Eric.Yu@Sun.COM>/*
22bd670b3Erik Nordmark * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230f1702cYu Xiangning<Eric.Yu@Sun.COM> * Use is subject to license terms.
240f1702cYu Xiangning<Eric.Yu@Sun.COM> */
250f1702cYu Xiangning<Eric.Yu@Sun.COM>
260f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/types.h>
270f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <inet/common.h>
280f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/stream.h>
290f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/stropts.h>
300f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/strsun.h>
310f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/sysmacros.h>
320f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/stropts.h>
330f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/strsubr.h>
340f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/tpicommon.h>
350f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/socket_proto.h>
360f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <sys/policy.h>
370f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <inet/optcom.h>
380f1702cYu Xiangning<Eric.Yu@Sun.COM>#include <inet/ipclassifier.h>
390f1702cYu Xiangning<Eric.Yu@Sun.COM>
400f1702cYu Xiangning<Eric.Yu@Sun.COM>boolean_t
410f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_set_rx_hiwat(queue_t *q, conn_t *connp, size_t size)
420f1702cYu Xiangning<Eric.Yu@Sun.COM>{
430f1702cYu Xiangning<Eric.Yu@Sun.COM>
440f1702cYu Xiangning<Eric.Yu@Sun.COM>	if (connp != NULL && IPCL_IS_NONSTR(connp)) {
450f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct sock_proto_props sopp;
460f1702cYu Xiangning<Eric.Yu@Sun.COM>
470f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_flags = SOCKOPT_RCVHIWAT;
480f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_rxhiwat = size;
490f1702cYu Xiangning<Eric.Yu@Sun.COM>		(*connp->conn_upcalls->su_set_proto_props)
500f1702cYu Xiangning<Eric.Yu@Sun.COM>		    (connp->conn_upper_handle, &sopp);
510f1702cYu Xiangning<Eric.Yu@Sun.COM>	} else {
520f1702cYu Xiangning<Eric.Yu@Sun.COM>		MBLKP	mp;
530f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct stroptions *stropt;
540f1702cYu Xiangning<Eric.Yu@Sun.COM>
550f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (!(mp = allocb(sizeof (*stropt), BPRI_LO)))
560f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (B_FALSE);
570f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_datap->db_type = M_SETOPTS;
580f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_wptr += sizeof (*stropt);
590f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt = (struct stroptions *)mp->b_rptr;
600f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_flags = SO_HIWAT;
610f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_hiwat = size;
620f1702cYu Xiangning<Eric.Yu@Sun.COM>		putnext(q, mp);
630f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
640f1702cYu Xiangning<Eric.Yu@Sun.COM>	return (B_TRUE);
650f1702cYu Xiangning<Eric.Yu@Sun.COM>}
660f1702cYu Xiangning<Eric.Yu@Sun.COM>
670f1702cYu Xiangning<Eric.Yu@Sun.COM>boolean_t
680f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_set_rx_lowat(queue_t *q, conn_t *connp, size_t size)
690f1702cYu Xiangning<Eric.Yu@Sun.COM>{
700f1702cYu Xiangning<Eric.Yu@Sun.COM>
710f1702cYu Xiangning<Eric.Yu@Sun.COM>	if (connp != NULL && IPCL_IS_NONSTR(connp)) {
720f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct sock_proto_props sopp;
730f1702cYu Xiangning<Eric.Yu@Sun.COM>
740f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_flags = SOCKOPT_RCVLOWAT;
750f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_rxlowat = size;
760f1702cYu Xiangning<Eric.Yu@Sun.COM>		(*connp->conn_upcalls->su_set_proto_props)
770f1702cYu Xiangning<Eric.Yu@Sun.COM>		    (connp->conn_upper_handle, &sopp);
780f1702cYu Xiangning<Eric.Yu@Sun.COM>	} else {
790f1702cYu Xiangning<Eric.Yu@Sun.COM>		MBLKP	mp;
800f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct stroptions *stropt;
810f1702cYu Xiangning<Eric.Yu@Sun.COM>
820f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (!(mp = allocb(sizeof (*stropt), BPRI_LO)))
830f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (B_FALSE);
840f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_datap->db_type = M_SETOPTS;
850f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_wptr += sizeof (*stropt);
860f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt = (struct stroptions *)mp->b_rptr;
870f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_flags = SO_LOWAT;
880f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_lowat = size;
890f1702cYu Xiangning<Eric.Yu@Sun.COM>		putnext(q, mp);
900f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
910f1702cYu Xiangning<Eric.Yu@Sun.COM>	return (B_TRUE);
920f1702cYu Xiangning<Eric.Yu@Sun.COM>}
930f1702cYu Xiangning<Eric.Yu@Sun.COM>
940f1702cYu Xiangning<Eric.Yu@Sun.COM>/*
950f1702cYu Xiangning<Eric.Yu@Sun.COM> * Set maximum packet size. This is the maximum amount of data the protocol
960f1702cYu Xiangning<Eric.Yu@Sun.COM> * wants to be given at any time, Larger data needs to be broken in multiples
970f1702cYu Xiangning<Eric.Yu@Sun.COM> * of maximum packet size and given to the protocol one at a time.
980f1702cYu Xiangning<Eric.Yu@Sun.COM> */
990f1702cYu Xiangning<Eric.Yu@Sun.COM>boolean_t
1000f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_set_maxpsz(queue_t *q, conn_t *connp, size_t size)
1010f1702cYu Xiangning<Eric.Yu@Sun.COM>{
1020f1702cYu Xiangning<Eric.Yu@Sun.COM>	if (connp != NULL && IPCL_IS_NONSTR(connp)) {
1030f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct sock_proto_props sopp;
1040f1702cYu Xiangning<Eric.Yu@Sun.COM>
1050f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_flags = SOCKOPT_MAXPSZ;
1060f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_maxpsz = size;
1070f1702cYu Xiangning<Eric.Yu@Sun.COM>		(*connp->conn_upcalls->su_set_proto_props)
1080f1702cYu Xiangning<Eric.Yu@Sun.COM>		    (connp->conn_upper_handle, &sopp);
1090f1702cYu Xiangning<Eric.Yu@Sun.COM>		return (B_TRUE);
1100f1702cYu Xiangning<Eric.Yu@Sun.COM>	} else {
1110f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct stdata	*stp;
1120f1702cYu Xiangning<Eric.Yu@Sun.COM>		queue_t		*wq;
1130f1702cYu Xiangning<Eric.Yu@Sun.COM>		stp = STREAM(q);
1140f1702cYu Xiangning<Eric.Yu@Sun.COM>
1150f1702cYu Xiangning<Eric.Yu@Sun.COM>		/*
1160f1702cYu Xiangning<Eric.Yu@Sun.COM>		 * At this point change of a queue parameter is not allowed
1170f1702cYu Xiangning<Eric.Yu@Sun.COM>		 * when a multiplexor is sitting on top.
1180f1702cYu Xiangning<Eric.Yu@Sun.COM>		 */
1190f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (stp == NULL || stp->sd_flag & STPLEX)
1200f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (B_FALSE);
1210f1702cYu Xiangning<Eric.Yu@Sun.COM>
1220f1702cYu Xiangning<Eric.Yu@Sun.COM>		claimstr(stp->sd_wrq);
1230f1702cYu Xiangning<Eric.Yu@Sun.COM>		wq = stp->sd_wrq->q_next;
1240f1702cYu Xiangning<Eric.Yu@Sun.COM>		ASSERT(wq != NULL);
1250f1702cYu Xiangning<Eric.Yu@Sun.COM>		(void) strqset(wq, QMAXPSZ, 0, size);
1260f1702cYu Xiangning<Eric.Yu@Sun.COM>		releasestr(stp->sd_wrq);
1270f1702cYu Xiangning<Eric.Yu@Sun.COM>		return (B_TRUE);
1280f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
1290f1702cYu Xiangning<Eric.Yu@Sun.COM>}
1300f1702cYu Xiangning<Eric.Yu@Sun.COM>
1310f1702cYu Xiangning<Eric.Yu@Sun.COM>/* ARGSUSED */
1320f1702cYu Xiangning<Eric.Yu@Sun.COM>boolean_t
1330f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_set_tx_maxblk(queue_t *q, conn_t *connp, ssize_t size)
1340f1702cYu Xiangning<Eric.Yu@Sun.COM>{
1350f1702cYu Xiangning<Eric.Yu@Sun.COM>	if (connp != NULL && IPCL_IS_NONSTR(connp)) {
1360f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct sock_proto_props sopp;
1370f1702cYu Xiangning<Eric.Yu@Sun.COM>
1380f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_flags = SOCKOPT_MAXBLK;
1390f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_maxblk = size;
1400f1702cYu Xiangning<Eric.Yu@Sun.COM>		(*connp->conn_upcalls->su_set_proto_props)
1410f1702cYu Xiangning<Eric.Yu@Sun.COM>		    (connp->conn_upper_handle, &sopp);
1420f1702cYu Xiangning<Eric.Yu@Sun.COM>	} else {
1430f1702cYu Xiangning<Eric.Yu@Sun.COM>		MBLKP	mp;
1440f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct stroptions *stropt;
1450f1702cYu Xiangning<Eric.Yu@Sun.COM>
1460f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (!(mp = allocb(sizeof (*stropt), BPRI_LO)))
1470f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (B_FALSE);
1480f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_datap->db_type = M_SETOPTS;
1490f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_wptr += sizeof (*stropt);
1500f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt = (struct stroptions *)mp->b_rptr;
1510f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_flags = SO_MAXBLK;
1520f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_maxblk = size;
1530f1702cYu Xiangning<Eric.Yu@Sun.COM>		putnext(q, mp);
1540f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
1550f1702cYu Xiangning<Eric.Yu@Sun.COM>	return (B_TRUE);
1560f1702cYu Xiangning<Eric.Yu@Sun.COM>}
1570f1702cYu Xiangning<Eric.Yu@Sun.COM>
1580f1702cYu Xiangning<Eric.Yu@Sun.COM>boolean_t
1590f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_set_tx_copyopt(queue_t *q, conn_t *connp, int copyopt)
1600f1702cYu Xiangning<Eric.Yu@Sun.COM>{
1610f1702cYu Xiangning<Eric.Yu@Sun.COM>	if (connp != NULL && IPCL_IS_NONSTR(connp)) {
1620f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct sock_proto_props sopp;
1630f1702cYu Xiangning<Eric.Yu@Sun.COM>
1640f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_flags = SOCKOPT_ZCOPY;
1650f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_zcopyflag = (ushort_t)copyopt;
1660f1702cYu Xiangning<Eric.Yu@Sun.COM>		(*connp->conn_upcalls->su_set_proto_props)
1670f1702cYu Xiangning<Eric.Yu@Sun.COM>		    (connp->conn_upper_handle, &sopp);
1680f1702cYu Xiangning<Eric.Yu@Sun.COM>	} else {
1690f1702cYu Xiangning<Eric.Yu@Sun.COM>		MBLKP	mp;
1700f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct stroptions *stropt;
1710f1702cYu Xiangning<Eric.Yu@Sun.COM>
1720f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (!(mp = allocb(sizeof (*stropt), BPRI_LO)))
1730f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (B_FALSE);
1740f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_datap->db_type = M_SETOPTS;
1750f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_wptr += sizeof (*stropt);
1760f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt = (struct stroptions *)mp->b_rptr;
1770f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_flags = SO_COPYOPT;
1780f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_copyopt = (ushort_t)copyopt;
1790f1702cYu Xiangning<Eric.Yu@Sun.COM>		putnext(q, mp);
1800f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
1810f1702cYu Xiangning<Eric.Yu@Sun.COM>	return (B_TRUE);
1820f1702cYu Xiangning<Eric.Yu@Sun.COM>}
1830f1702cYu Xiangning<Eric.Yu@Sun.COM>
1840f1702cYu Xiangning<Eric.Yu@Sun.COM>boolean_t
1850f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_set_tx_wroff(queue_t *q, conn_t *connp, size_t size)
1860f1702cYu Xiangning<Eric.Yu@Sun.COM>{
1870f1702cYu Xiangning<Eric.Yu@Sun.COM>	if (connp != NULL && IPCL_IS_NONSTR(connp)) {
1880f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct sock_proto_props sopp;
1890f1702cYu Xiangning<Eric.Yu@Sun.COM>
1900f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_flags = SOCKOPT_WROFF;
1910f1702cYu Xiangning<Eric.Yu@Sun.COM>		sopp.sopp_wroff = size;
1920f1702cYu Xiangning<Eric.Yu@Sun.COM>
1930f1702cYu Xiangning<Eric.Yu@Sun.COM>		/* XXX workaround for CR6757374 */
1940f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (connp->conn_upper_handle != NULL)
1950f1702cYu Xiangning<Eric.Yu@Sun.COM>			(*connp->conn_upcalls->su_set_proto_props)
1960f1702cYu Xiangning<Eric.Yu@Sun.COM>			    (connp->conn_upper_handle, &sopp);
1970f1702cYu Xiangning<Eric.Yu@Sun.COM>	} else {
1980f1702cYu Xiangning<Eric.Yu@Sun.COM>
1990f1702cYu Xiangning<Eric.Yu@Sun.COM>		MBLKP	mp;
2000f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct stroptions *stropt;
2010f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (!(mp = allocb(sizeof (*stropt), BPRI_LO)))
2020f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (B_FALSE);
2030f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_datap->db_type = M_SETOPTS;
2040f1702cYu Xiangning<Eric.Yu@Sun.COM>		mp->b_wptr += sizeof (*stropt);
2050f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt = (struct stroptions *)mp->b_rptr;
2060f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_flags = SO_WROFF;
2070f1702cYu Xiangning<Eric.Yu@Sun.COM>		stropt->so_wroff = (ushort_t)size;
2080f1702cYu Xiangning<Eric.Yu@Sun.COM>		putnext(q, mp);
2090f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
2100f1702cYu Xiangning<Eric.Yu@Sun.COM>	return (B_TRUE);
2110f1702cYu Xiangning<Eric.Yu@Sun.COM>}
2120f1702cYu Xiangning<Eric.Yu@Sun.COM>
2130f1702cYu Xiangning<Eric.Yu@Sun.COM>/*
2140f1702cYu Xiangning<Eric.Yu@Sun.COM> * set OOBINLINE processing on the socket
2150f1702cYu Xiangning<Eric.Yu@Sun.COM> */
2160f1702cYu Xiangning<Eric.Yu@Sun.COM>void
2170f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_set_rx_oob_opt(conn_t *connp, boolean_t onoff)
2180f1702cYu Xiangning<Eric.Yu@Sun.COM>{
2190f1702cYu Xiangning<Eric.Yu@Sun.COM>	struct sock_proto_props sopp;
2200f1702cYu Xiangning<Eric.Yu@Sun.COM>
2210f1702cYu Xiangning<Eric.Yu@Sun.COM>	ASSERT(IPCL_IS_NONSTR(connp));
2220f1702cYu Xiangning<Eric.Yu@Sun.COM>
2230f1702cYu Xiangning<Eric.Yu@Sun.COM>	sopp.sopp_flags = SOCKOPT_OOBINLINE;
2240f1702cYu Xiangning<Eric.Yu@Sun.COM>	sopp.sopp_oobinline = onoff;
2250f1702cYu Xiangning<Eric.Yu@Sun.COM>	(*connp->conn_upcalls->su_set_proto_props)
2260f1702cYu Xiangning<Eric.Yu@Sun.COM>	    (connp->conn_upper_handle, &sopp);
2270f1702cYu Xiangning<Eric.Yu@Sun.COM>}
2280f1702cYu Xiangning<Eric.Yu@Sun.COM>
2290f1702cYu Xiangning<Eric.Yu@Sun.COM>/*
2300f1702cYu Xiangning<Eric.Yu@Sun.COM> * Translate a TLI(/XTI) error into a system error as best we can.
2310f1702cYu Xiangning<Eric.Yu@Sun.COM> */
2320f1702cYu Xiangning<Eric.Yu@Sun.COM>static const int tli_errs[] = {
2330f1702cYu Xiangning<Eric.Yu@Sun.COM>		0,		/* no error	*/
2340f1702cYu Xiangning<Eric.Yu@Sun.COM>		EADDRNOTAVAIL,  /* TBADADDR	*/
2350f1702cYu Xiangning<Eric.Yu@Sun.COM>		ENOPROTOOPT,	/* TBADOPT	*/
2360f1702cYu Xiangning<Eric.Yu@Sun.COM>		EACCES,		/* TACCES	*/
2370f1702cYu Xiangning<Eric.Yu@Sun.COM>		EBADF,		/* TBADF	*/
2380f1702cYu Xiangning<Eric.Yu@Sun.COM>		EADDRNOTAVAIL,	/* TNOADDR	*/
2390f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TOUTSTATE	*/
2400f1702cYu Xiangning<Eric.Yu@Sun.COM>		ECONNABORTED,	/* TBADSEQ	*/
2410f1702cYu Xiangning<Eric.Yu@Sun.COM>		0,		/* TSYSERR - will never get	*/
2420f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TLOOK - should never be sent by transport */
2430f1702cYu Xiangning<Eric.Yu@Sun.COM>		EMSGSIZE,	/* TBADDATA	*/
2440f1702cYu Xiangning<Eric.Yu@Sun.COM>		EMSGSIZE,	/* TBUFOVFLW	*/
2450f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TFLOW	*/
2460f1702cYu Xiangning<Eric.Yu@Sun.COM>		EWOULDBLOCK,	/* TNODATA	*/
2470f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TNODIS	*/
2480f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TNOUDERR	*/
2490f1702cYu Xiangning<Eric.Yu@Sun.COM>		EINVAL,		/* TBADFLAG	*/
2500f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TNOREL	*/
2510f1702cYu Xiangning<Eric.Yu@Sun.COM>		EOPNOTSUPP,	/* TNOTSUPPORT	*/
2520f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TSTATECHNG	*/
2530f1702cYu Xiangning<Eric.Yu@Sun.COM>		/* following represent error namespace expansion with XTI */
2540f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TNOSTRUCTYPE - never sent by transport */
2550f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TBADNAME - never sent by transport */
2560f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TBADQLEN - never sent by transport */
2570f1702cYu Xiangning<Eric.Yu@Sun.COM>		EADDRINUSE,	/* TADDRBUSY	*/
2580f1702cYu Xiangning<Eric.Yu@Sun.COM>		EBADF,		/* TINDOUT	*/
2590f1702cYu Xiangning<Eric.Yu@Sun.COM>		EBADF,		/* TPROVMISMATCH */
2600f1702cYu Xiangning<Eric.Yu@Sun.COM>		EBADF,		/* TRESQLEN	*/
2610f1702cYu Xiangning<Eric.Yu@Sun.COM>		EBADF,		/* TRESADDR	*/
2620f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TQFULL - never sent by transport */
2630f1702cYu Xiangning<Eric.Yu@Sun.COM>		EPROTO,		/* TPROTO	*/
2640f1702cYu Xiangning<Eric.Yu@Sun.COM>};
2650f1702cYu Xiangning<Eric.Yu@Sun.COM>
2660f1702cYu Xiangning<Eric.Yu@Sun.COM>int
2670f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_tlitosyserr(int terr)
2680f1702cYu Xiangning<Eric.Yu@Sun.COM>{
2690f1702cYu Xiangning<Eric.Yu@Sun.COM>	ASSERT(terr != TSYSERR);
2700f1702cYu Xiangning<Eric.Yu@Sun.COM>	if (terr >= (sizeof (tli_errs) / sizeof (tli_errs[0])))
2710f1702cYu Xiangning<Eric.Yu@Sun.COM>		return (EPROTO);
2720f1702cYu Xiangning<Eric.Yu@Sun.COM>	else
2730f1702cYu Xiangning<Eric.Yu@Sun.COM>		return (tli_errs[terr]);
2740f1702cYu Xiangning<Eric.Yu@Sun.COM>}
2750f1702cYu Xiangning<Eric.Yu@Sun.COM>
2760f1702cYu Xiangning<Eric.Yu@Sun.COM>/*
2770f1702cYu Xiangning<Eric.Yu@Sun.COM> * Verify that address is suitable for connect/sendmsg and is aligned properly
2780f1702cYu Xiangning<Eric.Yu@Sun.COM> * Since this is a generic function we do not test for port being zero
2790f1702cYu Xiangning<Eric.Yu@Sun.COM> * as some protocols like icmp do not require a port
2800f1702cYu Xiangning<Eric.Yu@Sun.COM> */
2810f1702cYu Xiangning<Eric.Yu@Sun.COM>int
2820f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_verify_ip_addr(int family, const struct sockaddr *name, socklen_t namelen)
2830f1702cYu Xiangning<Eric.Yu@Sun.COM>{
2840f1702cYu Xiangning<Eric.Yu@Sun.COM>
2850f1702cYu Xiangning<Eric.Yu@Sun.COM>	if (name == NULL || !OK_32PTR((char *)name))
2860f1702cYu Xiangning<Eric.Yu@Sun.COM>		return (EINVAL);
2870f1702cYu Xiangning<Eric.Yu@Sun.COM>
2880f1702cYu Xiangning<Eric.Yu@Sun.COM>	switch (family) {
2890f1702cYu Xiangning<Eric.Yu@Sun.COM>	case AF_INET:
2900f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (name->sa_family != AF_INET) {
2910f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (EAFNOSUPPORT);
2920f1702cYu Xiangning<Eric.Yu@Sun.COM>		}
2930f1702cYu Xiangning<Eric.Yu@Sun.COM>
2940f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (namelen != (socklen_t)sizeof (struct sockaddr_in)) {
2950f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (EINVAL);
2960f1702cYu Xiangning<Eric.Yu@Sun.COM>		}
2970f1702cYu Xiangning<Eric.Yu@Sun.COM>		break;
2980f1702cYu Xiangning<Eric.Yu@Sun.COM>	case AF_INET6: {
2990f1702cYu Xiangning<Eric.Yu@Sun.COM>#ifdef DEBUG
3000f1702cYu Xiangning<Eric.Yu@Sun.COM>		struct sockaddr_in6 *sin6;
3010f1702cYu Xiangning<Eric.Yu@Sun.COM>#endif /* DEBUG */
3020f1702cYu Xiangning<Eric.Yu@Sun.COM>
3030f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (name->sa_family != AF_INET6) {
3040f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (EAFNOSUPPORT);
3050f1702cYu Xiangning<Eric.Yu@Sun.COM>		}
3060f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (namelen != (socklen_t)sizeof (struct sockaddr_in6)) {
3070f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (EINVAL);
3080f1702cYu Xiangning<Eric.Yu@Sun.COM>		}
3090f1702cYu Xiangning<Eric.Yu@Sun.COM>#ifdef DEBUG
3100f1702cYu Xiangning<Eric.Yu@Sun.COM>		/* Verify that apps don't forget to clear sin6_scope_id etc */
3110f1702cYu Xiangning<Eric.Yu@Sun.COM>		sin6 = (struct sockaddr_in6 *)name;
3120f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (sin6->sin6_scope_id != 0 &&
3130f1702cYu Xiangning<Eric.Yu@Sun.COM>		    !IN6_IS_ADDR_LINKSCOPE(&sin6->sin6_addr)) {
3140f1702cYu Xiangning<Eric.Yu@Sun.COM>			zcmn_err(getzoneid(), CE_WARN,
3150f1702cYu Xiangning<Eric.Yu@Sun.COM>			    "connect/send* with uninitialized sin6_scope_id "
3160f1702cYu Xiangning<Eric.Yu@Sun.COM>			    "(%d) on socket. Pid = %d\n",
3170f1702cYu Xiangning<Eric.Yu@Sun.COM>			    (int)sin6->sin6_scope_id, (int)curproc->p_pid);
3180f1702cYu Xiangning<Eric.Yu@Sun.COM>		}
3190f1702cYu Xiangning<Eric.Yu@Sun.COM>#endif /* DEBUG */
3200f1702cYu Xiangning<Eric.Yu@Sun.COM>		break;
3210f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
3220f1702cYu Xiangning<Eric.Yu@Sun.COM>	default:
3230f1702cYu Xiangning<Eric.Yu@Sun.COM>		return (EINVAL);
3240f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
3250f1702cYu Xiangning<Eric.Yu@Sun.COM>
3260f1702cYu Xiangning<Eric.Yu@Sun.COM>	return (0);
3270f1702cYu Xiangning<Eric.Yu@Sun.COM>}
3280f1702cYu Xiangning<Eric.Yu@Sun.COM>
3290f1702cYu Xiangning<Eric.Yu@Sun.COM>/*
3300f1702cYu Xiangning<Eric.Yu@Sun.COM> * Do a lookup of the options in the array.
3310f1702cYu Xiangning<Eric.Yu@Sun.COM> * Rerurn NULL if there isn't a match.
3320f1702cYu Xiangning<Eric.Yu@Sun.COM> */
3330f1702cYu Xiangning<Eric.Yu@Sun.COM>opdes_t *
3340f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_opt_lookup(t_uscalar_t level, t_uscalar_t name, opdes_t *opt_arr,
3350f1702cYu Xiangning<Eric.Yu@Sun.COM>    uint_t opt_arr_cnt)
3360f1702cYu Xiangning<Eric.Yu@Sun.COM>{
3370f1702cYu Xiangning<Eric.Yu@Sun.COM>	opdes_t		*optd;
3380f1702cYu Xiangning<Eric.Yu@Sun.COM>
3390f1702cYu Xiangning<Eric.Yu@Sun.COM>	for (optd = opt_arr; optd < &opt_arr[opt_arr_cnt];
3400f1702cYu Xiangning<Eric.Yu@Sun.COM>	    optd++) {
3410f1702cYu Xiangning<Eric.Yu@Sun.COM>		if (level == (uint_t)optd->opdes_level &&
3420f1702cYu Xiangning<Eric.Yu@Sun.COM>		    name == (uint_t)optd->opdes_name)
3430f1702cYu Xiangning<Eric.Yu@Sun.COM>			return (optd);
3440f1702cYu Xiangning<Eric.Yu@Sun.COM>	}
3450f1702cYu Xiangning<Eric.Yu@Sun.COM>	return (NULL);
3460f1702cYu Xiangning<Eric.Yu@Sun.COM>}
3470f1702cYu Xiangning<Eric.Yu@Sun.COM>
3480f1702cYu Xiangning<Eric.Yu@Sun.COM>/*
3490f1702cYu Xiangning<Eric.Yu@Sun.COM> * Do a lookup of the options in the array and do permission and length checking
3500f1702cYu Xiangning<Eric.Yu@Sun.COM> * Returns zero if there is no error (note: for non-tpi-providers not being able
351bd670b3Erik Nordmark * to find the option is not an error). TPI errors are returned as negative
352bd670b3Erik Nordmark * numbers and errnos as positive numbers.
353bd670b3Erik Nordmark * If max_len is set we update it based on the max length of the option.
3540f1702cYu Xiangning<Eric.Yu@Sun.COM> */
3550f1702cYu Xiangning<Eric.Yu@Sun.COM>int
3560f1702cYu Xiangning<Eric.Yu@Sun.COM>proto_opt_check(int level, int name, int len, t_uscalar_t *max_len,
357bd670b3Erik Nordmark    opdes_t *opt_arr, uint_t opt_arr_cnt, boolean_t negotiate, boolean_t check,
358