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