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 (at) cs.anu.edu.au>. 43 * 44 * Adi Masputra <adi.masputra (at) 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(