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