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