xref: /illumos-gate/usr/src/uts/common/io/ppp/sppp/sppp_dlpi.c (revision 5422785d352a2bb398daceab3d1898a8aa64d006)
1 /*
2  * sppp_dlpi.c - Solaris STREAMS PPP multiplexing pseudo-driver DLPI handlers
3  *
4  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
5  * Use is subject to license terms.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation is hereby granted, provided that the above copyright
9  * notice appears in all copies.
10  *
11  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
12  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
15  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
16  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
17  *
18  * Copyright (c) 1994 The Australian National University.
19  * All rights reserved.
20  *
21  * Permission to use, copy, modify, and distribute this software and its
22  * documentation is hereby granted, provided that the above copyright
23  * notice appears in all copies.  This software is provided without any
24  * warranty, express or implied. The Australian National University
25  * makes no representations about the suitability of this software for
26  * any purpose.
27  *
28  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
29  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
30  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
31  * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
32  * OF SUCH DAMAGE.
33  *
34  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
37  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
38  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
39  * OR MODIFICATIONS.
40  *
41  * This driver is derived from the original SVR4 STREAMS PPP driver
42  * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
43  *
44  * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
45  * for improved performance and scalability.
46  */
47 
48 #define	RCSID	"$Id: sppp_dlpi.c,v 1.0 2000/05/08 01:10:12 masputra Exp $"
49 
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <sys/stat.h>
53 #include <sys/stream.h>
54 #include <sys/stropts.h>
55 #include <sys/errno.h>
56 #include <sys/time.h>
57 #include <sys/cmn_err.h>
58 #include <sys/conf.h>
59 #include <sys/dlpi.h>
60 #include <sys/ddi.h>
61 #include <sys/kstat.h>
62 #include <sys/strsubr.h>
63 #include <sys/strsun.h>
64 #include <sys/ethernet.h>
65 #include <net/ppp_defs.h>
66 #include <netinet/in.h>
67 #include <net/pppio.h>
68 #include "s_common.h"
69 #include "sppp.h"
70 
71 static int	sppp_dlattachreq(queue_t *, mblk_t *, spppstr_t *);
72 static int	sppp_dldetachreq(queue_t *, mblk_t *, spppstr_t *);
73 static int	sppp_dlbindreq(queue_t *, mblk_t *, spppstr_t *);
74 static int	sppp_dlunbindreq(queue_t *, mblk_t *, spppstr_t *);
75 static int	sppp_dlinforeq(queue_t *, mblk_t *, spppstr_t *);
76 static int	sppp_dlunitdatareq(queue_t *, mblk_t *, spppstr_t *);
77 static int	sppp_dlpromisconreq(queue_t *, mblk_t *, spppstr_t *);
78 static int	sppp_dlpromiscoffreq(queue_t *, mblk_t *, spppstr_t *);
79 static int	sppp_dlphyreq(queue_t *, mblk_t *, spppstr_t *);
80 static void	sppp_dl_attach_upper(queue_t *, mblk_t *);
81 static void	sppp_dl_detach_upper(queue_t *, mblk_t *);
82 static void	sppp_dl_bind(queue_t *, mblk_t *);
83 static void	sppp_dl_unbind(queue_t *, mblk_t *);
84 static void	sppp_dl_promiscon(queue_t *, mblk_t *);
85 static void	sppp_dl_promiscoff(queue_t *, mblk_t *);
86 static mblk_t	*sppp_dladdether(spppstr_t *, mblk_t *, t_scalar_t);
87 
88 static struct sppp_dlpi_pinfo_t dl_pinfo[DL_MAXPRIM + 1];
89 
90 #if 0
91 #define	DBGERROR(x)	cmn_err x
92 #else
93 #define	DBGERROR(x)	((void)0)
94 #endif
95 
96 /* #define	DBG_DLPI	1 */
97 
98 #ifdef DBG_DLPI
99 struct sppp_dlpi_entry {
100 	uint32_t sde_val;
101 	const char *sde_name;
102 };
103 
104 static const struct sppp_dlpi_entry sppp_dlpi_list[] = {
105 	{ DL_INFO_REQ, "DL_INFO_REQ" },
106 	{ DL_INFO_ACK, "DL_INFO_ACK" },
107 	{ DL_ATTACH_REQ, "DL_ATTACH_REQ" },
108 	{ DL_DETACH_REQ, "DL_DETACH_REQ" },
109 	{ DL_BIND_REQ, "DL_BIND_REQ" },
110 	{ DL_BIND_ACK, "DL_BIND_ACK" },
111 	{ DL_UNBIND_REQ, "DL_UNBIND_REQ" },
112 	{ DL_OK_ACK, "DL_OK_ACK" },
113 	{ DL_ERROR_ACK, "DL_ERROR_ACK" },
114 	{ DL_SUBS_BIND_REQ, "DL_SUBS_BIND_REQ" },
115 	{ DL_SUBS_BIND_ACK, "DL_SUBS_BIND_ACK" },
116 	{ DL_SUBS_UNBIND_REQ, "DL_SUBS_UNBIND_REQ" },
117 	{ DL_ENABMULTI_REQ, "DL_ENABMULTI_REQ" },
118 	{ DL_DISABMULTI_REQ, "DL_DISABMULTI_REQ" },
119 	{ DL_PROMISCON_REQ, "DL_PROMISCON_REQ" },
120 	{ DL_PROMISCOFF_REQ, "DL_PROMISCOFF_REQ" },
121 	{ DL_UNITDATA_REQ, "DL_UNITDATA_REQ" },
122 	{ DL_UNITDATA_IND, "DL_UNITDATA_IND" },
123 	{ DL_UDERROR_IND, "DL_UDERROR_IND" },
124 	{ DL_UDQOS_REQ, "DL_UDQOS_REQ" },
125 	{ DL_CONNECT_REQ, "DL_CONNECT_REQ" },
126 	{ DL_CONNECT_IND, "DL_CONNECT_IND" },
127 	{ DL_CONNECT_RES, "DL_CONNECT_RES" },
128 	{ DL_CONNECT_CON, "DL_CONNECT_CON" },
129 	{ DL_TOKEN_REQ, "DL_TOKEN_REQ" },
130 	{ DL_TOKEN_ACK, "DL_TOKEN_ACK" },
131 	{ DL_DISCONNECT_REQ, "DL_DISCONNECT_REQ" },
132 	{ DL_DISCONNECT_IND, "DL_DISCONNECT_IND" },
133 	{ DL_RESET_REQ, "DL_RESET_REQ" },
134 	{ DL_RESET_IND, "DL_RESET_IND" },
135 	{ DL_RESET_RES, "DL_RESET_RES" },
136 	{ DL_RESET_CON, "DL_RESET_CON" },
137 	{ DL_DATA_ACK_REQ, "DL_DATA_ACK_REQ" },
138 	{ DL_DATA_ACK_IND, "DL_DATA_ACK_IND" },
139 	{ DL_DATA_ACK_STATUS_IND, "DL_DATA_ACK_STATUS_IND" },
140 	{ DL_REPLY_REQ, "DL_REPLY_REQ" },
141 	{ DL_REPLY_IND, "DL_REPLY_IND" },
142 	{ DL_REPLY_STATUS_IND, "DL_REPLY_STATUS_IND" },
143 	{ DL_REPLY_UPDATE_REQ, "DL_REPLY_UPDATE_REQ" },
144 	{ DL_REPLY_UPDATE_STATUS_IND, "DL_REPLY_UPDATE_STATUS_IND" },
145 	{ DL_XID_REQ, "DL_XID_REQ" },
146 	{ DL_XID_IND, "DL_XID_IND" },
147 	{ DL_XID_RES, "DL_XID_RES" },
148 	{ DL_XID_CON, "DL_XID_CON" },
149 	{ DL_TEST_REQ, "DL_TEST_REQ" },
150 	{ DL_TEST_IND, "DL_TEST_IND" },
151 	{ DL_TEST_RES, "DL_TEST_RES" },
152 	{ DL_TEST_CON, "DL_TEST_CON" },
153 	{ DL_PHYS_ADDR_REQ, "DL_PHYS_ADDR_REQ" },
154 	{ DL_PHYS_ADDR_ACK, "DL_PHYS_ADDR_ACK" },
155 	{ DL_SET_PHYS_ADDR_REQ, "DL_SET_PHYS_ADDR_REQ" },
156 	{ DL_GET_STATISTICS_REQ, "DL_GET_STATISTICS_REQ" },
157 	{ DL_GET_STATISTICS_ACK, "DL_GET_STATISTICS_ACK" },
158 	{ 0, NULL }
159 };
160 
161 static const struct sppp_dlpi_entry sppp_state_list[] = {
162 	{ DL_UNBOUND, "DL_UNBOUND" },
163 	{ DL_BIND_PENDING, "DL_BIND_PENDING" },
164 	{ DL_UNBIND_PENDING, "DL_UNBIND_PENDING" },
165 	{ DL_IDLE, "DL_IDLE" },
166 	{ DL_UNATTACHED, "DL_UNATTACHED" },
167 	{ DL_ATTACH_PENDING, "DL_ATTACH_PENDING" },
168 	{ DL_DETACH_PENDING, "DL_DETACH_PENDING" },
169 	{ DL_UDQOS_PENDING, "DL_UDQOS_PENDING" },
170 	{ DL_OUTCON_PENDING, "DL_OUTCON_PENDING" },
171 	{ DL_INCON_PENDING, "DL_INCON_PENDING" },
172 	{ DL_CONN_RES_PENDING, "DL_CONN_RES_PENDING" },
173 	{ DL_DATAXFER, "DL_DATAXFER" },
174 	{ DL_USER_RESET_PENDING, "DL_USER_RESET_PENDING" },
175 	{ DL_PROV_RESET_PENDING, "DL_PROV_RESET_PENDING" },
176 	{ DL_RESET_RES_PENDING, "DL_RESET_RES_PENDING" },
177 	{ DL_DISCON8_PENDING, "DL_DISCON8_PENDING" },
178 	{ DL_DISCON9_PENDING, "DL_DISCON9_PENDING" },
179 	{ DL_DISCON11_PENDING, "DL_DISCON11_PENDING" },
180 	{ DL_DISCON12_PENDING, "DL_DISCON12_PENDING" },
181 	{ DL_DISCON13_PENDING, "DL_DISCON13_PENDING" },
182 	{ DL_SUBS_BIND_PND, "DL_SUBS_BIND_PND" },
183 	{ DL_SUBS_UNBIND_PND, "DL_SUBS_UNBIND_PND" },
184 	{ 0, NULL }
185 };
186 
187 static const char *
188 prim2name(uint32_t prim)
189 {
190 	const struct sppp_dlpi_entry *sde;
191 
192 	for (sde = sppp_dlpi_list; sde->sde_name != NULL; sde++)
193 		if (sde->sde_val == prim)
194 			break;
195 	return (sde->sde_name);
196 }
197 
198 static const char *
199 state2name(uint32_t state)
200 {
201 	const struct sppp_dlpi_entry *sde;
202 
203 	for (sde = sppp_state_list; sde->sde_name != NULL; sde++)
204 		if (sde->sde_val == state)
205 			break;
206 	return (sde->sde_name);
207 }
208 
209 #define	DBGDLPI(x)	cmn_err x
210 #else
211 #define	DBGDLPI(x)	((void)0)
212 #endif /* DBG_DLPI */
213 
214 /*
215  * DL_INFO_ACK template for point-to-point interface.
216  */
217 static dl_info_ack_t	sppp_infoack = {
218 	DL_INFO_ACK,			/* dl_primitive */
219 	PPP_MAXMTU,			/* dl_max_sdu */
220 	0,				/* dl_min_sdu */
221 	SPPP_ADDRL,			/* dl_addr_length */
222 	/*
223 	 * snoop et. al. don't know about DL_OTHER so this entry
224 	 * was changed to DL_ETHER so ethernet tracing/snooping
225 	 * facilities will work with PPP interfaces.
226 	 */
227 	DL_ETHER,			/* dl_mac_type */
228 	0,				/* dl_reserved */
229 	0,				/* dl_current_state */
230 	SPPP_SAPL,			/* dl_sap_length */
231 	DL_CLDLS,			/* dl_service_mode */
232 	0,				/* dl_qos_length */
233 	0,				/* dl_qos_offset */
234 	0,				/* dl_range_length */
235 	0,				/* dl_range_offset */
236 	DL_STYLE2,			/* dl_provider_style */
237 	sizeof (dl_info_ack_t),		/* dl_addr_offset */
238 	DL_VERSION_2,			/* dl_version */
239 	0,				/* dl_brdcst_addr_length */
240 	0,				/* dl_brdcst_addr_offset */
241 	0				/* dl_growth */
242 };
243 
244 /*
245  * sppp_dlpi_pinfoinit()
246  *
247  * Description:
248  *    Initialize dl_pinfo[], called from sppp_attach.
249  */
250 void
251 sppp_dlpi_pinfoinit(void)
252 {
253 	bzero(dl_pinfo, sizeof (dl_pinfo));	/* Just to be safe */
254 
255 	dl_pinfo[DL_ATTACH_REQ].pi_minlen = sizeof (dl_attach_req_t);
256 	dl_pinfo[DL_ATTACH_REQ].pi_state = DL_UNATTACHED;
257 	dl_pinfo[DL_ATTACH_REQ].pi_funcp = sppp_dlattachreq;
258 
259 	dl_pinfo[DL_DETACH_REQ].pi_minlen = sizeof (dl_detach_req_t);
260 	dl_pinfo[DL_DETACH_REQ].pi_state = DL_UNBOUND;
261 	dl_pinfo[DL_DETACH_REQ].pi_funcp = sppp_dldetachreq;
262 
263 	dl_pinfo[DL_BIND_REQ].pi_minlen = sizeof (dl_bind_req_t);
264 	dl_pinfo[DL_BIND_REQ].pi_state = DL_UNBOUND;
265 	dl_pinfo[DL_BIND_REQ].pi_funcp = sppp_dlbindreq;
266 
267 	dl_pinfo[DL_UNBIND_REQ].pi_minlen = sizeof (dl_unbind_req_t);
268 	dl_pinfo[DL_UNBIND_REQ].pi_state = DL_IDLE;
269 	dl_pinfo[DL_UNBIND_REQ].pi_funcp = sppp_dlunbindreq;
270 
271 	dl_pinfo[DL_INFO_REQ].pi_minlen = sizeof (dl_info_req_t);
272 	dl_pinfo[DL_INFO_REQ].pi_state = -1;	/* special handling */
273 	dl_pinfo[DL_INFO_REQ].pi_funcp = sppp_dlinforeq;
274 
275 	dl_pinfo[DL_UNITDATA_REQ].pi_minlen = sizeof (dl_unitdata_req_t);
276 	dl_pinfo[DL_UNITDATA_REQ].pi_state = DL_IDLE;
277 	dl_pinfo[DL_UNITDATA_REQ].pi_funcp = sppp_dlunitdatareq;
278 
279 	dl_pinfo[DL_PROMISCON_REQ].pi_minlen = sizeof (dl_promiscon_req_t);
280 	dl_pinfo[DL_PROMISCON_REQ].pi_state = -1; /* special handling */
281 	dl_pinfo[DL_PROMISCON_REQ].pi_funcp = sppp_dlpromisconreq;
282 
283 	dl_pinfo[DL_PROMISCOFF_REQ].pi_minlen = sizeof (dl_promiscoff_req_t);
284 	dl_pinfo[DL_PROMISCOFF_REQ].pi_state = -1; /* special handling */
285 	dl_pinfo[DL_PROMISCOFF_REQ].pi_funcp = sppp_dlpromiscoffreq;
286 
287 	dl_pinfo[DL_PHYS_ADDR_REQ].pi_minlen = sizeof (dl_phys_addr_req_t);
288 	dl_pinfo[DL_PHYS_ADDR_REQ].pi_state = -1; /* special handling */
289 	dl_pinfo[DL_PHYS_ADDR_REQ].pi_funcp = sppp_dlphyreq;
290 }
291 
292 /*
293  * sppp_mproto()
294  *
295  * MT-Perimeters:
296  *    shared inner, shared outer.
297  *
298  * Description:
299  *    Handle M_PCPROTO/M_PROTO messages, called by sppp_uwput.
300  */
301 int
302 sppp_mproto(queue_t *q, mblk_t *mp, spppstr_t *sps)
303 {
304 	union DL_primitives *dlp;
305 	struct sppp_dlpi_pinfo_t *dpi;
306 	t_uscalar_t	prim;
307 	int		len;
308 	int		error = 0;
309 
310 	ASSERT(!IS_SPS_CONTROL(sps));
311 	if ((len = MBLKL(mp)) < sizeof (t_uscalar_t)) {
312 		DBGERROR((CE_CONT, "bad mproto: block length %d\n", len));
313 		merror(q, mp, EPROTO);
314 		return (0);
315 	}
316 	dlp = (union DL_primitives *)mp->b_rptr;
317 	prim = dlp->dl_primitive;
318 	if (prim > DL_MAXPRIM) {
319 		DBGERROR((CE_CONT, "bad mproto: primitive %d > %d\n", prim,
320 		    DL_MAXPRIM));
321 		error = DL_BADPRIM;
322 	} else {
323 		dpi = &dl_pinfo[prim];
324 		if (dpi->pi_funcp == NULL) {
325 			DBGERROR((CE_CONT,
326 			    "bad mproto: primitive %d not supported\n", prim));
327 			error = DL_NOTSUPPORTED;
328 		} else if (len < dpi->pi_minlen) {
329 			DBGERROR((CE_CONT,
330 			    "bad mproto: primitive len %d < %d\n", len,
331 			    dpi->pi_minlen));
332 			error = DL_BADPRIM;
333 		} else if (dpi->pi_state != -1 &&
334 		    sps->sps_dlstate != dpi->pi_state) {
335 			DBGERROR((CE_CONT,
336 			    "bad state %d != %d for primitive %d\n",
337 			    sps->sps_dlstate, dpi->pi_state, prim));
338 			error = DL_OUTSTATE;
339 		}
340 	}
341 	if (error != 0) {
342 		dlerrorack(q, mp, dlp->dl_primitive, error, 0);
343 		return (0);
344 	}
345 #ifdef DBG_DLPI
346 	{
347 		const char *cp = prim2name(prim);
348 		if (cp != NULL)
349 			cmn_err(CE_CONT, "/%d: Dispatching %s\n",
350 			    sps->sps_mn_id, cp);
351 		else
352 			cmn_err(CE_CONT,
353 			    "/%d: Dispatching unknown primitive %d\n",
354 			    sps->sps_mn_id, prim);
355 	}
356 #endif
357 	return ((*dpi->pi_funcp)(q, mp, sps));
358 }
359 
360 /*
361  * sppp_dlattachreq()
362  *
363  * MT-Perimeters:
364  *    shared inner, shared outer.
365  *
366  * Description:
367  *    Perform DL_ATTACH_REQ request, called by sppp_mproto.
368  */
369 static int
370 sppp_dlattachreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
371 {
372 	int	error = 0;
373 	union DL_primitives *dlp;
374 
375 	ASSERT(q != NULL && q->q_ptr != NULL);
376 	ASSERT(mp != NULL && mp->b_rptr != NULL);
377 	dlp = (union DL_primitives *)mp->b_rptr;
378 	ASSERT(sps != NULL);
379 	ASSERT(sps->sps_dlstate == DL_UNATTACHED);
380 
381 	if (IS_SPS_PIOATTACH(sps)) {
382 		DBGERROR((CE_CONT, "DLPI attach: already attached\n"));
383 		error = EINVAL;
384 	}
385 	if (error != 0) {
386 		dlerrorack(q, mp, dlp->dl_primitive, DL_OUTSTATE, error);
387 	} else {
388 		qwriter(q, mp, sppp_dl_attach_upper, PERIM_OUTER);
389 	}
390 	return (0);
391 }
392 
393 /*
394  * sppp_dl_attach_upper()
395  *
396  * MT-Perimeters:
397  *    exclusive inner, exclusive outer.
398  *
399  * Description:
400  *    Called by qwriter (INNER) from sppp_dlattachreq as the result of
401  *    receiving a DL_ATTACH_REQ message.
402  */
403 static void
404 sppp_dl_attach_upper(queue_t *q, mblk_t *mp)
405 {
406 	sppa_t		*ppa;
407 	spppstr_t	*sps = q->q_ptr;
408 	union DL_primitives *dlp;
409 	int		err = ENOMEM;
410 	cred_t		*cr;
411 	zoneid_t	zoneid;
412 
413 	ASSERT(!IS_SPS_PIOATTACH(sps));
414 	dlp = (union DL_primitives *)mp->b_rptr;
415 
416 	/* If there's something here, it's detached. */
417 	if (sps->sps_ppa != NULL) {
418 		sppp_remove_ppa(sps);
419 	}
420 
421 	if ((cr = msg_getcred(mp, NULL)) == NULL)
422 		zoneid = sps->sps_zoneid;
423 	else
424 		zoneid = crgetzoneid(cr);
425 
426 	ppa = sppp_find_ppa(dlp->attach_req.dl_ppa);
427 	if (ppa == NULL) {
428 		ppa = sppp_create_ppa(dlp->attach_req.dl_ppa, zoneid);
429 	} else if (ppa->ppa_zoneid != zoneid) {
430 		ppa = NULL;
431 		err = EPERM;
432 	}
433 
434 	/*
435 	 * If we can't find or create it, then it's either because we're out of
436 	 * memory or because the requested PPA is owned by a different zone.
437 	 */
438 	if (ppa == NULL) {
439 		DBGERROR((CE_CONT, "DLPI attach: cannot create ppa %u\n",
440 		    dlp->attach_req.dl_ppa));
441 		dlerrorack(q, mp, dlp->dl_primitive, DL_SYSERR, err);
442 		return;
443 	}
444 	/*
445 	 * Preallocate the hangup message so that we're always able to
446 	 * send this upstream in the event of a catastrophic failure.
447 	 */
448 	if ((sps->sps_hangup = allocb(1, BPRI_MED)) == NULL) {
449 		DBGERROR((CE_CONT, "DLPI attach: cannot allocate hangup\n"));
450 		dlerrorack(q, mp, dlp->dl_primitive, DL_SYSERR, ENOSR);
451 		return;
452 	}
453 	sps->sps_dlstate = DL_UNBOUND;
454 	sps->sps_ppa = ppa;
455 	/*
456 	 * Add this stream to the head of the list of sibling streams
457 	 * which belong to the specified ppa.
458 	 */
459 	rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
460 	ppa->ppa_refcnt++;
461 	sps->sps_nextsib = ppa->ppa_streams;
462 	ppa->ppa_streams = sps;
463 	/*
464 	 * And if this stream was marked as promiscuous (SPS_PROMISC), then we
465 	 * need to update the promiscuous streams count. This should only
466 	 * happen when DL_PROMISCON_REQ was issued prior to attachment.
467 	 */
468 	if (IS_SPS_PROMISC(sps)) {
469 		ppa->ppa_promicnt++;
470 	}
471 	rw_exit(&ppa->ppa_sib_lock);
472 	DBGDLPI((CE_CONT, "/%d: attached to ppa %d\n", sps->sps_mn_id,
473 	    ppa->ppa_ppa_id));
474 	dlokack(q, mp, DL_ATTACH_REQ);
475 }
476 
477 /*
478  * sppp_dldetachreq()
479  *
480  * MT-Perimeters:
481  *    shared inner, shared outer.
482  *
483  * Description:
484  *    Perform DL_DETACH_REQ request, called by sppp_mproto.
485  */
486 /* ARGSUSED */
487 static int
488 sppp_dldetachreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
489 {
490 	ASSERT(q != NULL && q->q_ptr != NULL);
491 	ASSERT(mp != NULL && mp->b_rptr != NULL);
492 	ASSERT(sps != NULL);
493 	ASSERT(sps->sps_dlstate == DL_UNBOUND);
494 	ASSERT(!IS_SPS_PIOATTACH(sps));
495 
496 	qwriter(q, mp, sppp_dl_detach_upper, PERIM_INNER);
497 	return (0);
498 }
499 
500 /*
501  * sppp_dl_detach_upper()
502  *
503  * MT-Perimeters:
504  *    exclusive inner, shared outer.
505  *
506  * Description:
507  *    Called by qwriter (INNER) from sppp_dldetachreq as the result of
508  *    receiving a DL_DETACH_REQ message.
509  */
510 /* ARGSUSED */
511 static void
512 sppp_dl_detach_upper(queue_t *q, mblk_t *mp)
513 {
514 	spppstr_t	*sps;
515 
516 	ASSERT(q != NULL && q->q_ptr != NULL);
517 	ASSERT(mp != NULL && mp->b_rptr != NULL);
518 	sps = (spppstr_t *)q->q_ptr;
519 	/*
520 	 * We don't actually detach from the PPA until closed or
521 	 * reattached.
522 	 */
523 	sps->sps_flags &= ~SPS_PROMISC;	/* clear flag anyway */
524 	sps->sps_dlstate = DL_UNATTACHED;
525 	dlokack(q, mp, DL_DETACH_REQ);
526 }
527 
528 /*
529  * sppp_dlbindreq()
530  *
531  * MT-Perimeters:
532  *    shared inner, shared outer.
533  *
534  * Description:
535  *    Perform DL_BIND_REQ request, called by sppp_mproto.
536  */
537 static int
538 sppp_dlbindreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
539 {
540 	sppa_t			*ppa;
541 	union DL_primitives	*dlp;
542 	spppreqsap_t		req_sap;
543 	int			error = 0;
544 
545 	ASSERT(q != NULL && q->q_ptr != NULL);
546 	ASSERT(mp != NULL && mp->b_rptr != NULL);
547 	dlp = (union DL_primitives *)mp->b_rptr;
548 	req_sap = dlp->bind_req.dl_sap;
549 	ASSERT(sps != NULL);
550 	ASSERT(!IS_SPS_PIOATTACH(sps));
551 	ASSERT(sps->sps_dlstate == DL_UNBOUND);
552 
553 	ppa = sps->sps_ppa;
554 	if (ppa == NULL) {
555 		DBGERROR((CE_CONT, "DLPI bind: no attached ppa\n"));
556 		error = DL_OUTSTATE;
557 	} else if ((req_sap != ETHERTYPE_IP) && (req_sap != ETHERTYPE_IPV6) &&
558 	    (req_sap != ETHERTYPE_ALLSAP)) {
559 		DBGERROR((CE_CONT, "DLPI bind: unknown SAP %x\n", req_sap));
560 		error = DL_BADADDR;
561 	}
562 	if (error != 0) {
563 		dlerrorack(q, mp, dlp->dl_primitive, error, 0);
564 	} else {
565 		qwriter(q, mp, sppp_dl_bind, PERIM_INNER);
566 	}
567 	return (0);
568 }
569 
570 /*
571  * sppp_dl_bind()
572  *
573  * MT-Perimeters:
574  *    exclusive inner, shared outer.
575  *
576  * Description:
577  *    Called by qwriter (INNER) from sppp_dlbindreq as the result of
578  *    receiving a DL_BIND_REQ message.
579  */
580 static void
581 sppp_dl_bind(queue_t *q, mblk_t *mp)
582 {
583 	spppstr_t		*sps;
584 	sppa_t			*ppa;
585 	union DL_primitives	*dlp;
586 	t_scalar_t		sap;
587 	spppreqsap_t		req_sap;
588 	mblk_t			*lsmp;
589 
590 	ASSERT(q != NULL && q->q_ptr != NULL);
591 	sps = (spppstr_t *)q->q_ptr;
592 	ASSERT(mp != NULL && mp->b_rptr != NULL);
593 	dlp = (union DL_primitives *)mp->b_rptr;
594 	ppa = sps->sps_ppa;
595 	ASSERT(ppa != NULL);
596 	req_sap = dlp->bind_req.dl_sap;
597 	ASSERT((req_sap == ETHERTYPE_IP) || (req_sap == ETHERTYPE_IPV6) ||
598 	    (req_sap == ETHERTYPE_ALLSAP));
599 
600 	if (req_sap == ETHERTYPE_IP) {
601 		sap = PPP_IP;
602 	} else if (req_sap == ETHERTYPE_IPV6) {
603 		sap = PPP_IPV6;
604 	} else if (req_sap == ETHERTYPE_ALLSAP) {
605 		sap = PPP_ALLSAP;
606 	}
607 	/*
608 	 * If there's another stream with the same sap has already been bound
609 	 * to the same ppa, then return with DL_NOADDR. However, we do make an
610 	 * exception for snoop (req_sap=0x00, sap=0xff) since multiple
611 	 * instances of snoop may execute an a given device.
612 	 */
613 	lsmp = NULL;
614 	if (sap != PPP_ALLSAP) {
615 		if ((sap == PPP_IP) && (ppa->ppa_ip_cache == NULL)) {
616 			ppa->ppa_ip_cache = sps;
617 			if (ppa->ppa_ctl != NULL) {
618 				lsmp = create_lsmsg(PPP_LINKSTAT_IPV4_BOUND);
619 			}
620 		} else if ((sap == PPP_IPV6) && (ppa->ppa_ip6_cache == NULL)) {
621 			ppa->ppa_ip6_cache = sps;
622 			if (ppa->ppa_ctl != NULL) {
623 				lsmp = create_lsmsg(PPP_LINKSTAT_IPV6_BOUND);
624 			}
625 		} else {
626 			DBGERROR((CE_CONT, "DLPI bind: bad SAP %x\n", sap));
627 			dlerrorack(q, mp, dlp->dl_primitive, DL_NOADDR,
628 			    EEXIST);
629 			return;
630 		}
631 		sps->sps_flags |= SPS_CACHED;
632 	}
633 	/*
634 	 * Tell the daemon that a DLPI bind has happened on this stream,
635 	 * and we'll only do this for PPP_IP or PPP_IPV6 sap (not snoop).
636 	 */
637 	if (lsmp != NULL && ppa->ppa_ctl != NULL) {
638 #ifdef DBG_DLPI
639 		cmn_err(CE_CONT, "sending up %s\n",
640 		    ((sap == PPP_IP) ? "PPP_LINKSTAT_IPV4_BOUND" :
641 		    "PPP_LINKSTAT_IPV6_BOUND"));
642 #endif
643 		putnext(ppa->ppa_ctl->sps_rq, lsmp);
644 	}
645 	DBGDLPI((CE_CONT, "/%d: bound to sap %X (req %X)\n", sps->sps_mn_id,
646 	    sap, req_sap));
647 	sps->sps_req_sap = req_sap;
648 	sps->sps_sap = sap;
649 	sps->sps_dlstate = DL_IDLE;
650 	dlbindack(q, mp, req_sap, &sap, sizeof (int32_t), 0, 0);
651 }
652 
653 /*
654  * sppp_dlunbindreq()
655  *
656  * MT-Perimeters:
657  *    shared inner, shared outer.
658  *
659  * Description:
660  *    Perform DL_UNBIND_REQ request, called by sppp_mproto.
661  */
662 /* ARGSUSED */
663 static int
664 sppp_dlunbindreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
665 {
666 	ASSERT(q != NULL && q->q_ptr != NULL);
667 	ASSERT(mp != NULL && mp->b_rptr != NULL);
668 	ASSERT(sps != NULL);
669 	ASSERT(!IS_SPS_PIOATTACH(sps));
670 	ASSERT(sps->sps_dlstate == DL_IDLE);
671 
672 	qwriter(q, mp, sppp_dl_unbind, PERIM_INNER);
673 	return (0);
674 }
675 
676 /*
677  * sppp_dl_unbind()
678  *
679  * MT-Perimeters:
680  *    exclusive inner, shared outer.
681  *
682  * Description:
683  *    Called by qwriter (INNER) from sppp_dlunbindreq as the result of
684  *    receiving a DL_UNBIND_REQ message.
685  */
686 static void
687 sppp_dl_unbind(queue_t *q, mblk_t *mp)
688 {
689 	spppstr_t	*sps;
690 	sppa_t		*ppa;
691 	t_scalar_t	sap;
692 	mblk_t		*msg;
693 	boolean_t	saydown;
694 
695 	ASSERT(q != NULL && q->q_ptr != NULL);
696 	sps = (spppstr_t *)q->q_ptr;
697 	ppa = sps->sps_ppa;
698 	ASSERT(mp != NULL && mp->b_rptr != NULL);
699 	sap = sps->sps_sap;
700 	ASSERT((sap == PPP_IP) || (sap == PPP_IPV6) || (sap == PPP_ALLSAP));
701 
702 	/* Flush messages on unbind, per DLPI specification. */
703 	flushq(WR(q), FLUSHALL);
704 	flushq(RD(q), FLUSHALL);
705 
706 	if ((ppa != NULL) && IS_SPS_CACHED(sps)) {
707 		sps->sps_flags &= ~SPS_CACHED;
708 		msg = NULL;
709 		saydown = (ppa->ppa_ctl != NULL &&
710 		    (sps->sps_npmode == NPMODE_PASS ||
711 		    sps->sps_npmode == NPMODE_QUEUE));
712 		if (sap == PPP_IP) {
713 			ppa->ppa_ip_cache = NULL;
714 			if (saydown)
715 				msg = create_lsmsg(PPP_LINKSTAT_IPV4_UNBOUND);
716 		} else if (sap == PPP_IPV6) {
717 			ppa->ppa_ip6_cache = NULL;
718 			if (saydown)
719 				msg = create_lsmsg(PPP_LINKSTAT_IPV6_UNBOUND);
720 		}
721 		if (msg != NULL) {
722 #ifdef DBG_DLPI
723 			cmn_err(CE_CONT, "sending up %s\n",
724 			    ((sap == PPP_IP) ? "PPP_LINKSTAT_IPV4_UNBOUND" :
725 			    "PPP_LINKSTAT_IPV6_UNBOUND"));
726 #endif
727 			putnext(ppa->ppa_ctl->sps_rq, msg);
728 		}
729 	}
730 	DBGDLPI((CE_CONT, "/%d: unbound from sap %X (req %X)\n", sps->sps_mn_id,
731 	    sps->sps_sap, sps->sps_req_sap));
732 	sps->sps_req_sap = 0;
733 	sps->sps_sap = -1;
734 	sps->sps_dlstate = DL_UNBOUND;
735 
736 	dlokack(q, mp, DL_UNBIND_REQ);
737 }
738 
739 /*
740  * sppp_dlinforeq()
741  *
742  * MT-Perimeters:
743  *    shared inner, shared outer.
744  *
745  * Description:
746  *    Perform DL_INFO_REQ request, called by sppp_mproto.
747  */
748 static int
749 sppp_dlinforeq(queue_t *q, mblk_t *mp, spppstr_t *sps)
750 {
751 	dl_info_ack_t	*dlip;
752 	uint32_t	size;
753 	uint32_t	addr_size;
754 	sppa_t		*ppa;
755 
756 	ASSERT(q != NULL && q->q_ptr != NULL);
757 	ASSERT(mp != NULL && mp->b_rptr != NULL);
758 	ASSERT(sps != NULL);
759 	ppa = sps->sps_ppa;
760 
761 	/* Exchange current msg for a DL_INFO_ACK. */
762 	addr_size = SPPP_ADDRL;
763 	size = sizeof (dl_info_ack_t) + addr_size;
764 	if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL) {
765 		DBGERROR((CE_CONT, "DLPI info: mexchange failed\n"));
766 		/* mexchange already sent up an merror ENOSR */
767 		return (0);
768 	}
769 	/* Fill in DL_INFO_ACK fields and reply */
770 	dlip = (dl_info_ack_t *)mp->b_rptr;
771 	*dlip = sppp_infoack;
772 	dlip->dl_current_state = sps->sps_dlstate;
773 	dlip->dl_max_sdu = ppa != NULL ? ppa->ppa_mtu : PPP_MAXMTU;
774 #ifdef DBG_DLPI
775 	{
776 		const char *cp = state2name(dlip->dl_current_state);
777 		if (cp != NULL)
778 			cmn_err(CE_CONT, "info returns state %s, max sdu %d\n",
779 			    cp, dlip->dl_max_sdu);
780 		else
781 			cmn_err(CE_CONT, "info returns state %d, max sdu %d\n",
782 			    dlip->dl_current_state, dlip->dl_max_sdu);
783 	}
784 #endif
785 	qreply(q, mp);
786 	return (0);
787 }
788 
789 /*
790  * sppp_dlunitdatareq()
791  *
792  * MT-Perimeters:
793  *    shared inner, shared outer.
794  *
795  * Description:
796  *    Handle DL_UNITDATA_REQ request, called by sppp_mproto. This procedure
797  *    gets called for M_PROTO (DLPI) style of transmission. The fact that we
798  *    have acknowledged IP's fastpath probing (DL_IOC_HDR_INFO) does not
799  *    guarantee that IP will always transmit via M_DATA, and it merely implies
800  *    that such situation _may_ happen. In other words, IP may decide to use
801  *    M_PROTO (DLPI) for data transmission should it decide to do so.
802  *    Therefore, we should never place any restrictions or checks against
803  *    streams marked with SPS_FASTPATH, since it is legal for this procedure
804  *    to be entered with or without the bit set.
805  */
806 static int
807 sppp_dlunitdatareq(queue_t *q, mblk_t *mp, spppstr_t *sps)
808 {
809 	sppa_t		*ppa;
810 	mblk_t		*hdrmp;
811 	mblk_t		*pktmp;
812 	dl_unitdata_req_t *dludp;
813 	int		dladdroff;
814 	int		dladdrlen;
815 	int		msize;
816 	int		error = 0;
817 	boolean_t	is_promisc;
818 
819 	ASSERT(q != NULL && q->q_ptr != NULL);
820 	ASSERT(mp != NULL && mp->b_rptr != NULL);
821 	ASSERT((MTYPE(mp) == M_PCPROTO) || (MTYPE(mp) == M_PROTO));
822 	dludp = (dl_unitdata_req_t *)mp->b_rptr;
823 	dladdroff = dludp->dl_dest_addr_offset;
824 	dladdrlen = dludp->dl_dest_addr_length;
825 	ASSERT(sps != NULL);
826 	ASSERT(!IS_SPS_PIOATTACH(sps));
827 	ASSERT(sps->sps_dlstate == DL_IDLE);
828 	ASSERT(q->q_ptr == sps);
829 	/*
830 	 * If this stream is not attached to any ppas, then discard data
831 	 * coming down through this stream.
832 	 */
833 	ppa = sps->sps_ppa;
834 	if (ppa == NULL) {
835 		DBGERROR((CE_CONT, "DLPI unitdata: no attached ppa\n"));
836 		error = ENOLINK;
837 	} else if (mp->b_cont == NULL) {
838 		DBGERROR((CE_CONT, "DLPI unitdata: missing data\n"));
839 		error = EPROTO;
840 	}
841 	if (error != 0) {
842 		dluderrorind(q, mp, mp->b_rptr + dladdroff, dladdrlen,
843 		    DL_BADDATA, error);
844 		return (0);
845 	}
846 	ASSERT(mp->b_cont->b_rptr != NULL);
847 	/*
848 	 * Check if outgoing packet size is larger than allowed. We use
849 	 * msgdsize to count all of M_DATA blocks in the message.
850 	 */
851 	msize = msgdsize(mp);
852 	if (msize > ppa->ppa_mtu) {
853 		/* Log, and send it anyway */
854 		mutex_enter(&ppa->ppa_sta_lock);
855 		ppa->ppa_otoolongs++;
856 		mutex_exit(&ppa->ppa_sta_lock);
857 	}
858 	if (IS_SPS_KDEBUG(sps)) {
859 		SPDEBUG(PPP_DRV_NAME
860 		    "/%d: DL_UNITDATA_REQ (%d bytes) sps=0x%p flags=0x%b "
861 		    "ppa=0x%p flags=0x%b\n", sps->sps_mn_id, msize,
862 		    (void *)sps, sps->sps_flags, SPS_FLAGS_STR,
863 		    (void *)ppa, ppa->ppa_flags, PPA_FLAGS_STR);
864 	}
865 	/* Allocate a message (M_DATA) to contain PPP header bytes. */
866 	if ((hdrmp = allocb(PPP_HDRLEN, BPRI_MED)) == NULL) {
867 		mutex_enter(&ppa->ppa_sta_lock);
868 		ppa->ppa_allocbfail++;
869 		mutex_exit(&ppa->ppa_sta_lock);
870 		DBGERROR((CE_CONT,
871 		    "DLPI unitdata: can't allocate header buffer\n"));
872 		dluderrorind(q, mp, mp->b_rptr + dladdroff, dladdrlen,
873 		    DL_SYSERR, ENOSR);
874 		return (0);
875 	}
876 	/*
877 	 * Should there be any promiscuous stream(s), send the data up
878 	 * for each promiscuous stream that we recognize.
879 	 */
880 	rw_enter(&ppa->ppa_sib_lock, RW_READER);
881 	is_promisc = ppa->ppa_promicnt;
882 	if (is_promisc) {
883 		ASSERT(ppa->ppa_streams != NULL);
884 		sppp_dlprsendup(ppa->ppa_streams, mp->b_cont, sps->sps_sap,
885 		    B_FALSE);
886 	}
887 	rw_exit(&ppa->ppa_sib_lock);
888 	/* Discard DLPI header and keep only IP payload (mp->b_cont). */
889 	pktmp = mp->b_cont;
890 	mp->b_cont = NULL;
891 	freemsg(mp);
892 	mp = hdrmp;
893 
894 	*(uchar_t *)mp->b_wptr++ = PPP_ALLSTATIONS;
895 	*(uchar_t *)mp->b_wptr++ = PPP_UI;
896 	*(uchar_t *)mp->b_wptr++ = ((uint16_t)sps->sps_sap >> 8) & 0xff;
897 	*(uchar_t *)mp->b_wptr++ = ((uint16_t)sps->sps_sap) & 0xff;
898 	ASSERT(MBLKL(mp) == PPP_HDRLEN);
899 
900 	linkb(mp, pktmp);
901 	/*
902 	 * Only time-stamp the packet with hrtime if the upper stream
903 	 * is configured to do so.
904 	 */
905 	if (IS_PPA_TIMESTAMP(ppa)) {
906 		ppa->ppa_lasttx = gethrtime();
907 	}
908 	/*
909 	 * Just put this back on the queue and allow the write service
910 	 * routine to handle it.  We're nested too deeply here to
911 	 * rewind the stack sufficiently to prevent overflow.  This is
912 	 * the slow path anyway.
913 	 */
914 	if (putq(q, mp) == 0) {
915 		mutex_enter(&ppa->ppa_sta_lock);
916 		ppa->ppa_oqdropped++;
917 		mutex_exit(&ppa->ppa_sta_lock);
918 		freemsg(mp);
919 	} else {
920 		qenable(q);
921 	}
922 	return (0);
923 }
924 
925 /*
926  * sppp_dlpromisconreq()
927  *
928  * MT-Perimeters:
929  *    shared inner, shared outer.
930  *
931  * Description:
932  *    Perform DL_PROMISCON_REQ request, called by sppp_mproto.
933  */
934 static int
935 sppp_dlpromisconreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
936 {
937 	t_uscalar_t	level;
938 
939 	ASSERT(q != NULL && q->q_ptr != NULL);
940 	ASSERT(mp != NULL && mp->b_rptr != NULL);
941 	level = ((dl_promiscon_req_t *)mp->b_rptr)->dl_level;
942 	ASSERT(sps != NULL);
943 
944 	/* snoop issues DL_PROMISCON_REQ more than once. */
945 	if (IS_SPS_PROMISC(sps)) {
946 		dlokack(q, mp, DL_PROMISCON_REQ);
947 	} else if ((level != DL_PROMISC_PHYS) && (level != DL_PROMISC_SAP) &&
948 	    (level != DL_PROMISC_MULTI)) {
949 		DBGERROR((CE_CONT, "DLPI promiscon: bad level %d\n", level));
950 		dlerrorack(q, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
951 	} else {
952 		qwriter(q, mp, sppp_dl_promiscon, PERIM_INNER);
953 	}
954 	return (0);
955 }
956 
957 /*
958  * sppp_dl_promiscon()
959  *
960  * MT-Perimeters:
961  *    exclusive inner, shared outer.
962  *
963  * Description:
964  *    Called by qwriter (INNER) from sppp_dlpromisconreq as the result of
965  *    receiving a DL_PROMISCON_REQ message.
966  */
967 static void
968 sppp_dl_promiscon(queue_t *q, mblk_t *mp)
969 {
970 	spppstr_t	*sps;
971 	sppa_t		*ppa;
972 
973 	ASSERT(q != NULL && q->q_ptr != NULL);
974 	sps = (spppstr_t *)q->q_ptr;
975 	ASSERT(!IS_SPS_PROMISC(sps));
976 	ASSERT(mp != NULL && mp->b_rptr != NULL);
977 	ppa = sps->sps_ppa;
978 
979 	sps->sps_flags |= SPS_PROMISC;
980 	/*
981 	 * We can't be sure that the sps_ppa field is valid, since the DLPI
982 	 * spec says that DL_PROMISCON_REQ can be issued at any state, i.e.,
983 	 * the request can be issued even before DL_ATTACH_REQ or PPPIO_ATTACH
984 	 * be issued to associate this stream with a ppa.
985 	 */
986 	if (ppa != NULL) {
987 		rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
988 		ppa->ppa_promicnt++;
989 		rw_exit(&ppa->ppa_sib_lock);
990 	}
991 	DBGDLPI((CE_CONT, "/%d: promiscuous mode on\n", sps->sps_mn_id));
992 	dlokack(q, mp, DL_PROMISCON_REQ);
993 }
994 
995 /*
996  * sppp_dlpromiscoffreq()
997  *
998  * MT-Perimeters:
999  *    shared inner, shared outer.
1000  *
1001  * Description:
1002  *    Perform DL_PROMISCOFF_REQ request, called by sppp_mproto.
1003  */
1004 static int
1005 sppp_dlpromiscoffreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
1006 {
1007 	t_uscalar_t	level;
1008 
1009 	ASSERT(q != NULL && q->q_ptr != NULL);
1010 	ASSERT(mp != NULL && mp->b_rptr != NULL);
1011 	level = ((dl_promiscoff_req_t *)mp->b_rptr)->dl_level;
1012 	ASSERT(sps != NULL);
1013 
1014 	if (!IS_SPS_PROMISC(sps)) {
1015 		DBGERROR((CE_CONT, "DLPI promiscoff: not promiscuous\n"));
1016 		dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
1017 	} else if ((level != DL_PROMISC_PHYS) && (level != DL_PROMISC_SAP) &&
1018 	    (level != DL_PROMISC_MULTI)) {
1019 		dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
1020 		DBGERROR((CE_CONT, "DLPI promiscoff: bad level %d\n", level));
1021 	} else {
1022 		qwriter(q, mp, sppp_dl_promiscoff, PERIM_INNER);
1023 	}
1024 	return (0);
1025 
1026 }
1027 
1028 /*
1029  * sppp_dl_promiscoff()
1030  *
1031  * MT-Perimeters:
1032  *    exclusive inner, shared outer.
1033  *
1034  * Description:
1035  *    Called by qwriter (INNER) from sppp_dlpromiscoffreq as the result of
1036  *    receiving a DL_PROMISCOFF_REQ message.
1037  */
1038 static void
1039 sppp_dl_promiscoff(queue_t *q, mblk_t *mp)
1040 {
1041 	spppstr_t	*sps;
1042 	sppa_t		*ppa;
1043 
1044 	ASSERT(q != NULL && q->q_ptr != NULL);
1045 	sps = (spppstr_t *)q->q_ptr;
1046 	ASSERT(IS_SPS_PROMISC(sps));
1047 	ASSERT(mp != NULL && mp->b_rptr != NULL);
1048 	ppa = sps->sps_ppa;
1049 
1050 	sps->sps_flags &= ~SPS_PROMISC;
1051 	/*
1052 	 * We can't be guaranteed that the sps_ppa field is still valid, since
1053 	 * the control stream might have been closed earlier, in which case
1054 	 * the close procedure would have NULL'd out the sps_ppa.
1055 	 */
1056 	if (ppa != NULL) {
1057 		rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
1058 		ASSERT(ppa->ppa_promicnt > 0);
1059 		ppa->ppa_promicnt--;
1060 		rw_exit(&ppa->ppa_sib_lock);
1061 	}
1062 	DBGDLPI((CE_CONT, "/%d: promiscuous mode off\n", sps->sps_mn_id));
1063 	dlokack(q, mp, DL_PROMISCOFF_REQ);
1064 }
1065 
1066 /*
1067  * sppp_dlphyreq()
1068  *
1069  * MT-Perimeters:
1070  *    shared inner, shared outer.
1071  *
1072  * Description:
1073  *    Perform DL_PHYS_ADDR_REQ request, called by sppp_mproto. This doesn't
1074  *    return anything useful, but it keeps ifconfig happy.
1075  */
1076 /* ARGSUSED */
1077 static int
1078 sppp_dlphyreq(queue_t *q, mblk_t *mp, spppstr_t *us)
1079 {
1080 	static struct ether_addr addr = { 0 };
1081 
1082 	dlphysaddrack(q, mp, (char *)&addr, ETHERADDRL);
1083 	return (0);
1084 }
1085 
1086 /*
1087  * sppp_dladdether()
1088  *
1089  * Description:
1090  *    Prepend an empty Ethernet header to msg for snoop, et al. Free
1091  *    the original mblk if alloc fails. Only called for the purpose of sending
1092  *    packets up the promiscous stream.
1093  */
1094 /* ARGSUSED */
1095 static mblk_t *
1096 sppp_dladdether(spppstr_t *sps, mblk_t *mp, t_scalar_t proto)
1097 {
1098 	mblk_t		*eh;
1099 	t_scalar_t	type;
1100 
1101 	if ((eh = allocb(sizeof (struct ether_header), BPRI_MED)) == NULL) {
1102 		freemsg(mp);
1103 		return (NULL);
1104 	}
1105 	if (proto == PPP_IP) {
1106 		type = ETHERTYPE_IP;
1107 	} else if (proto == PPP_IPV6) {
1108 		type = ETHERTYPE_IPV6;
1109 	} else {
1110 		/*
1111 		 * For all other protocols, end this up as an ETHERTYPE_PPP
1112 		 * type of packet. Since we've skipped the PPP headers in the
1113 		 * caller, make sure that we restore it. We know for sure that
1114 		 * the PPP header still exists in the message (only skipped),
1115 		 * since the sender of this message is pppd and it must have
1116 		 * included the PPP header in front.
1117 		 */
1118 		type = ETHERTYPE_PPP;
1119 		mp->b_rptr -= PPP_HDRLEN;
1120 		ASSERT(mp->b_rptr >= mp->b_datap->db_base);
1121 	}
1122 	eh->b_wptr += sizeof (struct ether_header);
1123 	bzero((caddr_t)eh->b_rptr, sizeof (struct ether_header));
1124 	((struct ether_header *)eh->b_rptr)->ether_type = htons((int16_t)type);
1125 
1126 	linkb(eh, mp);
1127 	return (eh);
1128 }
1129 
1130 /*
1131  * sppp_dladdud()
1132  *
1133  * Description:
1134  *    Prepend DL_UNITDATA_IND mblk to msg, free original alloc fails.
1135  */
1136 /* ARGSUSED */
1137 mblk_t *
1138 sppp_dladdud(spppstr_t *sps, mblk_t *mp, t_scalar_t proto, boolean_t promisc)
1139 {
1140 	dl_unitdata_ind_t *dlu;
1141 	mblk_t		*dh;
1142 	size_t		size;
1143 	t_scalar_t	type;
1144 
1145 	size = sizeof (dl_unitdata_ind_t) + (2 * SPPP_ADDRL);
1146 	if ((dh = allocb(size, BPRI_MED)) == NULL) {
1147 		freemsg(mp);
1148 		return (NULL);
1149 	}
1150 
1151 	dh->b_datap->db_type = M_PROTO;
1152 	dh->b_wptr = dh->b_datap->db_lim;
1153 	dh->b_rptr = dh->b_wptr - size;
1154 
1155 	dlu = (dl_unitdata_ind_t *)dh->b_rptr;
1156 	dlu->dl_primitive = DL_UNITDATA_IND;
1157 	dlu->dl_dest_addr_length = SPPP_ADDRL;
1158 	dlu->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
1159 	dlu->dl_src_addr_length = SPPP_ADDRL;
1160 	dlu->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + SPPP_ADDRL;
1161 	dlu->dl_group_address = 0;
1162 
1163 	if (promisc) {
1164 		if (proto == PPP_IP) {
1165 			type = ETHERTYPE_IP;
1166 		} else if (proto == PPP_IPV6) {
1167 			type = ETHERTYPE_IPV6;
1168 		} else {
1169 			/*
1170 			 * For all other protocols, send this up as an
1171 			 * ETHERTYPE_PPP type of packet. Since we've skipped
1172 			 * the PPP headers in the caller, make sure that we
1173 			 * restore it. We know for sure that the PPP header
1174 			 * still exists in the message (only skipped), since
1175 			 * the sender of this message is pppd and it must
1176 			 * have included the PPP header in front.
1177 			 */
1178 			type = ETHERTYPE_PPP;
1179 			mp->b_rptr -= PPP_HDRLEN;
1180 			ASSERT(mp->b_rptr >= mp->b_datap->db_base);
1181 		}
1182 	} else {
1183 		type = sps->sps_req_sap;
1184 	}
1185 	/*
1186 	 * Send the DLPI client the data with the SAP they requested,
1187 	 * (e.g. ETHERTYPE_IP) rather than the PPP protocol (e.g. PPP_IP).
1188 	 */
1189 	((spppreqsap_t *)(dlu + 1))[0] = type;
1190 	((spppreqsap_t *)(dlu + 1))[1] = type;
1191 
1192 	linkb(dh, mp);
1193 	return (dh);
1194 }
1195 
1196 /*
1197  * sppp_dlprsendup()
1198  *
1199  * Description:
1200  *    For any valid promiscuous streams (marked with SPS_PROMISC and its
1201  *    sps_dlstate is DL_IDLE), send data upstream. The caller is expected
1202  *    to hold ppa_sib_lock when calling this procedure.
1203  */
1204 void
1205 sppp_dlprsendup(spppstr_t *sps, mblk_t *mp, t_scalar_t proto, boolean_t header)
1206 {
1207 	sppa_t	*ppa;
1208 	mblk_t	*dmp;
1209 
1210 	ASSERT(sps != NULL);
1211 	ASSERT(mp != NULL && mp->b_rptr != NULL);
1212 	ppa = sps->sps_ppa;
1213 	ASSERT(ppa != NULL);
1214 
1215 	/* NOTE: caller must hold ppa_sib_lock in RW_READER mode */
1216 	ASSERT(RW_READ_HELD(&ppa->ppa_sib_lock));
1217 
1218 	for (; sps != NULL; sps = sps->sps_nextsib) {
1219 		/*
1220 		 * We specifically test to ensure that the DLPI state for the
1221 		 * promiscous stream is IDLE (DL_IDLE), since such state tells
1222 		 * us that the promiscous stream has been bound to PPP_ALLSAP.
1223 		 */
1224 		if (IS_SPS_PROMISC(sps) && (sps->sps_dlstate == DL_IDLE) &&
1225 		    canputnext(sps->sps_rq)) {
1226 			if ((dmp = dupmsg(mp)) == NULL) {
1227 				mutex_enter(&ppa->ppa_sta_lock);
1228 				ppa->ppa_allocbfail++;
1229 				mutex_exit(&ppa->ppa_sta_lock);
1230 				continue;
1231 			}
1232 			if (header) {
1233 				dmp->b_rptr += PPP_HDRLEN;
1234 			}
1235 			if (IS_SPS_RAWDATA(sps)) {
1236 				/* function frees original message if fails */
1237 				dmp = sppp_dladdether(sps, dmp, proto);
1238 			} else {
1239 				/* function frees original message if fails */
1240 				dmp = sppp_dladdud(sps, dmp, proto, B_TRUE);
1241 			}
1242 			if (dmp != NULL) {
1243 				putnext(sps->sps_rq, dmp);
1244 			} else {
1245 				mutex_enter(&ppa->ppa_sta_lock);
1246 				ppa->ppa_allocbfail++;
1247 				mutex_exit(&ppa->ppa_sta_lock);
1248 			}
1249 		}
1250 	}
1251 }
1252