17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * sppp_dlpi.c - Solaris STREAMS PPP multiplexing pseudo-driver DLPI handlers
37c478bd9Sstevel@tonic-gate  *
4*f53eecf5SJames Carlson  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
57c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
87c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that the above copyright
97c478bd9Sstevel@tonic-gate  * notice appears in all copies.
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
127c478bd9Sstevel@tonic-gate  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
137c478bd9Sstevel@tonic-gate  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
147c478bd9Sstevel@tonic-gate  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
157c478bd9Sstevel@tonic-gate  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
167c478bd9Sstevel@tonic-gate  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
177c478bd9Sstevel@tonic-gate  *
187c478bd9Sstevel@tonic-gate  * Copyright (c) 1994 The Australian National University.
197c478bd9Sstevel@tonic-gate  * All rights reserved.
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
227c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that the above copyright
237c478bd9Sstevel@tonic-gate  * notice appears in all copies.  This software is provided without any
247c478bd9Sstevel@tonic-gate  * warranty, express or implied. The Australian National University
257c478bd9Sstevel@tonic-gate  * makes no representations about the suitability of this software for
267c478bd9Sstevel@tonic-gate  * any purpose.
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
297c478bd9Sstevel@tonic-gate  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
307c478bd9Sstevel@tonic-gate  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
317c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
327c478bd9Sstevel@tonic-gate  * OF SUCH DAMAGE.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
357c478bd9Sstevel@tonic-gate  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
367c478bd9Sstevel@tonic-gate  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
377c478bd9Sstevel@tonic-gate  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
387c478bd9Sstevel@tonic-gate  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
397c478bd9Sstevel@tonic-gate  * OR MODIFICATIONS.
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  * This driver is derived from the original SVR4 STREAMS PPP driver
427c478bd9Sstevel@tonic-gate  * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
457c478bd9Sstevel@tonic-gate  * for improved performance and scalability.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #define	RCSID	"$Id: sppp_dlpi.c,v 1.0 2000/05/08 01:10:12 masputra Exp $"
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include <sys/types.h>
517c478bd9Sstevel@tonic-gate #include <sys/param.h>
527c478bd9Sstevel@tonic-gate #include <sys/stat.h>
537c478bd9Sstevel@tonic-gate #include <sys/stream.h>
547c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
557c478bd9Sstevel@tonic-gate #include <sys/errno.h>
567c478bd9Sstevel@tonic-gate #include <sys/time.h>
577c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
587c478bd9Sstevel@tonic-gate #include <sys/conf.h>
597c478bd9Sstevel@tonic-gate #include <sys/dlpi.h>
607c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
617c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
62*f53eecf5SJames Carlson #include <sys/strsubr.h>
637c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
647c478bd9Sstevel@tonic-gate #include <sys/ethernet.h>
657c478bd9Sstevel@tonic-gate #include <net/ppp_defs.h>
667c478bd9Sstevel@tonic-gate #include <netinet/in.h>
677c478bd9Sstevel@tonic-gate #include <net/pppio.h>
687c478bd9Sstevel@tonic-gate #include "s_common.h"
697c478bd9Sstevel@tonic-gate #include "sppp.h"
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate static int	sppp_dlattachreq(queue_t *, mblk_t *, spppstr_t *);
727c478bd9Sstevel@tonic-gate static int	sppp_dldetachreq(queue_t *, mblk_t *, spppstr_t *);
737c478bd9Sstevel@tonic-gate static int	sppp_dlbindreq(queue_t *, mblk_t *, spppstr_t *);
747c478bd9Sstevel@tonic-gate static int	sppp_dlunbindreq(queue_t *, mblk_t *, spppstr_t *);
757c478bd9Sstevel@tonic-gate static int	sppp_dlinforeq(queue_t *, mblk_t *, spppstr_t *);
767c478bd9Sstevel@tonic-gate static int	sppp_dlunitdatareq(queue_t *, mblk_t *, spppstr_t *);
777c478bd9Sstevel@tonic-gate static int	sppp_dlpromisconreq(queue_t *, mblk_t *, spppstr_t *);
787c478bd9Sstevel@tonic-gate static int	sppp_dlpromiscoffreq(queue_t *, mblk_t *, spppstr_t *);
797c478bd9Sstevel@tonic-gate static int	sppp_dlphyreq(queue_t *, mblk_t *, spppstr_t *);
807c478bd9Sstevel@tonic-gate static void	sppp_dl_attach_upper(queue_t *, mblk_t *);
817c478bd9Sstevel@tonic-gate static void	sppp_dl_detach_upper(queue_t *, mblk_t *);
827c478bd9Sstevel@tonic-gate static void	sppp_dl_bind(queue_t *, mblk_t *);
837c478bd9Sstevel@tonic-gate static void	sppp_dl_unbind(queue_t *, mblk_t *);
847c478bd9Sstevel@tonic-gate static void	sppp_dl_promiscon(queue_t *, mblk_t *);
857c478bd9Sstevel@tonic-gate static void	sppp_dl_promiscoff(queue_t *, mblk_t *);
867c478bd9Sstevel@tonic-gate static mblk_t	*sppp_dladdether(spppstr_t *, mblk_t *, t_scalar_t);
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static struct sppp_dlpi_pinfo_t dl_pinfo[DL_MAXPRIM + 1];
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate #if 0
917c478bd9Sstevel@tonic-gate #define	DBGERROR(x)	cmn_err x
927c478bd9Sstevel@tonic-gate #else
937c478bd9Sstevel@tonic-gate #define	DBGERROR(x)	((void)0)
947c478bd9Sstevel@tonic-gate #endif
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /* #define	DBG_DLPI	1 */
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
997c478bd9Sstevel@tonic-gate struct sppp_dlpi_entry {
1007c478bd9Sstevel@tonic-gate 	uint32_t sde_val;
1017c478bd9Sstevel@tonic-gate 	const char *sde_name;
1027c478bd9Sstevel@tonic-gate };
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate static const struct sppp_dlpi_entry sppp_dlpi_list[] = {
1057c478bd9Sstevel@tonic-gate 	{ DL_INFO_REQ, "DL_INFO_REQ" },
1067c478bd9Sstevel@tonic-gate 	{ DL_INFO_ACK, "DL_INFO_ACK" },
1077c478bd9Sstevel@tonic-gate 	{ DL_ATTACH_REQ, "DL_ATTACH_REQ" },
1087c478bd9Sstevel@tonic-gate 	{ DL_DETACH_REQ, "DL_DETACH_REQ" },
1097c478bd9Sstevel@tonic-gate 	{ DL_BIND_REQ, "DL_BIND_REQ" },
1107c478bd9Sstevel@tonic-gate 	{ DL_BIND_ACK, "DL_BIND_ACK" },
1117c478bd9Sstevel@tonic-gate 	{ DL_UNBIND_REQ, "DL_UNBIND_REQ" },
1127c478bd9Sstevel@tonic-gate 	{ DL_OK_ACK, "DL_OK_ACK" },
1137c478bd9Sstevel@tonic-gate 	{ DL_ERROR_ACK, "DL_ERROR_ACK" },
1147c478bd9Sstevel@tonic-gate 	{ DL_SUBS_BIND_REQ, "DL_SUBS_BIND_REQ" },
1157c478bd9Sstevel@tonic-gate 	{ DL_SUBS_BIND_ACK, "DL_SUBS_BIND_ACK" },
1167c478bd9Sstevel@tonic-gate 	{ DL_SUBS_UNBIND_REQ, "DL_SUBS_UNBIND_REQ" },
1177c478bd9Sstevel@tonic-gate 	{ DL_ENABMULTI_REQ, "DL_ENABMULTI_REQ" },
1187c478bd9Sstevel@tonic-gate 	{ DL_DISABMULTI_REQ, "DL_DISABMULTI_REQ" },
1197c478bd9Sstevel@tonic-gate 	{ DL_PROMISCON_REQ, "DL_PROMISCON_REQ" },
1207c478bd9Sstevel@tonic-gate 	{ DL_PROMISCOFF_REQ, "DL_PROMISCOFF_REQ" },
1217c478bd9Sstevel@tonic-gate 	{ DL_UNITDATA_REQ, "DL_UNITDATA_REQ" },
1227c478bd9Sstevel@tonic-gate 	{ DL_UNITDATA_IND, "DL_UNITDATA_IND" },
1237c478bd9Sstevel@tonic-gate 	{ DL_UDERROR_IND, "DL_UDERROR_IND" },
1247c478bd9Sstevel@tonic-gate 	{ DL_UDQOS_REQ, "DL_UDQOS_REQ" },
1257c478bd9Sstevel@tonic-gate 	{ DL_CONNECT_REQ, "DL_CONNECT_REQ" },
1267c478bd9Sstevel@tonic-gate 	{ DL_CONNECT_IND, "DL_CONNECT_IND" },
1277c478bd9Sstevel@tonic-gate 	{ DL_CONNECT_RES, "DL_CONNECT_RES" },
1287c478bd9Sstevel@tonic-gate 	{ DL_CONNECT_CON, "DL_CONNECT_CON" },
1297c478bd9Sstevel@tonic-gate 	{ DL_TOKEN_REQ, "DL_TOKEN_REQ" },
1307c478bd9Sstevel@tonic-gate 	{ DL_TOKEN_ACK, "DL_TOKEN_ACK" },
1317c478bd9Sstevel@tonic-gate 	{ DL_DISCONNECT_REQ, "DL_DISCONNECT_REQ" },
1327c478bd9Sstevel@tonic-gate 	{ DL_DISCONNECT_IND, "DL_DISCONNECT_IND" },
1337c478bd9Sstevel@tonic-gate 	{ DL_RESET_REQ, "DL_RESET_REQ" },
1347c478bd9Sstevel@tonic-gate 	{ DL_RESET_IND, "DL_RESET_IND" },
1357c478bd9Sstevel@tonic-gate 	{ DL_RESET_RES, "DL_RESET_RES" },
1367c478bd9Sstevel@tonic-gate 	{ DL_RESET_CON, "DL_RESET_CON" },
1377c478bd9Sstevel@tonic-gate 	{ DL_DATA_ACK_REQ, "DL_DATA_ACK_REQ" },
1387c478bd9Sstevel@tonic-gate 	{ DL_DATA_ACK_IND, "DL_DATA_ACK_IND" },
1397c478bd9Sstevel@tonic-gate 	{ DL_DATA_ACK_STATUS_IND, "DL_DATA_ACK_STATUS_IND" },
1407c478bd9Sstevel@tonic-gate 	{ DL_REPLY_REQ, "DL_REPLY_REQ" },
1417c478bd9Sstevel@tonic-gate 	{ DL_REPLY_IND, "DL_REPLY_IND" },
1427c478bd9Sstevel@tonic-gate 	{ DL_REPLY_STATUS_IND, "DL_REPLY_STATUS_IND" },
1437c478bd9Sstevel@tonic-gate 	{ DL_REPLY_UPDATE_REQ, "DL_REPLY_UPDATE_REQ" },
1447c478bd9Sstevel@tonic-gate 	{ DL_REPLY_UPDATE_STATUS_IND, "DL_REPLY_UPDATE_STATUS_IND" },
1457c478bd9Sstevel@tonic-gate 	{ DL_XID_REQ, "DL_XID_REQ" },
1467c478bd9Sstevel@tonic-gate 	{ DL_XID_IND, "DL_XID_IND" },
1477c478bd9Sstevel@tonic-gate 	{ DL_XID_RES, "DL_XID_RES" },
1487c478bd9Sstevel@tonic-gate 	{ DL_XID_CON, "DL_XID_CON" },
1497c478bd9Sstevel@tonic-gate 	{ DL_TEST_REQ, "DL_TEST_REQ" },
1507c478bd9Sstevel@tonic-gate 	{ DL_TEST_IND, "DL_TEST_IND" },
1517c478bd9Sstevel@tonic-gate 	{ DL_TEST_RES, "DL_TEST_RES" },
1527c478bd9Sstevel@tonic-gate 	{ DL_TEST_CON, "DL_TEST_CON" },
1537c478bd9Sstevel@tonic-gate 	{ DL_PHYS_ADDR_REQ, "DL_PHYS_ADDR_REQ" },
1547c478bd9Sstevel@tonic-gate 	{ DL_PHYS_ADDR_ACK, "DL_PHYS_ADDR_ACK" },
1557c478bd9Sstevel@tonic-gate 	{ DL_SET_PHYS_ADDR_REQ, "DL_SET_PHYS_ADDR_REQ" },
1567c478bd9Sstevel@tonic-gate 	{ DL_GET_STATISTICS_REQ, "DL_GET_STATISTICS_REQ" },
1577c478bd9Sstevel@tonic-gate 	{ DL_GET_STATISTICS_ACK, "DL_GET_STATISTICS_ACK" },
1587c478bd9Sstevel@tonic-gate 	{ 0, NULL }
1597c478bd9Sstevel@tonic-gate };
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate static const struct sppp_dlpi_entry sppp_state_list[] = {
1627c478bd9Sstevel@tonic-gate 	{ DL_UNBOUND, "DL_UNBOUND" },
1637c478bd9Sstevel@tonic-gate 	{ DL_BIND_PENDING, "DL_BIND_PENDING" },
1647c478bd9Sstevel@tonic-gate 	{ DL_UNBIND_PENDING, "DL_UNBIND_PENDING" },
1657c478bd9Sstevel@tonic-gate 	{ DL_IDLE, "DL_IDLE" },
1667c478bd9Sstevel@tonic-gate 	{ DL_UNATTACHED, "DL_UNATTACHED" },
1677c478bd9Sstevel@tonic-gate 	{ DL_ATTACH_PENDING, "DL_ATTACH_PENDING" },
1687c478bd9Sstevel@tonic-gate 	{ DL_DETACH_PENDING, "DL_DETACH_PENDING" },
1697c478bd9Sstevel@tonic-gate 	{ DL_UDQOS_PENDING, "DL_UDQOS_PENDING" },
1707c478bd9Sstevel@tonic-gate 	{ DL_OUTCON_PENDING, "DL_OUTCON_PENDING" },
1717c478bd9Sstevel@tonic-gate 	{ DL_INCON_PENDING, "DL_INCON_PENDING" },
1727c478bd9Sstevel@tonic-gate 	{ DL_CONN_RES_PENDING, "DL_CONN_RES_PENDING" },
1737c478bd9Sstevel@tonic-gate 	{ DL_DATAXFER, "DL_DATAXFER" },
1747c478bd9Sstevel@tonic-gate 	{ DL_USER_RESET_PENDING, "DL_USER_RESET_PENDING" },
1757c478bd9Sstevel@tonic-gate 	{ DL_PROV_RESET_PENDING, "DL_PROV_RESET_PENDING" },
1767c478bd9Sstevel@tonic-gate 	{ DL_RESET_RES_PENDING, "DL_RESET_RES_PENDING" },
1777c478bd9Sstevel@tonic-gate 	{ DL_DISCON8_PENDING, "DL_DISCON8_PENDING" },
1787c478bd9Sstevel@tonic-gate 	{ DL_DISCON9_PENDING, "DL_DISCON9_PENDING" },
1797c478bd9Sstevel@tonic-gate 	{ DL_DISCON11_PENDING, "DL_DISCON11_PENDING" },
1807c478bd9Sstevel@tonic-gate 	{ DL_DISCON12_PENDING, "DL_DISCON12_PENDING" },
1817c478bd9Sstevel@tonic-gate 	{ DL_DISCON13_PENDING, "DL_DISCON13_PENDING" },
1827c478bd9Sstevel@tonic-gate 	{ DL_SUBS_BIND_PND, "DL_SUBS_BIND_PND" },
1837c478bd9Sstevel@tonic-gate 	{ DL_SUBS_UNBIND_PND, "DL_SUBS_UNBIND_PND" },
1847c478bd9Sstevel@tonic-gate 	{ 0, NULL }
1857c478bd9Sstevel@tonic-gate };
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate static const char *
prim2name(uint32_t prim)1887c478bd9Sstevel@tonic-gate prim2name(uint32_t prim)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	const struct sppp_dlpi_entry *sde;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	for (sde = sppp_dlpi_list; sde->sde_name != NULL; sde++)
1937c478bd9Sstevel@tonic-gate 		if (sde->sde_val == prim)
1947c478bd9Sstevel@tonic-gate 			break;
1957c478bd9Sstevel@tonic-gate 	return (sde->sde_name);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate static const char *
state2name(uint32_t state)1997c478bd9Sstevel@tonic-gate state2name(uint32_t state)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate 	const struct sppp_dlpi_entry *sde;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	for (sde = sppp_state_list; sde->sde_name != NULL; sde++)
2047c478bd9Sstevel@tonic-gate 		if (sde->sde_val == state)
2057c478bd9Sstevel@tonic-gate 			break;
2067c478bd9Sstevel@tonic-gate 	return (sde->sde_name);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate #define	DBGDLPI(x)	cmn_err x
2107c478bd9Sstevel@tonic-gate #else
2117c478bd9Sstevel@tonic-gate #define	DBGDLPI(x)	((void)0)
2127c478bd9Sstevel@tonic-gate #endif /* DBG_DLPI */
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  * DL_INFO_ACK template for point-to-point interface.
2167c478bd9Sstevel@tonic-gate  */
2177c478bd9Sstevel@tonic-gate static dl_info_ack_t	sppp_infoack = {
2187c478bd9Sstevel@tonic-gate 	DL_INFO_ACK,			/* dl_primitive */
2197c478bd9Sstevel@tonic-gate 	PPP_MAXMTU,			/* dl_max_sdu */
2207c478bd9Sstevel@tonic-gate 	0,				/* dl_min_sdu */
2217c478bd9Sstevel@tonic-gate 	SPPP_ADDRL,			/* dl_addr_length */
2227c478bd9Sstevel@tonic-gate 	/*
2237c478bd9Sstevel@tonic-gate 	 * snoop et. al. don't know about DL_OTHER so this entry
2247c478bd9Sstevel@tonic-gate 	 * was changed to DL_ETHER so ethernet tracing/snooping
2257c478bd9Sstevel@tonic-gate 	 * facilities will work with PPP interfaces.
2267c478bd9Sstevel@tonic-gate 	 */
2277c478bd9Sstevel@tonic-gate 	DL_ETHER,			/* dl_mac_type */
2287c478bd9Sstevel@tonic-gate 	0,				/* dl_reserved */
2297c478bd9Sstevel@tonic-gate 	0,				/* dl_current_state */
2307c478bd9Sstevel@tonic-gate 	SPPP_SAPL,			/* dl_sap_length */
2317c478bd9Sstevel@tonic-gate 	DL_CLDLS,			/* dl_service_mode */
2327c478bd9Sstevel@tonic-gate 	0,				/* dl_qos_length */
2337c478bd9Sstevel@tonic-gate 	0,				/* dl_qos_offset */
2347c478bd9Sstevel@tonic-gate 	0,				/* dl_range_length */
2357c478bd9Sstevel@tonic-gate 	0,				/* dl_range_offset */
2367c478bd9Sstevel@tonic-gate 	DL_STYLE2,			/* dl_provider_style */
2377c478bd9Sstevel@tonic-gate 	sizeof (dl_info_ack_t),		/* dl_addr_offset */
2387c478bd9Sstevel@tonic-gate 	DL_VERSION_2,			/* dl_version */
2397c478bd9Sstevel@tonic-gate 	0,				/* dl_brdcst_addr_length */
2407c478bd9Sstevel@tonic-gate 	0,				/* dl_brdcst_addr_offset */
2417c478bd9Sstevel@tonic-gate 	0				/* dl_growth */
2427c478bd9Sstevel@tonic-gate };
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate  * sppp_dlpi_pinfoinit()
2467c478bd9Sstevel@tonic-gate  *
2477c478bd9Sstevel@tonic-gate  * Description:
2487c478bd9Sstevel@tonic-gate  *    Initialize dl_pinfo[], called from sppp_attach.
2497c478bd9Sstevel@tonic-gate  */
2507c478bd9Sstevel@tonic-gate void
sppp_dlpi_pinfoinit(void)2517c478bd9Sstevel@tonic-gate sppp_dlpi_pinfoinit(void)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate 	bzero(dl_pinfo, sizeof (dl_pinfo));	/* Just to be safe */
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_ATTACH_REQ].pi_minlen = sizeof (dl_attach_req_t);
2567c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_ATTACH_REQ].pi_state = DL_UNATTACHED;
2577c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_ATTACH_REQ].pi_funcp = sppp_dlattachreq;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_DETACH_REQ].pi_minlen = sizeof (dl_detach_req_t);
2607c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_DETACH_REQ].pi_state = DL_UNBOUND;
2617c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_DETACH_REQ].pi_funcp = sppp_dldetachreq;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_BIND_REQ].pi_minlen = sizeof (dl_bind_req_t);
2647c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_BIND_REQ].pi_state = DL_UNBOUND;
2657c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_BIND_REQ].pi_funcp = sppp_dlbindreq;
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_UNBIND_REQ].pi_minlen = sizeof (dl_unbind_req_t);
2687c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_UNBIND_REQ].pi_state = DL_IDLE;
2697c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_UNBIND_REQ].pi_funcp = sppp_dlunbindreq;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_INFO_REQ].pi_minlen = sizeof (dl_info_req_t);
272*f53eecf5SJames Carlson 	dl_pinfo[DL_INFO_REQ].pi_state = -1;	/* special handling */
2737c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_INFO_REQ].pi_funcp = sppp_dlinforeq;
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_UNITDATA_REQ].pi_minlen = sizeof (dl_unitdata_req_t);
2767c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_UNITDATA_REQ].pi_state = DL_IDLE;
2777c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_UNITDATA_REQ].pi_funcp = sppp_dlunitdatareq;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_PROMISCON_REQ].pi_minlen = sizeof (dl_promiscon_req_t);
280*f53eecf5SJames Carlson 	dl_pinfo[DL_PROMISCON_REQ].pi_state = -1; /* special handling */
2817c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_PROMISCON_REQ].pi_funcp = sppp_dlpromisconreq;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_PROMISCOFF_REQ].pi_minlen = sizeof (dl_promiscoff_req_t);
284*f53eecf5SJames Carlson 	dl_pinfo[DL_PROMISCOFF_REQ].pi_state = -1; /* special handling */
2857c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_PROMISCOFF_REQ].pi_funcp = sppp_dlpromiscoffreq;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_PHYS_ADDR_REQ].pi_minlen = sizeof (dl_phys_addr_req_t);
288*f53eecf5SJames Carlson 	dl_pinfo[DL_PHYS_ADDR_REQ].pi_state = -1; /* special handling */
2897c478bd9Sstevel@tonic-gate 	dl_pinfo[DL_PHYS_ADDR_REQ].pi_funcp = sppp_dlphyreq;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate  * sppp_mproto()
2947c478bd9Sstevel@tonic-gate  *
2957c478bd9Sstevel@tonic-gate  * MT-Perimeters:
2967c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
2977c478bd9Sstevel@tonic-gate  *
2987c478bd9Sstevel@tonic-gate  * Description:
2997c478bd9Sstevel@tonic-gate  *    Handle M_PCPROTO/M_PROTO messages, called by sppp_uwput.
3007c478bd9Sstevel@tonic-gate  */
3017c478bd9Sstevel@tonic-gate int
sppp_mproto(queue_t * q,mblk_t * mp,spppstr_t * sps)3027c478bd9Sstevel@tonic-gate sppp_mproto(queue_t *q, mblk_t *mp, spppstr_t *sps)
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate 	union DL_primitives *dlp;
3057c478bd9Sstevel@tonic-gate 	struct sppp_dlpi_pinfo_t *dpi;
3067c478bd9Sstevel@tonic-gate 	t_uscalar_t	prim;
3077c478bd9Sstevel@tonic-gate 	int		len;
3087c478bd9Sstevel@tonic-gate 	int		error = 0;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	ASSERT(!IS_SPS_CONTROL(sps));
3117c478bd9Sstevel@tonic-gate 	if ((len = MBLKL(mp)) < sizeof (t_uscalar_t)) {
3127c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "bad mproto: block length %d\n", len));
3137c478bd9Sstevel@tonic-gate 		merror(q, mp, EPROTO);
3147c478bd9Sstevel@tonic-gate 		return (0);
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 	dlp = (union DL_primitives *)mp->b_rptr;
3177c478bd9Sstevel@tonic-gate 	prim = dlp->dl_primitive;
3187c478bd9Sstevel@tonic-gate 	if (prim > DL_MAXPRIM) {
3197c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "bad mproto: primitive %d > %d\n", prim,
3207c478bd9Sstevel@tonic-gate 		    DL_MAXPRIM));
3217c478bd9Sstevel@tonic-gate 		error = DL_BADPRIM;
3227c478bd9Sstevel@tonic-gate 	} else {
3237c478bd9Sstevel@tonic-gate 		dpi = &dl_pinfo[prim];
3247c478bd9Sstevel@tonic-gate 		if (dpi->pi_funcp == NULL) {
3257c478bd9Sstevel@tonic-gate 			DBGERROR((CE_CONT,
3267c478bd9Sstevel@tonic-gate 			    "bad mproto: primitive %d not supported\n", prim));
3277c478bd9Sstevel@tonic-gate 			error = DL_NOTSUPPORTED;
3287c478bd9Sstevel@tonic-gate 		} else if (len < dpi->pi_minlen) {
3297c478bd9Sstevel@tonic-gate 			DBGERROR((CE_CONT,
3307c478bd9Sstevel@tonic-gate 			    "bad mproto: primitive len %d < %d\n", len,
3317c478bd9Sstevel@tonic-gate 			    dpi->pi_minlen));
3327c478bd9Sstevel@tonic-gate 			error = DL_BADPRIM;
333*f53eecf5SJames Carlson 		} else if (dpi->pi_state != -1 &&
334*f53eecf5SJames Carlson 		    sps->sps_dlstate != dpi->pi_state) {
3357c478bd9Sstevel@tonic-gate 			DBGERROR((CE_CONT,
3367c478bd9Sstevel@tonic-gate 			    "bad state %d != %d for primitive %d\n",
3377c478bd9Sstevel@tonic-gate 			    sps->sps_dlstate, dpi->pi_state, prim));
3387c478bd9Sstevel@tonic-gate 			error = DL_OUTSTATE;
3397c478bd9Sstevel@tonic-gate 		}
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 	if (error != 0) {
3427c478bd9Sstevel@tonic-gate 		dlerrorack(q, mp, dlp->dl_primitive, error, 0);
3437c478bd9Sstevel@tonic-gate 		return (0);
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
3467c478bd9Sstevel@tonic-gate 	{
3477c478bd9Sstevel@tonic-gate 		const char *cp = prim2name(prim);
3487c478bd9Sstevel@tonic-gate 		if (cp != NULL)
3497c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "/%d: Dispatching %s\n",
3507c478bd9Sstevel@tonic-gate 			    sps->sps_mn_id, cp);
3517c478bd9Sstevel@tonic-gate 		else
3527c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT,
3537c478bd9Sstevel@tonic-gate 			    "/%d: Dispatching unknown primitive %d\n",
3547c478bd9Sstevel@tonic-gate 			    sps->sps_mn_id, prim);
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate #endif
3577c478bd9Sstevel@tonic-gate 	return ((*dpi->pi_funcp)(q, mp, sps));
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate  * sppp_dlattachreq()
3627c478bd9Sstevel@tonic-gate  *
3637c478bd9Sstevel@tonic-gate  * MT-Perimeters:
3647c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
3657c478bd9Sstevel@tonic-gate  *
3667c478bd9Sstevel@tonic-gate  * Description:
3677c478bd9Sstevel@tonic-gate  *    Perform DL_ATTACH_REQ request, called by sppp_mproto.
3687c478bd9Sstevel@tonic-gate  */
3697c478bd9Sstevel@tonic-gate static int
sppp_dlattachreq(queue_t * q,mblk_t * mp,spppstr_t * sps)3707c478bd9Sstevel@tonic-gate sppp_dlattachreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate 	int	error = 0;
3737c478bd9Sstevel@tonic-gate 	union DL_primitives *dlp;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
3767c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
3777c478bd9Sstevel@tonic-gate 	dlp = (union DL_primitives *)mp->b_rptr;
3787c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
3797c478bd9Sstevel@tonic-gate 	ASSERT(sps->sps_dlstate == DL_UNATTACHED);
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	if (IS_SPS_PIOATTACH(sps)) {
3827c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI attach: already attached\n"));
3837c478bd9Sstevel@tonic-gate 		error = EINVAL;
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 	if (error != 0) {
3867c478bd9Sstevel@tonic-gate 		dlerrorack(q, mp, dlp->dl_primitive, DL_OUTSTATE, error);
3877c478bd9Sstevel@tonic-gate 	} else {
3887c478bd9Sstevel@tonic-gate 		qwriter(q, mp, sppp_dl_attach_upper, PERIM_OUTER);
3897c478bd9Sstevel@tonic-gate 	}
3907c478bd9Sstevel@tonic-gate 	return (0);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate /*
3947c478bd9Sstevel@tonic-gate  * sppp_dl_attach_upper()
3957c478bd9Sstevel@tonic-gate  *
3967c478bd9Sstevel@tonic-gate  * MT-Perimeters:
3977c478bd9Sstevel@tonic-gate  *    exclusive inner, exclusive outer.
3987c478bd9Sstevel@tonic-gate  *
3997c478bd9Sstevel@tonic-gate  * Description:
4007c478bd9Sstevel@tonic-gate  *    Called by qwriter (INNER) from sppp_dlattachreq as the result of
4017c478bd9Sstevel@tonic-gate  *    receiving a DL_ATTACH_REQ message.
4027c478bd9Sstevel@tonic-gate  */
4037c478bd9Sstevel@tonic-gate static void
sppp_dl_attach_upper(queue_t * q,mblk_t * mp)4047c478bd9Sstevel@tonic-gate sppp_dl_attach_upper(queue_t *q, mblk_t *mp)
4057c478bd9Sstevel@tonic-gate {
4067c478bd9Sstevel@tonic-gate 	sppa_t		*ppa;
407*f53eecf5SJames Carlson 	spppstr_t	*sps = q->q_ptr;
4087c478bd9Sstevel@tonic-gate 	union DL_primitives *dlp;
409*f53eecf5SJames Carlson 	int		err = ENOMEM;
410*f53eecf5SJames Carlson 	cred_t		*cr;
411*f53eecf5SJames Carlson 	zoneid_t	zoneid;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	ASSERT(!IS_SPS_PIOATTACH(sps));
4147c478bd9Sstevel@tonic-gate 	dlp = (union DL_primitives *)mp->b_rptr;
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	/* If there's something here, it's detached. */
4177c478bd9Sstevel@tonic-gate 	if (sps->sps_ppa != NULL) {
4187c478bd9Sstevel@tonic-gate 		sppp_remove_ppa(sps);
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate 
421*f53eecf5SJames Carlson 	if ((cr = msg_getcred(mp, NULL)) == NULL)
422*f53eecf5SJames Carlson 		zoneid = sps->sps_zoneid;
423*f53eecf5SJames Carlson 	else
424*f53eecf5SJames Carlson 		zoneid = crgetzoneid(cr);
425*f53eecf5SJames Carlson 
4267c478bd9Sstevel@tonic-gate 	ppa = sppp_find_ppa(dlp->attach_req.dl_ppa);
427*f53eecf5SJames Carlson 	if (ppa == NULL) {
428*f53eecf5SJames Carlson 		ppa = sppp_create_ppa(dlp->attach_req.dl_ppa, zoneid);
429*f53eecf5SJames Carlson 	} else if (ppa->ppa_zoneid != zoneid) {
430*f53eecf5SJames Carlson 		ppa = NULL;
431*f53eecf5SJames Carlson 		err = EPERM;
432*f53eecf5SJames Carlson 	}
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	/*
435*f53eecf5SJames Carlson 	 * If we can't find or create it, then it's either because we're out of
436*f53eecf5SJames Carlson 	 * memory or because the requested PPA is owned by a different zone.
4377c478bd9Sstevel@tonic-gate 	 */
4387c478bd9Sstevel@tonic-gate 	if (ppa == NULL) {
4397c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI attach: cannot create ppa %u\n",
4407c478bd9Sstevel@tonic-gate 		    dlp->attach_req.dl_ppa));
441*f53eecf5SJames Carlson 		dlerrorack(q, mp, dlp->dl_primitive, DL_SYSERR, err);
4427c478bd9Sstevel@tonic-gate 		return;
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate 	/*
4457c478bd9Sstevel@tonic-gate 	 * Preallocate the hangup message so that we're always able to
4467c478bd9Sstevel@tonic-gate 	 * send this upstream in the event of a catastrophic failure.
4477c478bd9Sstevel@tonic-gate 	 */
4487c478bd9Sstevel@tonic-gate 	if ((sps->sps_hangup = allocb(1, BPRI_MED)) == NULL) {
4497c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI attach: cannot allocate hangup\n"));
4507c478bd9Sstevel@tonic-gate 		dlerrorack(q, mp, dlp->dl_primitive, DL_SYSERR, ENOSR);
4517c478bd9Sstevel@tonic-gate 		return;
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 	sps->sps_dlstate = DL_UNBOUND;
4547c478bd9Sstevel@tonic-gate 	sps->sps_ppa = ppa;
4557c478bd9Sstevel@tonic-gate 	/*
4567c478bd9Sstevel@tonic-gate 	 * Add this stream to the head of the list of sibling streams
4577c478bd9Sstevel@tonic-gate 	 * which belong to the specified ppa.
4587c478bd9Sstevel@tonic-gate 	 */
4597c478bd9Sstevel@tonic-gate 	rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
4607c478bd9Sstevel@tonic-gate 	ppa->ppa_refcnt++;
4617c478bd9Sstevel@tonic-gate 	sps->sps_nextsib = ppa->ppa_streams;
4627c478bd9Sstevel@tonic-gate 	ppa->ppa_streams = sps;
4637c478bd9Sstevel@tonic-gate 	/*
4647c478bd9Sstevel@tonic-gate 	 * And if this stream was marked as promiscuous (SPS_PROMISC), then we
4657c478bd9Sstevel@tonic-gate 	 * need to update the promiscuous streams count. This should only
4667c478bd9Sstevel@tonic-gate 	 * happen when DL_PROMISCON_REQ was issued prior to attachment.
4677c478bd9Sstevel@tonic-gate 	 */
4687c478bd9Sstevel@tonic-gate 	if (IS_SPS_PROMISC(sps)) {
4697c478bd9Sstevel@tonic-gate 		ppa->ppa_promicnt++;
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 	rw_exit(&ppa->ppa_sib_lock);
4727c478bd9Sstevel@tonic-gate 	DBGDLPI((CE_CONT, "/%d: attached to ppa %d\n", sps->sps_mn_id,
4737c478bd9Sstevel@tonic-gate 	    ppa->ppa_ppa_id));
4747c478bd9Sstevel@tonic-gate 	dlokack(q, mp, DL_ATTACH_REQ);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate /*
4787c478bd9Sstevel@tonic-gate  * sppp_dldetachreq()
4797c478bd9Sstevel@tonic-gate  *
4807c478bd9Sstevel@tonic-gate  * MT-Perimeters:
4817c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
4827c478bd9Sstevel@tonic-gate  *
4837c478bd9Sstevel@tonic-gate  * Description:
4847c478bd9Sstevel@tonic-gate  *    Perform DL_DETACH_REQ request, called by sppp_mproto.
4857c478bd9Sstevel@tonic-gate  */
4867c478bd9Sstevel@tonic-gate /* ARGSUSED */
4877c478bd9Sstevel@tonic-gate static int
sppp_dldetachreq(queue_t * q,mblk_t * mp,spppstr_t * sps)4887c478bd9Sstevel@tonic-gate sppp_dldetachreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
4897c478bd9Sstevel@tonic-gate {
4907c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
4917c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
4927c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
4937c478bd9Sstevel@tonic-gate 	ASSERT(sps->sps_dlstate == DL_UNBOUND);
4947c478bd9Sstevel@tonic-gate 	ASSERT(!IS_SPS_PIOATTACH(sps));
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	qwriter(q, mp, sppp_dl_detach_upper, PERIM_INNER);
4977c478bd9Sstevel@tonic-gate 	return (0);
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate /*
5017c478bd9Sstevel@tonic-gate  * sppp_dl_detach_upper()
5027c478bd9Sstevel@tonic-gate  *
5037c478bd9Sstevel@tonic-gate  * MT-Perimeters:
5047c478bd9Sstevel@tonic-gate  *    exclusive inner, shared outer.
5057c478bd9Sstevel@tonic-gate  *
5067c478bd9Sstevel@tonic-gate  * Description:
5077c478bd9Sstevel@tonic-gate  *    Called by qwriter (INNER) from sppp_dldetachreq as the result of
5087c478bd9Sstevel@tonic-gate  *    receiving a DL_DETACH_REQ message.
5097c478bd9Sstevel@tonic-gate  */
5107c478bd9Sstevel@tonic-gate /* ARGSUSED */
5117c478bd9Sstevel@tonic-gate static void
sppp_dl_detach_upper(queue_t * q,mblk_t * mp)5127c478bd9Sstevel@tonic-gate sppp_dl_detach_upper(queue_t *q, mblk_t *mp)
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate 	spppstr_t	*sps;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
5177c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
5187c478bd9Sstevel@tonic-gate 	sps = (spppstr_t *)q->q_ptr;
5197c478bd9Sstevel@tonic-gate 	/*
5207c478bd9Sstevel@tonic-gate 	 * We don't actually detach from the PPA until closed or
5217c478bd9Sstevel@tonic-gate 	 * reattached.
5227c478bd9Sstevel@tonic-gate 	 */
5237c478bd9Sstevel@tonic-gate 	sps->sps_flags &= ~SPS_PROMISC;	/* clear flag anyway */
5247c478bd9Sstevel@tonic-gate 	sps->sps_dlstate = DL_UNATTACHED;
5257c478bd9Sstevel@tonic-gate 	dlokack(q, mp, DL_DETACH_REQ);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate  * sppp_dlbindreq()
5307c478bd9Sstevel@tonic-gate  *
5317c478bd9Sstevel@tonic-gate  * MT-Perimeters:
5327c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
5337c478bd9Sstevel@tonic-gate  *
5347c478bd9Sstevel@tonic-gate  * Description:
5357c478bd9Sstevel@tonic-gate  *    Perform DL_BIND_REQ request, called by sppp_mproto.
5367c478bd9Sstevel@tonic-gate  */
5377c478bd9Sstevel@tonic-gate static int
sppp_dlbindreq(queue_t * q,mblk_t * mp,spppstr_t * sps)5387c478bd9Sstevel@tonic-gate sppp_dlbindreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
5397c478bd9Sstevel@tonic-gate {
5407c478bd9Sstevel@tonic-gate 	sppa_t			*ppa;
5417c478bd9Sstevel@tonic-gate 	union DL_primitives	*dlp;
5427c478bd9Sstevel@tonic-gate 	spppreqsap_t		req_sap;
5437c478bd9Sstevel@tonic-gate 	int			error = 0;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
5467c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
5477c478bd9Sstevel@tonic-gate 	dlp = (union DL_primitives *)mp->b_rptr;
5487c478bd9Sstevel@tonic-gate 	req_sap = dlp->bind_req.dl_sap;
5497c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
5507c478bd9Sstevel@tonic-gate 	ASSERT(!IS_SPS_PIOATTACH(sps));
5517c478bd9Sstevel@tonic-gate 	ASSERT(sps->sps_dlstate == DL_UNBOUND);
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	ppa = sps->sps_ppa;
5547c478bd9Sstevel@tonic-gate 	if (ppa == NULL) {
5557c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI bind: no attached ppa\n"));
5567c478bd9Sstevel@tonic-gate 		error = DL_OUTSTATE;
5577c478bd9Sstevel@tonic-gate 	} else if ((req_sap != ETHERTYPE_IP) && (req_sap != ETHERTYPE_IPV6) &&
558*f53eecf5SJames Carlson 	    (req_sap != ETHERTYPE_ALLSAP)) {
5597c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI bind: unknown SAP %x\n", req_sap));
5607c478bd9Sstevel@tonic-gate 		error = DL_BADADDR;
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 	if (error != 0) {
5637c478bd9Sstevel@tonic-gate 		dlerrorack(q, mp, dlp->dl_primitive, error, 0);
5647c478bd9Sstevel@tonic-gate 	} else {
5657c478bd9Sstevel@tonic-gate 		qwriter(q, mp, sppp_dl_bind, PERIM_INNER);
5667c478bd9Sstevel@tonic-gate 	}
5677c478bd9Sstevel@tonic-gate 	return (0);
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate /*
5717c478bd9Sstevel@tonic-gate  * sppp_dl_bind()
5727c478bd9Sstevel@tonic-gate  *
5737c478bd9Sstevel@tonic-gate  * MT-Perimeters:
5747c478bd9Sstevel@tonic-gate  *    exclusive inner, shared outer.
5757c478bd9Sstevel@tonic-gate  *
5767c478bd9Sstevel@tonic-gate  * Description:
5777c478bd9Sstevel@tonic-gate  *    Called by qwriter (INNER) from sppp_dlbindreq as the result of
5787c478bd9Sstevel@tonic-gate  *    receiving a DL_BIND_REQ message.
5797c478bd9Sstevel@tonic-gate  */
5807c478bd9Sstevel@tonic-gate static void
sppp_dl_bind(queue_t * q,mblk_t * mp)5817c478bd9Sstevel@tonic-gate sppp_dl_bind(queue_t *q, mblk_t *mp)
5827c478bd9Sstevel@tonic-gate {
5837c478bd9Sstevel@tonic-gate 	spppstr_t		*sps;
5847c478bd9Sstevel@tonic-gate 	sppa_t			*ppa;
5857c478bd9Sstevel@tonic-gate 	union DL_primitives	*dlp;
5867c478bd9Sstevel@tonic-gate 	t_scalar_t		sap;
5877c478bd9Sstevel@tonic-gate 	spppreqsap_t		req_sap;
5887c478bd9Sstevel@tonic-gate 	mblk_t			*lsmp;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
5917c478bd9Sstevel@tonic-gate 	sps = (spppstr_t *)q->q_ptr;
5927c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
5937c478bd9Sstevel@tonic-gate 	dlp = (union DL_primitives *)mp->b_rptr;
5947c478bd9Sstevel@tonic-gate 	ppa = sps->sps_ppa;
5957c478bd9Sstevel@tonic-gate 	ASSERT(ppa != NULL);
5967c478bd9Sstevel@tonic-gate 	req_sap = dlp->bind_req.dl_sap;
5977c478bd9Sstevel@tonic-gate 	ASSERT((req_sap == ETHERTYPE_IP) || (req_sap == ETHERTYPE_IPV6) ||
598*f53eecf5SJames Carlson 	    (req_sap == ETHERTYPE_ALLSAP));
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	if (req_sap == ETHERTYPE_IP) {
6017c478bd9Sstevel@tonic-gate 		sap = PPP_IP;
6027c478bd9Sstevel@tonic-gate 	} else if (req_sap == ETHERTYPE_IPV6) {
6037c478bd9Sstevel@tonic-gate 		sap = PPP_IPV6;
6047c478bd9Sstevel@tonic-gate 	} else if (req_sap == ETHERTYPE_ALLSAP) {
6057c478bd9Sstevel@tonic-gate 		sap = PPP_ALLSAP;
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate 	/*
6087c478bd9Sstevel@tonic-gate 	 * If there's another stream with the same sap has already been bound
6097c478bd9Sstevel@tonic-gate 	 * to the same ppa, then return with DL_NOADDR. However, we do make an
6107c478bd9Sstevel@tonic-gate 	 * exception for snoop (req_sap=0x00, sap=0xff) since multiple
6117c478bd9Sstevel@tonic-gate 	 * instances of snoop may execute an a given device.
6127c478bd9Sstevel@tonic-gate 	 */
6137c478bd9Sstevel@tonic-gate 	lsmp = NULL;
6147c478bd9Sstevel@tonic-gate 	if (sap != PPP_ALLSAP) {
6157c478bd9Sstevel@tonic-gate 		if ((sap == PPP_IP) && (ppa->ppa_ip_cache == NULL)) {
6167c478bd9Sstevel@tonic-gate 			ppa->ppa_ip_cache = sps;
6177c478bd9Sstevel@tonic-gate 			if (ppa->ppa_ctl != NULL) {
6187c478bd9Sstevel@tonic-gate 				lsmp = create_lsmsg(PPP_LINKSTAT_IPV4_BOUND);
6197c478bd9Sstevel@tonic-gate 			}
6207c478bd9Sstevel@tonic-gate 		} else if ((sap == PPP_IPV6) && (ppa->ppa_ip6_cache == NULL)) {
6217c478bd9Sstevel@tonic-gate 			ppa->ppa_ip6_cache = sps;
6227c478bd9Sstevel@tonic-gate 			if (ppa->ppa_ctl != NULL) {
6237c478bd9Sstevel@tonic-gate 				lsmp = create_lsmsg(PPP_LINKSTAT_IPV6_BOUND);
6247c478bd9Sstevel@tonic-gate 			}
6257c478bd9Sstevel@tonic-gate 		} else {
6267c478bd9Sstevel@tonic-gate 			DBGERROR((CE_CONT, "DLPI bind: bad SAP %x\n", sap));
6277c478bd9Sstevel@tonic-gate 			dlerrorack(q, mp, dlp->dl_primitive, DL_NOADDR,
6287c478bd9Sstevel@tonic-gate 			    EEXIST);
6297c478bd9Sstevel@tonic-gate 			return;
6307c478bd9Sstevel@tonic-gate 		}
6317c478bd9Sstevel@tonic-gate 		sps->sps_flags |= SPS_CACHED;
6327c478bd9Sstevel@tonic-gate 	}
6337c478bd9Sstevel@tonic-gate 	/*
6347c478bd9Sstevel@tonic-gate 	 * Tell the daemon that a DLPI bind has happened on this stream,
6357c478bd9Sstevel@tonic-gate 	 * and we'll only do this for PPP_IP or PPP_IPV6 sap (not snoop).
6367c478bd9Sstevel@tonic-gate 	 */
6377c478bd9Sstevel@tonic-gate 	if (lsmp != NULL && ppa->ppa_ctl != NULL) {
6387c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
6397c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "sending up %s\n",
6407c478bd9Sstevel@tonic-gate 		    ((sap == PPP_IP) ? "PPP_LINKSTAT_IPV4_BOUND" :
6417c478bd9Sstevel@tonic-gate 		    "PPP_LINKSTAT_IPV6_BOUND"));
6427c478bd9Sstevel@tonic-gate #endif
6437c478bd9Sstevel@tonic-gate 		putnext(ppa->ppa_ctl->sps_rq, lsmp);
6447c478bd9Sstevel@tonic-gate 	}
6457c478bd9Sstevel@tonic-gate 	DBGDLPI((CE_CONT, "/%d: bound to sap %X (req %X)\n", sps->sps_mn_id,
6467c478bd9Sstevel@tonic-gate 	    sap, req_sap));
6477c478bd9Sstevel@tonic-gate 	sps->sps_req_sap = req_sap;
6487c478bd9Sstevel@tonic-gate 	sps->sps_sap = sap;
6497c478bd9Sstevel@tonic-gate 	sps->sps_dlstate = DL_IDLE;
6507c478bd9Sstevel@tonic-gate 	dlbindack(q, mp, req_sap, &sap, sizeof (int32_t), 0, 0);
6517c478bd9Sstevel@tonic-gate }
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate /*
6547c478bd9Sstevel@tonic-gate  * sppp_dlunbindreq()
6557c478bd9Sstevel@tonic-gate  *
6567c478bd9Sstevel@tonic-gate  * MT-Perimeters:
6577c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
6587c478bd9Sstevel@tonic-gate  *
6597c478bd9Sstevel@tonic-gate  * Description:
6607c478bd9Sstevel@tonic-gate  *    Perform DL_UNBIND_REQ request, called by sppp_mproto.
6617c478bd9Sstevel@tonic-gate  */
6627c478bd9Sstevel@tonic-gate /* ARGSUSED */
6637c478bd9Sstevel@tonic-gate static int
sppp_dlunbindreq(queue_t * q,mblk_t * mp,spppstr_t * sps)6647c478bd9Sstevel@tonic-gate sppp_dlunbindreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
6677c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
6687c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
6697c478bd9Sstevel@tonic-gate 	ASSERT(!IS_SPS_PIOATTACH(sps));
6707c478bd9Sstevel@tonic-gate 	ASSERT(sps->sps_dlstate == DL_IDLE);
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	qwriter(q, mp, sppp_dl_unbind, PERIM_INNER);
6737c478bd9Sstevel@tonic-gate 	return (0);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate  * sppp_dl_unbind()
6787c478bd9Sstevel@tonic-gate  *
6797c478bd9Sstevel@tonic-gate  * MT-Perimeters:
6807c478bd9Sstevel@tonic-gate  *    exclusive inner, shared outer.
6817c478bd9Sstevel@tonic-gate  *
6827c478bd9Sstevel@tonic-gate  * Description:
6837c478bd9Sstevel@tonic-gate  *    Called by qwriter (INNER) from sppp_dlunbindreq as the result of
6847c478bd9Sstevel@tonic-gate  *    receiving a DL_UNBIND_REQ message.
6857c478bd9Sstevel@tonic-gate  */
6867c478bd9Sstevel@tonic-gate static void
sppp_dl_unbind(queue_t * q,mblk_t * mp)6877c478bd9Sstevel@tonic-gate sppp_dl_unbind(queue_t *q, mblk_t *mp)
6887c478bd9Sstevel@tonic-gate {
6897c478bd9Sstevel@tonic-gate 	spppstr_t	*sps;
6907c478bd9Sstevel@tonic-gate 	sppa_t		*ppa;
6917c478bd9Sstevel@tonic-gate 	t_scalar_t	sap;
6927c478bd9Sstevel@tonic-gate 	mblk_t		*msg;
6937c478bd9Sstevel@tonic-gate 	boolean_t	saydown;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
6967c478bd9Sstevel@tonic-gate 	sps = (spppstr_t *)q->q_ptr;
6977c478bd9Sstevel@tonic-gate 	ppa = sps->sps_ppa;
6987c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
6997c478bd9Sstevel@tonic-gate 	sap = sps->sps_sap;
7007c478bd9Sstevel@tonic-gate 	ASSERT((sap == PPP_IP) || (sap == PPP_IPV6) || (sap == PPP_ALLSAP));
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	/* Flush messages on unbind, per DLPI specification. */
7037c478bd9Sstevel@tonic-gate 	flushq(WR(q), FLUSHALL);
7047c478bd9Sstevel@tonic-gate 	flushq(RD(q), FLUSHALL);
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	if ((ppa != NULL) && IS_SPS_CACHED(sps)) {
7077c478bd9Sstevel@tonic-gate 		sps->sps_flags &= ~SPS_CACHED;
7087c478bd9Sstevel@tonic-gate 		msg = NULL;
7097c478bd9Sstevel@tonic-gate 		saydown = (ppa->ppa_ctl != NULL &&
7107c478bd9Sstevel@tonic-gate 		    (sps->sps_npmode == NPMODE_PASS ||
711*f53eecf5SJames Carlson 		    sps->sps_npmode == NPMODE_QUEUE));
7127c478bd9Sstevel@tonic-gate 		if (sap == PPP_IP) {
7137c478bd9Sstevel@tonic-gate 			ppa->ppa_ip_cache = NULL;
7147c478bd9Sstevel@tonic-gate 			if (saydown)
7157c478bd9Sstevel@tonic-gate 				msg = create_lsmsg(PPP_LINKSTAT_IPV4_UNBOUND);
7167c478bd9Sstevel@tonic-gate 		} else if (sap == PPP_IPV6) {
7177c478bd9Sstevel@tonic-gate 			ppa->ppa_ip6_cache = NULL;
7187c478bd9Sstevel@tonic-gate 			if (saydown)
7197c478bd9Sstevel@tonic-gate 				msg = create_lsmsg(PPP_LINKSTAT_IPV6_UNBOUND);
7207c478bd9Sstevel@tonic-gate 		}
7217c478bd9Sstevel@tonic-gate 		if (msg != NULL) {
7227c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
7237c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "sending up %s\n",
7247c478bd9Sstevel@tonic-gate 			    ((sap == PPP_IP) ? "PPP_LINKSTAT_IPV4_UNBOUND" :
7257c478bd9Sstevel@tonic-gate 			    "PPP_LINKSTAT_IPV6_UNBOUND"));
7267c478bd9Sstevel@tonic-gate #endif
7277c478bd9Sstevel@tonic-gate 			putnext(ppa->ppa_ctl->sps_rq, msg);
7287c478bd9Sstevel@tonic-gate 		}
7297c478bd9Sstevel@tonic-gate 	}
7307c478bd9Sstevel@tonic-gate 	DBGDLPI((CE_CONT, "/%d: unbound from sap %X (req %X)\n", sps->sps_mn_id,
7317c478bd9Sstevel@tonic-gate 	    sps->sps_sap, sps->sps_req_sap));
7327c478bd9Sstevel@tonic-gate 	sps->sps_req_sap = 0;
7337c478bd9Sstevel@tonic-gate 	sps->sps_sap = -1;
7347c478bd9Sstevel@tonic-gate 	sps->sps_dlstate = DL_UNBOUND;
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	dlokack(q, mp, DL_UNBIND_REQ);
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate /*
7407c478bd9Sstevel@tonic-gate  * sppp_dlinforeq()
7417c478bd9Sstevel@tonic-gate  *
7427c478bd9Sstevel@tonic-gate  * MT-Perimeters:
7437c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
7447c478bd9Sstevel@tonic-gate  *
7457c478bd9Sstevel@tonic-gate  * Description:
7467c478bd9Sstevel@tonic-gate  *    Perform DL_INFO_REQ request, called by sppp_mproto.
7477c478bd9Sstevel@tonic-gate  */
7487c478bd9Sstevel@tonic-gate static int
sppp_dlinforeq(queue_t * q,mblk_t * mp,spppstr_t * sps)7497c478bd9Sstevel@tonic-gate sppp_dlinforeq(queue_t *q, mblk_t *mp, spppstr_t *sps)
7507c478bd9Sstevel@tonic-gate {
7517c478bd9Sstevel@tonic-gate 	dl_info_ack_t	*dlip;
7527c478bd9Sstevel@tonic-gate 	uint32_t	size;
7537c478bd9Sstevel@tonic-gate 	uint32_t	addr_size;
7547c478bd9Sstevel@tonic-gate 	sppa_t		*ppa;
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
7577c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
7587c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
7597c478bd9Sstevel@tonic-gate 	ppa = sps->sps_ppa;
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	/* Exchange current msg for a DL_INFO_ACK. */
7627c478bd9Sstevel@tonic-gate 	addr_size = SPPP_ADDRL;
7637c478bd9Sstevel@tonic-gate 	size = sizeof (dl_info_ack_t) + addr_size;
7647c478bd9Sstevel@tonic-gate 	if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL) {
7657c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI info: mexchange failed\n"));
7667c478bd9Sstevel@tonic-gate 		/* mexchange already sent up an merror ENOSR */
7677c478bd9Sstevel@tonic-gate 		return (0);
7687c478bd9Sstevel@tonic-gate 	}
7697c478bd9Sstevel@tonic-gate 	/* Fill in DL_INFO_ACK fields and reply */
7707c478bd9Sstevel@tonic-gate 	dlip = (dl_info_ack_t *)mp->b_rptr;
7717c478bd9Sstevel@tonic-gate 	*dlip = sppp_infoack;
7727c478bd9Sstevel@tonic-gate 	dlip->dl_current_state = sps->sps_dlstate;
7737c478bd9Sstevel@tonic-gate 	dlip->dl_max_sdu = ppa != NULL ? ppa->ppa_mtu : PPP_MAXMTU;
7747c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
7757c478bd9Sstevel@tonic-gate 	{
7767c478bd9Sstevel@tonic-gate 		const char *cp = state2name(dlip->dl_current_state);
7777c478bd9Sstevel@tonic-gate 		if (cp != NULL)
7787c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "info returns state %s, max sdu %d\n",
7797c478bd9Sstevel@tonic-gate 			    cp, dlip->dl_max_sdu);
7807c478bd9Sstevel@tonic-gate 		else
7817c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "info returns state %d, max sdu %d\n",
7827c478bd9Sstevel@tonic-gate 			    dlip->dl_current_state, dlip->dl_max_sdu);
7837c478bd9Sstevel@tonic-gate 	}
7847c478bd9Sstevel@tonic-gate #endif
7857c478bd9Sstevel@tonic-gate 	qreply(q, mp);
7867c478bd9Sstevel@tonic-gate 	return (0);
7877c478bd9Sstevel@tonic-gate }
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate /*
7907c478bd9Sstevel@tonic-gate  * sppp_dlunitdatareq()
7917c478bd9Sstevel@tonic-gate  *
7927c478bd9Sstevel@tonic-gate  * MT-Perimeters:
7937c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
7947c478bd9Sstevel@tonic-gate  *
7957c478bd9Sstevel@tonic-gate  * Description:
7967c478bd9Sstevel@tonic-gate  *    Handle DL_UNITDATA_REQ request, called by sppp_mproto. This procedure
7977c478bd9Sstevel@tonic-gate  *    gets called for M_PROTO (DLPI) style of transmission. The fact that we
7987c478bd9Sstevel@tonic-gate  *    have acknowledged IP's fastpath probing (DL_IOC_HDR_INFO) does not
7997c478bd9Sstevel@tonic-gate  *    guarantee that IP will always transmit via M_DATA, and it merely implies
8007c478bd9Sstevel@tonic-gate  *    that such situation _may_ happen. In other words, IP may decide to use
8017c478bd9Sstevel@tonic-gate  *    M_PROTO (DLPI) for data transmission should it decide to do so.
8027c478bd9Sstevel@tonic-gate  *    Therefore, we should never place any restrictions or checks against
8037c478bd9Sstevel@tonic-gate  *    streams marked with SPS_FASTPATH, since it is legal for this procedure
8047c478bd9Sstevel@tonic-gate  *    to be entered with or without the bit set.
8057c478bd9Sstevel@tonic-gate  */
8067c478bd9Sstevel@tonic-gate static int
sppp_dlunitdatareq(queue_t * q,mblk_t * mp,spppstr_t * sps)8077c478bd9Sstevel@tonic-gate sppp_dlunitdatareq(queue_t *q, mblk_t *mp, spppstr_t *sps)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate 	sppa_t		*ppa;
8107c478bd9Sstevel@tonic-gate 	mblk_t		*hdrmp;
8117c478bd9Sstevel@tonic-gate 	mblk_t		*pktmp;
8127c478bd9Sstevel@tonic-gate 	dl_unitdata_req_t *dludp;
8137c478bd9Sstevel@tonic-gate 	int		dladdroff;
8147c478bd9Sstevel@tonic-gate 	int		dladdrlen;
8157c478bd9Sstevel@tonic-gate 	int		msize;
8167c478bd9Sstevel@tonic-gate 	int		error = 0;
8177c478bd9Sstevel@tonic-gate 	boolean_t	is_promisc;
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
8207c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
8217c478bd9Sstevel@tonic-gate 	ASSERT((MTYPE(mp) == M_PCPROTO) || (MTYPE(mp) == M_PROTO));
8227c478bd9Sstevel@tonic-gate 	dludp = (dl_unitdata_req_t *)mp->b_rptr;
8237c478bd9Sstevel@tonic-gate 	dladdroff = dludp->dl_dest_addr_offset;
8247c478bd9Sstevel@tonic-gate 	dladdrlen = dludp->dl_dest_addr_length;
8257c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
8267c478bd9Sstevel@tonic-gate 	ASSERT(!IS_SPS_PIOATTACH(sps));
8277c478bd9Sstevel@tonic-gate 	ASSERT(sps->sps_dlstate == DL_IDLE);
8287c478bd9Sstevel@tonic-gate 	ASSERT(q->q_ptr == sps);
8297c478bd9Sstevel@tonic-gate 	/*
8307c478bd9Sstevel@tonic-gate 	 * If this stream is not attached to any ppas, then discard data
8317c478bd9Sstevel@tonic-gate 	 * coming down through this stream.
8327c478bd9Sstevel@tonic-gate 	 */
8337c478bd9Sstevel@tonic-gate 	ppa = sps->sps_ppa;
8347c478bd9Sstevel@tonic-gate 	if (ppa == NULL) {
8357c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI unitdata: no attached ppa\n"));
8367c478bd9Sstevel@tonic-gate 		error = ENOLINK;
8377c478bd9Sstevel@tonic-gate 	} else if (mp->b_cont == NULL) {
8387c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI unitdata: missing data\n"));
8397c478bd9Sstevel@tonic-gate 		error = EPROTO;
8407c478bd9Sstevel@tonic-gate 	}
8417c478bd9Sstevel@tonic-gate 	if (error != 0) {
8427c478bd9Sstevel@tonic-gate 		dluderrorind(q, mp, mp->b_rptr + dladdroff, dladdrlen,
8437c478bd9Sstevel@tonic-gate 		    DL_BADDATA, error);
8447c478bd9Sstevel@tonic-gate 		return (0);
8457c478bd9Sstevel@tonic-gate 	}
8467c478bd9Sstevel@tonic-gate 	ASSERT(mp->b_cont->b_rptr != NULL);
8477c478bd9Sstevel@tonic-gate 	/*
8487c478bd9Sstevel@tonic-gate 	 * Check if outgoing packet size is larger than allowed. We use
8497c478bd9Sstevel@tonic-gate 	 * msgdsize to count all of M_DATA blocks in the message.
8507c478bd9Sstevel@tonic-gate 	 */
8517c478bd9Sstevel@tonic-gate 	msize = msgdsize(mp);
8527c478bd9Sstevel@tonic-gate 	if (msize > ppa->ppa_mtu) {
8537c478bd9Sstevel@tonic-gate 		/* Log, and send it anyway */
8547c478bd9Sstevel@tonic-gate 		mutex_enter(&ppa->ppa_sta_lock);
8557c478bd9Sstevel@tonic-gate 		ppa->ppa_otoolongs++;
8567c478bd9Sstevel@tonic-gate 		mutex_exit(&ppa->ppa_sta_lock);
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate 	if (IS_SPS_KDEBUG(sps)) {
8597c478bd9Sstevel@tonic-gate 		SPDEBUG(PPP_DRV_NAME
8607c478bd9Sstevel@tonic-gate 		    "/%d: DL_UNITDATA_REQ (%d bytes) sps=0x%p flags=0x%b "
8617c478bd9Sstevel@tonic-gate 		    "ppa=0x%p flags=0x%b\n", sps->sps_mn_id, msize,
8627c478bd9Sstevel@tonic-gate 		    (void *)sps, sps->sps_flags, SPS_FLAGS_STR,
8637c478bd9Sstevel@tonic-gate 		    (void *)ppa, ppa->ppa_flags, PPA_FLAGS_STR);
8647c478bd9Sstevel@tonic-gate 	}
8657c478bd9Sstevel@tonic-gate 	/* Allocate a message (M_DATA) to contain PPP header bytes. */
8667c478bd9Sstevel@tonic-gate 	if ((hdrmp = allocb(PPP_HDRLEN, BPRI_MED)) == NULL) {
8677c478bd9Sstevel@tonic-gate 		mutex_enter(&ppa->ppa_sta_lock);
8687c478bd9Sstevel@tonic-gate 		ppa->ppa_allocbfail++;
8697c478bd9Sstevel@tonic-gate 		mutex_exit(&ppa->ppa_sta_lock);
8707c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT,
8717c478bd9Sstevel@tonic-gate 		    "DLPI unitdata: can't allocate header buffer\n"));
8727c478bd9Sstevel@tonic-gate 		dluderrorind(q, mp, mp->b_rptr + dladdroff, dladdrlen,
8737c478bd9Sstevel@tonic-gate 		    DL_SYSERR, ENOSR);
8747c478bd9Sstevel@tonic-gate 		return (0);
8757c478bd9Sstevel@tonic-gate 	}
8767c478bd9Sstevel@tonic-gate 	/*
8777c478bd9Sstevel@tonic-gate 	 * Should there be any promiscuous stream(s), send the data up
8787c478bd9Sstevel@tonic-gate 	 * for each promiscuous stream that we recognize.
8797c478bd9Sstevel@tonic-gate 	 */
8807c478bd9Sstevel@tonic-gate 	rw_enter(&ppa->ppa_sib_lock, RW_READER);
8817c478bd9Sstevel@tonic-gate 	is_promisc = ppa->ppa_promicnt;
8827c478bd9Sstevel@tonic-gate 	if (is_promisc) {
8837c478bd9Sstevel@tonic-gate 		ASSERT(ppa->ppa_streams != NULL);
8847c478bd9Sstevel@tonic-gate 		sppp_dlprsendup(ppa->ppa_streams, mp->b_cont, sps->sps_sap,
8857c478bd9Sstevel@tonic-gate 		    B_FALSE);
8867c478bd9Sstevel@tonic-gate 	}
8877c478bd9Sstevel@tonic-gate 	rw_exit(&ppa->ppa_sib_lock);
8887c478bd9Sstevel@tonic-gate 	/* Discard DLPI header and keep only IP payload (mp->b_cont). */
8897c478bd9Sstevel@tonic-gate 	pktmp = mp->b_cont;
8907c478bd9Sstevel@tonic-gate 	mp->b_cont = NULL;
8917c478bd9Sstevel@tonic-gate 	freemsg(mp);
8927c478bd9Sstevel@tonic-gate 	mp = hdrmp;
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 	*(uchar_t *)mp->b_wptr++ = PPP_ALLSTATIONS;
8957c478bd9Sstevel@tonic-gate 	*(uchar_t *)mp->b_wptr++ = PPP_UI;
8967c478bd9Sstevel@tonic-gate 	*(uchar_t *)mp->b_wptr++ = ((uint16_t)sps->sps_sap >> 8) & 0xff;
8977c478bd9Sstevel@tonic-gate 	*(uchar_t *)mp->b_wptr++ = ((uint16_t)sps->sps_sap) & 0xff;
8987c478bd9Sstevel@tonic-gate 	ASSERT(MBLKL(mp) == PPP_HDRLEN);
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 	linkb(mp, pktmp);
9017c478bd9Sstevel@tonic-gate 	/*
9027c478bd9Sstevel@tonic-gate 	 * Only time-stamp the packet with hrtime if the upper stream
9037c478bd9Sstevel@tonic-gate 	 * is configured to do so.
9047c478bd9Sstevel@tonic-gate 	 */
9057c478bd9Sstevel@tonic-gate 	if (IS_PPA_TIMESTAMP(ppa)) {
9067c478bd9Sstevel@tonic-gate 		ppa->ppa_lasttx = gethrtime();
9077c478bd9Sstevel@tonic-gate 	}
9087c478bd9Sstevel@tonic-gate 	/*
9097c478bd9Sstevel@tonic-gate 	 * Just put this back on the queue and allow the write service
9107c478bd9Sstevel@tonic-gate 	 * routine to handle it.  We're nested too deeply here to
9117c478bd9Sstevel@tonic-gate 	 * rewind the stack sufficiently to prevent overflow.  This is
9127c478bd9Sstevel@tonic-gate 	 * the slow path anyway.
9137c478bd9Sstevel@tonic-gate 	 */
9147c478bd9Sstevel@tonic-gate 	if (putq(q, mp) == 0) {
9157c478bd9Sstevel@tonic-gate 		mutex_enter(&ppa->ppa_sta_lock);
9167c478bd9Sstevel@tonic-gate 		ppa->ppa_oqdropped++;
9177c478bd9Sstevel@tonic-gate 		mutex_exit(&ppa->ppa_sta_lock);
9187c478bd9Sstevel@tonic-gate 		freemsg(mp);
9197c478bd9Sstevel@tonic-gate 	} else {
9207c478bd9Sstevel@tonic-gate 		qenable(q);
9217c478bd9Sstevel@tonic-gate 	}
9227c478bd9Sstevel@tonic-gate 	return (0);
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate /*
9267c478bd9Sstevel@tonic-gate  * sppp_dlpromisconreq()
9277c478bd9Sstevel@tonic-gate  *
9287c478bd9Sstevel@tonic-gate  * MT-Perimeters:
9297c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
9307c478bd9Sstevel@tonic-gate  *
9317c478bd9Sstevel@tonic-gate  * Description:
9327c478bd9Sstevel@tonic-gate  *    Perform DL_PROMISCON_REQ request, called by sppp_mproto.
9337c478bd9Sstevel@tonic-gate  */
9347c478bd9Sstevel@tonic-gate static int
sppp_dlpromisconreq(queue_t * q,mblk_t * mp,spppstr_t * sps)9357c478bd9Sstevel@tonic-gate sppp_dlpromisconreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
9367c478bd9Sstevel@tonic-gate {
9377c478bd9Sstevel@tonic-gate 	t_uscalar_t	level;
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
9407c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
9417c478bd9Sstevel@tonic-gate 	level = ((dl_promiscon_req_t *)mp->b_rptr)->dl_level;
9427c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	/* snoop issues DL_PROMISCON_REQ more than once. */
9457c478bd9Sstevel@tonic-gate 	if (IS_SPS_PROMISC(sps)) {
9467c478bd9Sstevel@tonic-gate 		dlokack(q, mp, DL_PROMISCON_REQ);
9477c478bd9Sstevel@tonic-gate 	} else if ((level != DL_PROMISC_PHYS) && (level != DL_PROMISC_SAP) &&
9487c478bd9Sstevel@tonic-gate 	    (level != DL_PROMISC_MULTI)) {
9497c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI promiscon: bad level %d\n", level));
9507c478bd9Sstevel@tonic-gate 		dlerrorack(q, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
9517c478bd9Sstevel@tonic-gate 	} else {
9527c478bd9Sstevel@tonic-gate 		qwriter(q, mp, sppp_dl_promiscon, PERIM_INNER);
9537c478bd9Sstevel@tonic-gate 	}
9547c478bd9Sstevel@tonic-gate 	return (0);
9557c478bd9Sstevel@tonic-gate }
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate /*
9587c478bd9Sstevel@tonic-gate  * sppp_dl_promiscon()
9597c478bd9Sstevel@tonic-gate  *
9607c478bd9Sstevel@tonic-gate  * MT-Perimeters:
9617c478bd9Sstevel@tonic-gate  *    exclusive inner, shared outer.
9627c478bd9Sstevel@tonic-gate  *
9637c478bd9Sstevel@tonic-gate  * Description:
9647c478bd9Sstevel@tonic-gate  *    Called by qwriter (INNER) from sppp_dlpromisconreq as the result of
9657c478bd9Sstevel@tonic-gate  *    receiving a DL_PROMISCON_REQ message.
9667c478bd9Sstevel@tonic-gate  */
9677c478bd9Sstevel@tonic-gate static void
sppp_dl_promiscon(queue_t * q,mblk_t * mp)9687c478bd9Sstevel@tonic-gate sppp_dl_promiscon(queue_t *q, mblk_t *mp)
9697c478bd9Sstevel@tonic-gate {
9707c478bd9Sstevel@tonic-gate 	spppstr_t	*sps;
9717c478bd9Sstevel@tonic-gate 	sppa_t		*ppa;
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
9747c478bd9Sstevel@tonic-gate 	sps = (spppstr_t *)q->q_ptr;
9757c478bd9Sstevel@tonic-gate 	ASSERT(!IS_SPS_PROMISC(sps));
9767c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
9777c478bd9Sstevel@tonic-gate 	ppa = sps->sps_ppa;
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	sps->sps_flags |= SPS_PROMISC;
9807c478bd9Sstevel@tonic-gate 	/*
9817c478bd9Sstevel@tonic-gate 	 * We can't be sure that the sps_ppa field is valid, since the DLPI
9827c478bd9Sstevel@tonic-gate 	 * spec says that DL_PROMISCON_REQ can be issued at any state, i.e.,
9837c478bd9Sstevel@tonic-gate 	 * the request can be issued even before DL_ATTACH_REQ or PPPIO_ATTACH
9847c478bd9Sstevel@tonic-gate 	 * be issued to associate this stream with a ppa.
9857c478bd9Sstevel@tonic-gate 	 */
9867c478bd9Sstevel@tonic-gate 	if (ppa != NULL) {
9877c478bd9Sstevel@tonic-gate 		rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
9887c478bd9Sstevel@tonic-gate 		ppa->ppa_promicnt++;
9897c478bd9Sstevel@tonic-gate 		rw_exit(&ppa->ppa_sib_lock);
9907c478bd9Sstevel@tonic-gate 	}
9917c478bd9Sstevel@tonic-gate 	DBGDLPI((CE_CONT, "/%d: promiscuous mode on\n", sps->sps_mn_id));
9927c478bd9Sstevel@tonic-gate 	dlokack(q, mp, DL_PROMISCON_REQ);
9937c478bd9Sstevel@tonic-gate }
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate /*
9967c478bd9Sstevel@tonic-gate  * sppp_dlpromiscoffreq()
9977c478bd9Sstevel@tonic-gate  *
9987c478bd9Sstevel@tonic-gate  * MT-Perimeters:
9997c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
10007c478bd9Sstevel@tonic-gate  *
10017c478bd9Sstevel@tonic-gate  * Description:
10027c478bd9Sstevel@tonic-gate  *    Perform DL_PROMISCOFF_REQ request, called by sppp_mproto.
10037c478bd9Sstevel@tonic-gate  */
10047c478bd9Sstevel@tonic-gate static int
sppp_dlpromiscoffreq(queue_t * q,mblk_t * mp,spppstr_t * sps)10057c478bd9Sstevel@tonic-gate sppp_dlpromiscoffreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
10067c478bd9Sstevel@tonic-gate {
10077c478bd9Sstevel@tonic-gate 	t_uscalar_t	level;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
10107c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
10117c478bd9Sstevel@tonic-gate 	level = ((dl_promiscoff_req_t *)mp->b_rptr)->dl_level;
10127c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	if (!IS_SPS_PROMISC(sps)) {
10157c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI promiscoff: not promiscuous\n"));
10167c478bd9Sstevel@tonic-gate 		dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
10177c478bd9Sstevel@tonic-gate 	} else if ((level != DL_PROMISC_PHYS) && (level != DL_PROMISC_SAP) &&
10187c478bd9Sstevel@tonic-gate 	    (level != DL_PROMISC_MULTI)) {
10197c478bd9Sstevel@tonic-gate 		dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
10207c478bd9Sstevel@tonic-gate 		DBGERROR((CE_CONT, "DLPI promiscoff: bad level %d\n", level));
10217c478bd9Sstevel@tonic-gate 	} else {
10227c478bd9Sstevel@tonic-gate 		qwriter(q, mp, sppp_dl_promiscoff, PERIM_INNER);
10237c478bd9Sstevel@tonic-gate 	}
10247c478bd9Sstevel@tonic-gate 	return (0);
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate /*
10297c478bd9Sstevel@tonic-gate  * sppp_dl_promiscoff()
10307c478bd9Sstevel@tonic-gate  *
10317c478bd9Sstevel@tonic-gate  * MT-Perimeters:
10327c478bd9Sstevel@tonic-gate  *    exclusive inner, shared outer.
10337c478bd9Sstevel@tonic-gate  *
10347c478bd9Sstevel@tonic-gate  * Description:
10357c478bd9Sstevel@tonic-gate  *    Called by qwriter (INNER) from sppp_dlpromiscoffreq as the result of
10367c478bd9Sstevel@tonic-gate  *    receiving a DL_PROMISCOFF_REQ message.
10377c478bd9Sstevel@tonic-gate  */
10387c478bd9Sstevel@tonic-gate static void
sppp_dl_promiscoff(queue_t * q,mblk_t * mp)10397c478bd9Sstevel@tonic-gate sppp_dl_promiscoff(queue_t *q, mblk_t *mp)
10407c478bd9Sstevel@tonic-gate {
10417c478bd9Sstevel@tonic-gate 	spppstr_t	*sps;
10427c478bd9Sstevel@tonic-gate 	sppa_t		*ppa;
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 	ASSERT(q != NULL && q->q_ptr != NULL);
10457c478bd9Sstevel@tonic-gate 	sps = (spppstr_t *)q->q_ptr;
10467c478bd9Sstevel@tonic-gate 	ASSERT(IS_SPS_PROMISC(sps));
10477c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
10487c478bd9Sstevel@tonic-gate 	ppa = sps->sps_ppa;
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 	sps->sps_flags &= ~SPS_PROMISC;
10517c478bd9Sstevel@tonic-gate 	/*
10527c478bd9Sstevel@tonic-gate 	 * We can't be guaranteed that the sps_ppa field is still valid, since
10537c478bd9Sstevel@tonic-gate 	 * the control stream might have been closed earlier, in which case
10547c478bd9Sstevel@tonic-gate 	 * the close procedure would have NULL'd out the sps_ppa.
10557c478bd9Sstevel@tonic-gate 	 */
10567c478bd9Sstevel@tonic-gate 	if (ppa != NULL) {
10577c478bd9Sstevel@tonic-gate 		rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
10587c478bd9Sstevel@tonic-gate 		ASSERT(ppa->ppa_promicnt > 0);
10597c478bd9Sstevel@tonic-gate 		ppa->ppa_promicnt--;
10607c478bd9Sstevel@tonic-gate 		rw_exit(&ppa->ppa_sib_lock);
10617c478bd9Sstevel@tonic-gate 	}
10627c478bd9Sstevel@tonic-gate 	DBGDLPI((CE_CONT, "/%d: promiscuous mode off\n", sps->sps_mn_id));
10637c478bd9Sstevel@tonic-gate 	dlokack(q, mp, DL_PROMISCOFF_REQ);
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate /*
10677c478bd9Sstevel@tonic-gate  * sppp_dlphyreq()
10687c478bd9Sstevel@tonic-gate  *
10697c478bd9Sstevel@tonic-gate  * MT-Perimeters:
10707c478bd9Sstevel@tonic-gate  *    shared inner, shared outer.
10717c478bd9Sstevel@tonic-gate  *
10727c478bd9Sstevel@tonic-gate  * Description:
10737c478bd9Sstevel@tonic-gate  *    Perform DL_PHYS_ADDR_REQ request, called by sppp_mproto. This doesn't
10747c478bd9Sstevel@tonic-gate  *    return anything useful, but it keeps ifconfig happy.
10757c478bd9Sstevel@tonic-gate  */
10767c478bd9Sstevel@tonic-gate /* ARGSUSED */
10777c478bd9Sstevel@tonic-gate static int
sppp_dlphyreq(queue_t * q,mblk_t * mp,spppstr_t * us)10787c478bd9Sstevel@tonic-gate sppp_dlphyreq(queue_t *q, mblk_t *mp, spppstr_t *us)
10797c478bd9Sstevel@tonic-gate {
10807c478bd9Sstevel@tonic-gate 	static struct ether_addr addr = { 0 };
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate 	dlphysaddrack(q, mp, (char *)&addr, ETHERADDRL);
10837c478bd9Sstevel@tonic-gate 	return (0);
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate /*
10877c478bd9Sstevel@tonic-gate  * sppp_dladdether()
10887c478bd9Sstevel@tonic-gate  *
10897c478bd9Sstevel@tonic-gate  * Description:
10907c478bd9Sstevel@tonic-gate  *    Prepend an empty Ethernet header to msg for snoop, et al. Free
10917c478bd9Sstevel@tonic-gate  *    the original mblk if alloc fails. Only called for the purpose of sending
10927c478bd9Sstevel@tonic-gate  *    packets up the promiscous stream.
10937c478bd9Sstevel@tonic-gate  */
10947c478bd9Sstevel@tonic-gate /* ARGSUSED */
10957c478bd9Sstevel@tonic-gate static mblk_t *
sppp_dladdether(spppstr_t * sps,mblk_t * mp,t_scalar_t proto)10967c478bd9Sstevel@tonic-gate sppp_dladdether(spppstr_t *sps, mblk_t *mp, t_scalar_t proto)
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate 	mblk_t		*eh;
10997c478bd9Sstevel@tonic-gate 	t_scalar_t	type;
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	if ((eh = allocb(sizeof (struct ether_header), BPRI_MED)) == NULL) {
11027c478bd9Sstevel@tonic-gate 		freemsg(mp);
11037c478bd9Sstevel@tonic-gate 		return (NULL);
11047c478bd9Sstevel@tonic-gate 	}
11057c478bd9Sstevel@tonic-gate 	if (proto == PPP_IP) {
11067c478bd9Sstevel@tonic-gate 		type = ETHERTYPE_IP;
11077c478bd9Sstevel@tonic-gate 	} else if (proto == PPP_IPV6) {
11087c478bd9Sstevel@tonic-gate 		type = ETHERTYPE_IPV6;
11097c478bd9Sstevel@tonic-gate 	} else {
11107c478bd9Sstevel@tonic-gate 		/*
11117c478bd9Sstevel@tonic-gate 		 * For all other protocols, end this up as an ETHERTYPE_PPP
11127c478bd9Sstevel@tonic-gate 		 * type of packet. Since we've skipped the PPP headers in the
11137c478bd9Sstevel@tonic-gate 		 * caller, make sure that we restore it. We know for sure that
11147c478bd9Sstevel@tonic-gate 		 * the PPP header still exists in the message (only skipped),
11157c478bd9Sstevel@tonic-gate 		 * since the sender of this message is pppd and it must have
11167c478bd9Sstevel@tonic-gate 		 * included the PPP header in front.
11177c478bd9Sstevel@tonic-gate 		 */
11187c478bd9Sstevel@tonic-gate 		type = ETHERTYPE_PPP;
11197c478bd9Sstevel@tonic-gate 		mp->b_rptr -= PPP_HDRLEN;
11207c478bd9Sstevel@tonic-gate 		ASSERT(mp->b_rptr >= mp->b_datap->db_base);
11217c478bd9Sstevel@tonic-gate 	}
11227c478bd9Sstevel@tonic-gate 	eh->b_wptr += sizeof (struct ether_header);
11237c478bd9Sstevel@tonic-gate 	bzero((caddr_t)eh->b_rptr, sizeof (struct ether_header));
11247c478bd9Sstevel@tonic-gate 	((struct ether_header *)eh->b_rptr)->ether_type = htons((int16_t)type);
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 	linkb(eh, mp);
11277c478bd9Sstevel@tonic-gate 	return (eh);
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate /*
11317c478bd9Sstevel@tonic-gate  * sppp_dladdud()
11327c478bd9Sstevel@tonic-gate  *
11337c478bd9Sstevel@tonic-gate  * Description:
11347c478bd9Sstevel@tonic-gate  *    Prepend DL_UNITDATA_IND mblk to msg, free original alloc fails.
11357c478bd9Sstevel@tonic-gate  */
11367c478bd9Sstevel@tonic-gate /* ARGSUSED */
11377c478bd9Sstevel@tonic-gate mblk_t *
sppp_dladdud(spppstr_t * sps,mblk_t * mp,t_scalar_t proto,boolean_t promisc)11387c478bd9Sstevel@tonic-gate sppp_dladdud(spppstr_t *sps, mblk_t *mp, t_scalar_t proto, boolean_t promisc)
11397c478bd9Sstevel@tonic-gate {
11407c478bd9Sstevel@tonic-gate 	dl_unitdata_ind_t *dlu;
11417c478bd9Sstevel@tonic-gate 	mblk_t		*dh;
11427c478bd9Sstevel@tonic-gate 	size_t		size;
11437c478bd9Sstevel@tonic-gate 	t_scalar_t	type;
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 	size = sizeof (dl_unitdata_ind_t) + (2 * SPPP_ADDRL);
11467c478bd9Sstevel@tonic-gate 	if ((dh = allocb(size, BPRI_MED)) == NULL) {
11477c478bd9Sstevel@tonic-gate 		freemsg(mp);
11487c478bd9Sstevel@tonic-gate 		return (NULL);
11497c478bd9Sstevel@tonic-gate 	}
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 	dh->b_datap->db_type = M_PROTO;
11527c478bd9Sstevel@tonic-gate 	dh->b_wptr = dh->b_datap->db_lim;
11537c478bd9Sstevel@tonic-gate 	dh->b_rptr = dh->b_wptr - size;
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 	dlu = (dl_unitdata_ind_t *)dh->b_rptr;
11567c478bd9Sstevel@tonic-gate 	dlu->dl_primitive = DL_UNITDATA_IND;
11577c478bd9Sstevel@tonic-gate 	dlu->dl_dest_addr_length = SPPP_ADDRL;
11587c478bd9Sstevel@tonic-gate 	dlu->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
11597c478bd9Sstevel@tonic-gate 	dlu->dl_src_addr_length = SPPP_ADDRL;
11607c478bd9Sstevel@tonic-gate 	dlu->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + SPPP_ADDRL;
11617c478bd9Sstevel@tonic-gate 	dlu->dl_group_address = 0;
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	if (promisc) {
11647c478bd9Sstevel@tonic-gate 		if (proto == PPP_IP) {
11657c478bd9Sstevel@tonic-gate 			type = ETHERTYPE_IP;
11667c478bd9Sstevel@tonic-gate 		} else if (proto == PPP_IPV6) {
11677c478bd9Sstevel@tonic-gate 			type = ETHERTYPE_IPV6;
11687c478bd9Sstevel@tonic-gate 		} else {
11697c478bd9Sstevel@tonic-gate 			/*
11707c478bd9Sstevel@tonic-gate 			 * For all other protocols, send this up as an
11717c478bd9Sstevel@tonic-gate 			 * ETHERTYPE_PPP type of packet. Since we've skipped
11727c478bd9Sstevel@tonic-gate 			 * the PPP headers in the caller, make sure that we
11737c478bd9Sstevel@tonic-gate 			 * restore it. We know for sure that the PPP header
11747c478bd9Sstevel@tonic-gate 			 * still exists in the message (only skipped), since
11757c478bd9Sstevel@tonic-gate 			 * the sender of this message is pppd and it must
11767c478bd9Sstevel@tonic-gate 			 * have included the PPP header in front.
11777c478bd9Sstevel@tonic-gate 			 */
11787c478bd9Sstevel@tonic-gate 			type = ETHERTYPE_PPP;
11797c478bd9Sstevel@tonic-gate 			mp->b_rptr -= PPP_HDRLEN;
11807c478bd9Sstevel@tonic-gate 			ASSERT(mp->b_rptr >= mp->b_datap->db_base);
11817c478bd9Sstevel@tonic-gate 		}
11827c478bd9Sstevel@tonic-gate 	} else {
11837c478bd9Sstevel@tonic-gate 		type = sps->sps_req_sap;
11847c478bd9Sstevel@tonic-gate 	}
11857c478bd9Sstevel@tonic-gate 	/*
11867c478bd9Sstevel@tonic-gate 	 * Send the DLPI client the data with the SAP they requested,
11877c478bd9Sstevel@tonic-gate 	 * (e.g. ETHERTYPE_IP) rather than the PPP protocol (e.g. PPP_IP).
11887c478bd9Sstevel@tonic-gate 	 */
11897c478bd9Sstevel@tonic-gate 	((spppreqsap_t *)(dlu + 1))[0] = type;
11907c478bd9Sstevel@tonic-gate 	((spppreqsap_t *)(dlu + 1))[1] = type;
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 	linkb(dh, mp);
11937c478bd9Sstevel@tonic-gate 	return (dh);
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate /*
11977c478bd9Sstevel@tonic-gate  * sppp_dlprsendup()
11987c478bd9Sstevel@tonic-gate  *
11997c478bd9Sstevel@tonic-gate  * Description:
12007c478bd9Sstevel@tonic-gate  *    For any valid promiscuous streams (marked with SPS_PROMISC and its
12017c478bd9Sstevel@tonic-gate  *    sps_dlstate is DL_IDLE), send data upstream. The caller is expected
12027c478bd9Sstevel@tonic-gate  *    to hold ppa_sib_lock when calling this procedure.
12037c478bd9Sstevel@tonic-gate  */
12047c478bd9Sstevel@tonic-gate void
sppp_dlprsendup(spppstr_t * sps,mblk_t * mp,t_scalar_t proto,boolean_t header)12057c478bd9Sstevel@tonic-gate sppp_dlprsendup(spppstr_t *sps, mblk_t *mp, t_scalar_t proto, boolean_t header)
12067c478bd9Sstevel@tonic-gate {
12077c478bd9Sstevel@tonic-gate 	sppa_t	*ppa;
12087c478bd9Sstevel@tonic-gate 	mblk_t	*dmp;
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 	ASSERT(sps != NULL);
12117c478bd9Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_rptr != NULL);
12127c478bd9Sstevel@tonic-gate 	ppa = sps->sps_ppa;
12137c478bd9Sstevel@tonic-gate 	ASSERT(ppa != NULL);
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	/* NOTE: caller must hold ppa_sib_lock in RW_READER mode */
12167c478bd9Sstevel@tonic-gate 	ASSERT(RW_READ_HELD(&ppa->ppa_sib_lock));
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	for (; sps != NULL; sps = sps->sps_nextsib) {
12197c478bd9Sstevel@tonic-gate 		/*
12207c478bd9Sstevel@tonic-gate 		 * We specifically test to ensure that the DLPI state for the
12217c478bd9Sstevel@tonic-gate 		 * promiscous stream is IDLE (DL_IDLE), since such state tells
12227c478bd9Sstevel@tonic-gate 		 * us that the promiscous stream has been bound to PPP_ALLSAP.
12237c478bd9Sstevel@tonic-gate 		 */
12247c478bd9Sstevel@tonic-gate 		if (IS_SPS_PROMISC(sps) && (sps->sps_dlstate == DL_IDLE) &&
12257c478bd9Sstevel@tonic-gate 		    canputnext(sps->sps_rq)) {
12267c478bd9Sstevel@tonic-gate 			if ((dmp = dupmsg(mp)) == NULL) {
12277c478bd9Sstevel@tonic-gate 				mutex_enter(&ppa->ppa_sta_lock);
12287c478bd9Sstevel@tonic-gate 				ppa->ppa_allocbfail++;
12297c478bd9Sstevel@tonic-gate 				mutex_exit(&ppa->ppa_sta_lock);
12307c478bd9Sstevel@tonic-gate 				continue;
12317c478bd9Sstevel@tonic-gate 			}
12327c478bd9Sstevel@tonic-gate 			if (header) {
12337c478bd9Sstevel@tonic-gate 				dmp->b_rptr += PPP_HDRLEN;
12347c478bd9Sstevel@tonic-gate 			}
12357c478bd9Sstevel@tonic-gate 			if (IS_SPS_RAWDATA(sps)) {
12367c478bd9Sstevel@tonic-gate 				/* function frees original message if fails */
12377c478bd9Sstevel@tonic-gate 				dmp = sppp_dladdether(sps, dmp, proto);
12387c478bd9Sstevel@tonic-gate 			} else {
12397c478bd9Sstevel@tonic-gate 				/* function frees original message if fails */
12407c478bd9Sstevel@tonic-gate 				dmp = sppp_dladdud(sps, dmp, proto, B_TRUE);
12417c478bd9Sstevel@tonic-gate 			}
12427c478bd9Sstevel@tonic-gate 			if (dmp != NULL) {
12437c478bd9Sstevel@tonic-gate 				putnext(sps->sps_rq, dmp);
12447c478bd9Sstevel@tonic-gate 			} else {
12457c478bd9Sstevel@tonic-gate 				mutex_enter(&ppa->ppa_sta_lock);
12467c478bd9Sstevel@tonic-gate 				ppa->ppa_allocbfail++;
12477c478bd9Sstevel@tonic-gate 				mutex_exit(&ppa->ppa_sta_lock);
12487c478bd9Sstevel@tonic-gate 			}
12497c478bd9Sstevel@tonic-gate 		}
12507c478bd9Sstevel@tonic-gate 	}
12517c478bd9Sstevel@tonic-gate }
1252