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 *
prim2name(uint32_t prim)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 *
state2name(uint32_t state)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
sppp_dlpi_pinfoinit(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
sppp_mproto(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dlattachreq(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dl_attach_upper(queue_t * q,mblk_t * mp)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
sppp_dldetachreq(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dl_detach_upper(queue_t * q,mblk_t * mp)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
sppp_dlbindreq(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dl_bind(queue_t * q,mblk_t * mp)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
sppp_dlunbindreq(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dl_unbind(queue_t * q,mblk_t * mp)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
sppp_dlinforeq(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dlunitdatareq(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dlpromisconreq(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dl_promiscon(queue_t * q,mblk_t * mp)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
sppp_dlpromiscoffreq(queue_t * q,mblk_t * mp,spppstr_t * sps)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
sppp_dl_promiscoff(queue_t * q,mblk_t * mp)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
sppp_dlphyreq(queue_t * q,mblk_t * mp,spppstr_t * us)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 *
sppp_dladdether(spppstr_t * sps,mblk_t * mp,t_scalar_t proto)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 *
sppp_dladdud(spppstr_t * sps,mblk_t * mp,t_scalar_t proto,boolean_t promisc)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
sppp_dlprsendup(spppstr_t * sps,mblk_t * mp,t_scalar_t proto,boolean_t header)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