2 * sppp_dlpi.c - Solaris STREAMS PPP multiplexing pseudo-driver DLPI handlers
4 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
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.
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
18 * Copyright (c) 1994 The Australian National University.
19 * All rights reserved.
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
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
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,
41 * This driver is derived from the original SVR4 STREAMS PPP driver
42 * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
44 * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
45 * for improved performance and scalability.
48 #define RCSID "$Id: sppp_dlpi.c,v 1.0 2000/05/08 01:10:12 masputra Exp $"
50 #include <sys/types.h>
51 #include <sys/param.h>
53 #include <sys/stream.h>
54 #include <sys/stropts.h>
55 #include <sys/errno.h>
57 #include <sys/cmn_err.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>
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
);
88 static struct sppp_dlpi_pinfo_t dl_pinfo
[DL_MAXPRIM
+ 1];
91 #define DBGERROR(x) cmn_err x
93 #define DBGERROR(x) ((void)0)
96 /* #define DBG_DLPI 1 */
99 struct sppp_dlpi_entry
{
101 const char *sde_name
;
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" },
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" },
188 prim2name(uint32_t prim
)
190 const struct sppp_dlpi_entry
*sde
;
192 for (sde
= sppp_dlpi_list
; sde
->sde_name
!= NULL
; sde
++)
193 if (sde
->sde_val
== prim
)
195 return (sde
->sde_name
);
199 state2name(uint32_t state
)
201 const struct sppp_dlpi_entry
*sde
;
203 for (sde
= sppp_state_list
; sde
->sde_name
!= NULL
; sde
++)
204 if (sde
->sde_val
== state
)
206 return (sde
->sde_name
);
209 #define DBGDLPI(x) cmn_err x
211 #define DBGDLPI(x) ((void)0)
212 #endif /* DBG_DLPI */
215 * DL_INFO_ACK template for point-to-point interface.
217 static dl_info_ack_t sppp_infoack
= {
218 DL_INFO_ACK
, /* dl_primitive */
219 PPP_MAXMTU
, /* dl_max_sdu */
221 SPPP_ADDRL
, /* dl_addr_length */
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.
227 DL_ETHER
, /* dl_mac_type */
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 */
245 * sppp_dlpi_pinfoinit()
248 * Initialize dl_pinfo[], called from sppp_attach.
251 sppp_dlpi_pinfoinit(void)
253 bzero(dl_pinfo
, sizeof (dl_pinfo
)); /* Just to be safe */
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
296 * shared inner, shared outer.
299 * Handle M_PCPROTO/M_PROTO messages, called by sppp_uwput.
302 sppp_mproto(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
304 union DL_primitives
*dlp
;
305 struct sppp_dlpi_pinfo_t
*dpi
;
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
);
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
,
323 dpi
= &dl_pinfo
[prim
];
324 if (dpi
->pi_funcp
== NULL
) {
326 "bad mproto: primitive %d not supported\n", prim
));
327 error
= DL_NOTSUPPORTED
;
328 } else if (len
< dpi
->pi_minlen
) {
330 "bad mproto: primitive len %d < %d\n", len
,
333 } else if (dpi
->pi_state
!= -1 &&
334 sps
->sps_dlstate
!= dpi
->pi_state
) {
336 "bad state %d != %d for primitive %d\n",
337 sps
->sps_dlstate
, dpi
->pi_state
, prim
));
342 dlerrorack(q
, mp
, dlp
->dl_primitive
, error
, 0);
347 const char *cp
= prim2name(prim
);
349 cmn_err(CE_CONT
, "/%d: Dispatching %s\n",
353 "/%d: Dispatching unknown primitive %d\n",
354 sps
->sps_mn_id
, prim
);
357 return ((*dpi
->pi_funcp
)(q
, mp
, sps
));
364 * shared inner, shared outer.
367 * Perform DL_ATTACH_REQ request, called by sppp_mproto.
370 sppp_dlattachreq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
373 union DL_primitives
*dlp
;
375 ASSERT(q
!= NULL
&& q
->q_ptr
!= NULL
);
376 ASSERT(mp
!= NULL
&& mp
->b_rptr
!= NULL
);
377 dlp
= (union DL_primitives
*)mp
->b_rptr
;
379 ASSERT(sps
->sps_dlstate
== DL_UNATTACHED
);
381 if (IS_SPS_PIOATTACH(sps
)) {
382 DBGERROR((CE_CONT
, "DLPI attach: already attached\n"));
386 dlerrorack(q
, mp
, dlp
->dl_primitive
, DL_OUTSTATE
, error
);
388 qwriter(q
, mp
, sppp_dl_attach_upper
, PERIM_OUTER
);
394 * sppp_dl_attach_upper()
397 * exclusive inner, exclusive outer.
400 * Called by qwriter (INNER) from sppp_dlattachreq as the result of
401 * receiving a DL_ATTACH_REQ message.
404 sppp_dl_attach_upper(queue_t
*q
, mblk_t
*mp
)
407 spppstr_t
*sps
= q
->q_ptr
;
408 union DL_primitives
*dlp
;
413 ASSERT(!IS_SPS_PIOATTACH(sps
));
414 dlp
= (union DL_primitives
*)mp
->b_rptr
;
416 /* If there's something here, it's detached. */
417 if (sps
->sps_ppa
!= NULL
) {
418 sppp_remove_ppa(sps
);
421 if ((cr
= msg_getcred(mp
, NULL
)) == NULL
)
422 zoneid
= sps
->sps_zoneid
;
424 zoneid
= crgetzoneid(cr
);
426 ppa
= sppp_find_ppa(dlp
->attach_req
.dl_ppa
);
428 ppa
= sppp_create_ppa(dlp
->attach_req
.dl_ppa
, zoneid
);
429 } else if (ppa
->ppa_zoneid
!= zoneid
) {
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.
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
);
445 * Preallocate the hangup message so that we're always able to
446 * send this upstream in the event of a catastrophic failure.
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
);
453 sps
->sps_dlstate
= DL_UNBOUND
;
456 * Add this stream to the head of the list of sibling streams
457 * which belong to the specified ppa.
459 rw_enter(&ppa
->ppa_sib_lock
, RW_WRITER
);
461 sps
->sps_nextsib
= ppa
->ppa_streams
;
462 ppa
->ppa_streams
= sps
;
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.
468 if (IS_SPS_PROMISC(sps
)) {
471 rw_exit(&ppa
->ppa_sib_lock
);
472 DBGDLPI((CE_CONT
, "/%d: attached to ppa %d\n", sps
->sps_mn_id
,
474 dlokack(q
, mp
, DL_ATTACH_REQ
);
481 * shared inner, shared outer.
484 * Perform DL_DETACH_REQ request, called by sppp_mproto.
488 sppp_dldetachreq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
490 ASSERT(q
!= NULL
&& q
->q_ptr
!= NULL
);
491 ASSERT(mp
!= NULL
&& mp
->b_rptr
!= NULL
);
493 ASSERT(sps
->sps_dlstate
== DL_UNBOUND
);
494 ASSERT(!IS_SPS_PIOATTACH(sps
));
496 qwriter(q
, mp
, sppp_dl_detach_upper
, PERIM_INNER
);
501 * sppp_dl_detach_upper()
504 * exclusive inner, shared outer.
507 * Called by qwriter (INNER) from sppp_dldetachreq as the result of
508 * receiving a DL_DETACH_REQ message.
512 sppp_dl_detach_upper(queue_t
*q
, mblk_t
*mp
)
516 ASSERT(q
!= NULL
&& q
->q_ptr
!= NULL
);
517 ASSERT(mp
!= NULL
&& mp
->b_rptr
!= NULL
);
518 sps
= (spppstr_t
*)q
->q_ptr
;
520 * We don't actually detach from the PPA until closed or
523 sps
->sps_flags
&= ~SPS_PROMISC
; /* clear flag anyway */
524 sps
->sps_dlstate
= DL_UNATTACHED
;
525 dlokack(q
, mp
, DL_DETACH_REQ
);
532 * shared inner, shared outer.
535 * Perform DL_BIND_REQ request, called by sppp_mproto.
538 sppp_dlbindreq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
541 union DL_primitives
*dlp
;
542 spppreqsap_t req_sap
;
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
;
550 ASSERT(!IS_SPS_PIOATTACH(sps
));
551 ASSERT(sps
->sps_dlstate
== DL_UNBOUND
);
555 DBGERROR((CE_CONT
, "DLPI bind: no attached ppa\n"));
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
));
563 dlerrorack(q
, mp
, dlp
->dl_primitive
, error
, 0);
565 qwriter(q
, mp
, sppp_dl_bind
, PERIM_INNER
);
574 * exclusive inner, shared outer.
577 * Called by qwriter (INNER) from sppp_dlbindreq as the result of
578 * receiving a DL_BIND_REQ message.
581 sppp_dl_bind(queue_t
*q
, mblk_t
*mp
)
585 union DL_primitives
*dlp
;
587 spppreqsap_t req_sap
;
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
;
596 req_sap
= dlp
->bind_req
.dl_sap
;
597 ASSERT((req_sap
== ETHERTYPE_IP
) || (req_sap
== ETHERTYPE_IPV6
) ||
598 (req_sap
== ETHERTYPE_ALLSAP
));
600 if (req_sap
== ETHERTYPE_IP
) {
602 } else if (req_sap
== ETHERTYPE_IPV6
) {
604 } else if (req_sap
== ETHERTYPE_ALLSAP
) {
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.
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
);
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
);
626 DBGERROR((CE_CONT
, "DLPI bind: bad SAP %x\n", sap
));
627 dlerrorack(q
, mp
, dlp
->dl_primitive
, DL_NOADDR
,
631 sps
->sps_flags
|= SPS_CACHED
;
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).
637 if (lsmp
!= NULL
&& ppa
->ppa_ctl
!= NULL
) {
639 cmn_err(CE_CONT
, "sending up %s\n",
640 ((sap
== PPP_IP
) ? "PPP_LINKSTAT_IPV4_BOUND" :
641 "PPP_LINKSTAT_IPV6_BOUND"));
643 putnext(ppa
->ppa_ctl
->sps_rq
, lsmp
);
645 DBGDLPI((CE_CONT
, "/%d: bound to sap %X (req %X)\n", sps
->sps_mn_id
,
647 sps
->sps_req_sap
= req_sap
;
649 sps
->sps_dlstate
= DL_IDLE
;
650 dlbindack(q
, mp
, req_sap
, &sap
, sizeof (int32_t), 0, 0);
657 * shared inner, shared outer.
660 * Perform DL_UNBIND_REQ request, called by sppp_mproto.
664 sppp_dlunbindreq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
666 ASSERT(q
!= NULL
&& q
->q_ptr
!= NULL
);
667 ASSERT(mp
!= NULL
&& mp
->b_rptr
!= NULL
);
669 ASSERT(!IS_SPS_PIOATTACH(sps
));
670 ASSERT(sps
->sps_dlstate
== DL_IDLE
);
672 qwriter(q
, mp
, sppp_dl_unbind
, PERIM_INNER
);
680 * exclusive inner, shared outer.
683 * Called by qwriter (INNER) from sppp_dlunbindreq as the result of
684 * receiving a DL_UNBIND_REQ message.
687 sppp_dl_unbind(queue_t
*q
, mblk_t
*mp
)
695 ASSERT(q
!= NULL
&& q
->q_ptr
!= NULL
);
696 sps
= (spppstr_t
*)q
->q_ptr
;
698 ASSERT(mp
!= NULL
&& mp
->b_rptr
!= NULL
);
700 ASSERT((sap
== PPP_IP
) || (sap
== PPP_IPV6
) || (sap
== PPP_ALLSAP
));
702 /* Flush messages on unbind, per DLPI specification. */
703 flushq(WR(q
), FLUSHALL
);
704 flushq(RD(q
), FLUSHALL
);
706 if ((ppa
!= NULL
) && IS_SPS_CACHED(sps
)) {
707 sps
->sps_flags
&= ~SPS_CACHED
;
709 saydown
= (ppa
->ppa_ctl
!= NULL
&&
710 (sps
->sps_npmode
== NPMODE_PASS
||
711 sps
->sps_npmode
== NPMODE_QUEUE
));
713 ppa
->ppa_ip_cache
= NULL
;
715 msg
= create_lsmsg(PPP_LINKSTAT_IPV4_UNBOUND
);
716 } else if (sap
== PPP_IPV6
) {
717 ppa
->ppa_ip6_cache
= NULL
;
719 msg
= create_lsmsg(PPP_LINKSTAT_IPV6_UNBOUND
);
723 cmn_err(CE_CONT
, "sending up %s\n",
724 ((sap
== PPP_IP
) ? "PPP_LINKSTAT_IPV4_UNBOUND" :
725 "PPP_LINKSTAT_IPV6_UNBOUND"));
727 putnext(ppa
->ppa_ctl
->sps_rq
, msg
);
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;
734 sps
->sps_dlstate
= DL_UNBOUND
;
736 dlokack(q
, mp
, DL_UNBIND_REQ
);
743 * shared inner, shared outer.
746 * Perform DL_INFO_REQ request, called by sppp_mproto.
749 sppp_dlinforeq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
756 ASSERT(q
!= NULL
&& q
->q_ptr
!= NULL
);
757 ASSERT(mp
!= NULL
&& mp
->b_rptr
!= NULL
);
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 */
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
;
776 const char *cp
= state2name(dlip
->dl_current_state
);
778 cmn_err(CE_CONT
, "info returns state %s, max sdu %d\n",
779 cp
, dlip
->dl_max_sdu
);
781 cmn_err(CE_CONT
, "info returns state %d, max sdu %d\n",
782 dlip
->dl_current_state
, dlip
->dl_max_sdu
);
790 * sppp_dlunitdatareq()
793 * shared inner, shared outer.
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.
807 sppp_dlunitdatareq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
812 dl_unitdata_req_t
*dludp
;
817 boolean_t is_promisc
;
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
;
826 ASSERT(!IS_SPS_PIOATTACH(sps
));
827 ASSERT(sps
->sps_dlstate
== DL_IDLE
);
828 ASSERT(q
->q_ptr
== sps
);
830 * If this stream is not attached to any ppas, then discard data
831 * coming down through this stream.
835 DBGERROR((CE_CONT
, "DLPI unitdata: no attached ppa\n"));
837 } else if (mp
->b_cont
== NULL
) {
838 DBGERROR((CE_CONT
, "DLPI unitdata: missing data\n"));
842 dluderrorind(q
, mp
, mp
->b_rptr
+ dladdroff
, dladdrlen
,
846 ASSERT(mp
->b_cont
->b_rptr
!= NULL
);
848 * Check if outgoing packet size is larger than allowed. We use
849 * msgdsize to count all of M_DATA blocks in the message.
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
);
858 if (IS_SPS_KDEBUG(sps
)) {
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
);
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
);
871 "DLPI unitdata: can't allocate header buffer\n"));
872 dluderrorind(q
, mp
, mp
->b_rptr
+ dladdroff
, dladdrlen
,
877 * Should there be any promiscuous stream(s), send the data up
878 * for each promiscuous stream that we recognize.
880 rw_enter(&ppa
->ppa_sib_lock
, RW_READER
);
881 is_promisc
= ppa
->ppa_promicnt
;
883 ASSERT(ppa
->ppa_streams
!= NULL
);
884 sppp_dlprsendup(ppa
->ppa_streams
, mp
->b_cont
, sps
->sps_sap
,
887 rw_exit(&ppa
->ppa_sib_lock
);
888 /* Discard DLPI header and keep only IP payload (mp->b_cont). */
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
);
902 * Only time-stamp the packet with hrtime if the upper stream
903 * is configured to do so.
905 if (IS_PPA_TIMESTAMP(ppa
)) {
906 ppa
->ppa_lasttx
= gethrtime();
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.
914 if (putq(q
, mp
) == 0) {
915 mutex_enter(&ppa
->ppa_sta_lock
);
916 ppa
->ppa_oqdropped
++;
917 mutex_exit(&ppa
->ppa_sta_lock
);
926 * sppp_dlpromisconreq()
929 * shared inner, shared outer.
932 * Perform DL_PROMISCON_REQ request, called by sppp_mproto.
935 sppp_dlpromisconreq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
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
;
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);
952 qwriter(q
, mp
, sppp_dl_promiscon
, PERIM_INNER
);
958 * sppp_dl_promiscon()
961 * exclusive inner, shared outer.
964 * Called by qwriter (INNER) from sppp_dlpromisconreq as the result of
965 * receiving a DL_PROMISCON_REQ message.
968 sppp_dl_promiscon(queue_t
*q
, mblk_t
*mp
)
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
);
979 sps
->sps_flags
|= SPS_PROMISC
;
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.
987 rw_enter(&ppa
->ppa_sib_lock
, RW_WRITER
);
989 rw_exit(&ppa
->ppa_sib_lock
);
991 DBGDLPI((CE_CONT
, "/%d: promiscuous mode on\n", sps
->sps_mn_id
));
992 dlokack(q
, mp
, DL_PROMISCON_REQ
);
996 * sppp_dlpromiscoffreq()
999 * shared inner, shared outer.
1002 * Perform DL_PROMISCOFF_REQ request, called by sppp_mproto.
1005 sppp_dlpromiscoffreq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*sps
)
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
);
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
));
1022 qwriter(q
, mp
, sppp_dl_promiscoff
, PERIM_INNER
);
1029 * sppp_dl_promiscoff()
1032 * exclusive inner, shared outer.
1035 * Called by qwriter (INNER) from sppp_dlpromiscoffreq as the result of
1036 * receiving a DL_PROMISCOFF_REQ message.
1039 sppp_dl_promiscoff(queue_t
*q
, mblk_t
*mp
)
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
);
1050 sps
->sps_flags
&= ~SPS_PROMISC
;
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.
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
);
1062 DBGDLPI((CE_CONT
, "/%d: promiscuous mode off\n", sps
->sps_mn_id
));
1063 dlokack(q
, mp
, DL_PROMISCOFF_REQ
);
1070 * shared inner, shared outer.
1073 * Perform DL_PHYS_ADDR_REQ request, called by sppp_mproto. This doesn't
1074 * return anything useful, but it keeps ifconfig happy.
1078 sppp_dlphyreq(queue_t
*q
, mblk_t
*mp
, spppstr_t
*us
)
1080 static struct ether_addr addr
= { 0 };
1082 dlphysaddrack(q
, mp
, (char *)&addr
, ETHERADDRL
);
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.
1096 sppp_dladdether(spppstr_t
*sps
, mblk_t
*mp
, t_scalar_t proto
)
1101 if ((eh
= allocb(sizeof (struct ether_header
), BPRI_MED
)) == NULL
) {
1105 if (proto
== PPP_IP
) {
1106 type
= ETHERTYPE_IP
;
1107 } else if (proto
== PPP_IPV6
) {
1108 type
= ETHERTYPE_IPV6
;
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.
1118 type
= ETHERTYPE_PPP
;
1119 mp
->b_rptr
-= PPP_HDRLEN
;
1120 ASSERT(mp
->b_rptr
>= mp
->b_datap
->db_base
);
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
);
1134 * Prepend DL_UNITDATA_IND mblk to msg, free original alloc fails.
1138 sppp_dladdud(spppstr_t
*sps
, mblk_t
*mp
, t_scalar_t proto
, boolean_t promisc
)
1140 dl_unitdata_ind_t
*dlu
;
1145 size
= sizeof (dl_unitdata_ind_t
) + (2 * SPPP_ADDRL
);
1146 if ((dh
= allocb(size
, BPRI_MED
)) == NULL
) {
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
;
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;
1164 if (proto
== PPP_IP
) {
1165 type
= ETHERTYPE_IP
;
1166 } else if (proto
== PPP_IPV6
) {
1167 type
= ETHERTYPE_IPV6
;
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.
1178 type
= ETHERTYPE_PPP
;
1179 mp
->b_rptr
-= PPP_HDRLEN
;
1180 ASSERT(mp
->b_rptr
>= mp
->b_datap
->db_base
);
1183 type
= sps
->sps_req_sap
;
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).
1189 ((spppreqsap_t
*)(dlu
+ 1))[0] = type
;
1190 ((spppreqsap_t
*)(dlu
+ 1))[1] = type
;
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.
1205 sppp_dlprsendup(spppstr_t
*sps
, mblk_t
*mp
, t_scalar_t proto
, boolean_t header
)
1210 ASSERT(sps
!= NULL
);
1211 ASSERT(mp
!= NULL
&& mp
->b_rptr
!= NULL
);
1213 ASSERT(ppa
!= NULL
);
1215 /* NOTE: caller must hold ppa_sib_lock in RW_READER mode */
1216 ASSERT(RW_READ_HELD(&ppa
->ppa_sib_lock
));
1218 for (; sps
!= NULL
; sps
= sps
->sps_nextsib
) {
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.
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
);
1233 dmp
->b_rptr
+= PPP_HDRLEN
;
1235 if (IS_SPS_RAWDATA(sps
)) {
1236 /* function frees original message if fails */
1237 dmp
= sppp_dladdether(sps
, dmp
, proto
);
1239 /* function frees original message if fails */
1240 dmp
= sppp_dladdud(sps
, dmp
, proto
, B_TRUE
);
1243 putnext(sps
->sps_rq
, dmp
);
1245 mutex_enter(&ppa
->ppa_sta_lock
);
1246 ppa
->ppa_allocbfail
++;
1247 mutex_exit(&ppa
->ppa_sta_lock
);