1 /*
   2  * sppp_dlpi.c - Solaris STREAMS PPP multiplexing pseudo-driver DLPI handlers
   3  *
   4  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   5  * Use is subject to license terms.
   6  *
   7  * Permission to use, copy, modify, and distribute this software and its
   8  * documentation is hereby granted, provided that the above copyright
   9  * notice appears in all copies.
  10  *
  11  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
  12  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  13  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  14  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
  15  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  16  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
  17  *
  18  * Copyright (c) 1994 The Australian National University.
  19  * All rights reserved.
  20  *
  21  * Permission to use, copy, modify, and distribute this software and its
  22  * documentation is hereby granted, provided that the above copyright
  23  * notice appears in all copies.  This software is provided without any
  24  * warranty, express or implied. The Australian National University
  25  * makes no representations about the suitability of this software for
  26  * any purpose.
  27  *
  28  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
  29  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  30  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
  31  * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
  32  * OF SUCH DAMAGE.
  33  *
  34  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  36  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  37  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
  38  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  39  * OR MODIFICATIONS.
  40  *
  41  * This driver is derived from the original SVR4 STREAMS PPP driver
  42  * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
  43  *
  44  * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
  45  * for improved performance and scalability.
  46  */
  47 
  48 #define RCSID   "$Id: sppp_dlpi.c,v 1.0 2000/05/08 01:10:12 masputra Exp $"
  49 
  50 #include <sys/types.h>
  51 #include <sys/param.h>
  52 #include <sys/stat.h>
  53 #include <sys/stream.h>
  54 #include <sys/stropts.h>
  55 #include <sys/errno.h>
  56 #include <sys/time.h>
  57 #include <sys/cmn_err.h>
  58 #include <sys/conf.h>
  59 #include <sys/dlpi.h>
  60 #include <sys/ddi.h>
  61 #include <sys/kstat.h>
  62 #include <sys/strsubr.h>
  63 #include <sys/strsun.h>
  64 #include <sys/ethernet.h>
  65 #include <net/ppp_defs.h>
  66 #include <netinet/in.h>
  67 #include <net/pppio.h>
  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 = -1;    /* 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 = -1; /* 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 = -1; /* 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 = -1; /* 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 != -1 &&
 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 = q->q_ptr;
 408         union DL_primitives *dlp;
 409         int             err = ENOMEM;
 410         cred_t          *cr;
 411         zoneid_t        zoneid;
 412 
 413         ASSERT(!IS_SPS_PIOATTACH(sps));
 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         if ((cr = msg_getcred(mp, NULL)) == NULL)
 422                 zoneid = sps->sps_zoneid;
 423         else
 424                 zoneid = crgetzoneid(cr);
 425 
 426         ppa = sppp_find_ppa(dlp->attach_req.dl_ppa);
 427         if (ppa == NULL) {
 428                 ppa = sppp_create_ppa(dlp->attach_req.dl_ppa, zoneid);
 429         } else if (ppa->ppa_zoneid != zoneid) {
 430                 ppa = NULL;
 431                 err = EPERM;
 432         }
 433 
 434         /*
 435          * If we can't find or create it, then it's either because we're out of
 436          * memory or because the requested PPA is owned by a different zone.
 437          */
 438         if (ppa == NULL) {
 439                 DBGERROR((CE_CONT, "DLPI attach: cannot create ppa %u\n",
 440                     dlp->attach_req.dl_ppa));
 441                 dlerrorack(q, mp, dlp->dl_primitive, DL_SYSERR, err);
 442                 return;
 443         }
 444         /*
 445          * Preallocate the hangup message so that we're always able to
 446          * send this upstream in the event of a catastrophic failure.
 447          */
 448         if ((sps->sps_hangup = allocb(1, BPRI_MED)) == NULL) {
 449                 DBGERROR((CE_CONT, "DLPI attach: cannot allocate hangup\n"));
 450                 dlerrorack(q, mp, dlp->dl_primitive, DL_SYSERR, ENOSR);
 451                 return;
 452         }
 453         sps->sps_dlstate = DL_UNBOUND;
 454         sps->sps_ppa = ppa;
 455         /*
 456          * Add this stream to the head of the list of sibling streams
 457          * which belong to the specified ppa.
 458          */
 459         rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
 460         ppa->ppa_refcnt++;
 461         sps->sps_nextsib = ppa->ppa_streams;
 462         ppa->ppa_streams = sps;
 463         /*
 464          * And if this stream was marked as promiscuous (SPS_PROMISC), then we
 465          * need to update the promiscuous streams count. This should only
 466          * happen when DL_PROMISCON_REQ was issued prior to attachment.
 467          */
 468         if (IS_SPS_PROMISC(sps)) {
 469                 ppa->ppa_promicnt++;
 470         }
 471         rw_exit(&ppa->ppa_sib_lock);
 472         DBGDLPI((CE_CONT, "/%d: attached to ppa %d\n", sps->sps_mn_id,
 473             ppa->ppa_ppa_id));
 474         dlokack(q, mp, DL_ATTACH_REQ);
 475 }
 476 
 477 /*
 478  * sppp_dldetachreq()
 479  *
 480  * MT-Perimeters:
 481  *    shared inner, shared outer.
 482  *
 483  * Description:
 484  *    Perform DL_DETACH_REQ request, called by sppp_mproto.
 485  */
 486 /* ARGSUSED */
 487 static int
 488 sppp_dldetachreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
 489 {
 490         ASSERT(q != NULL && q->q_ptr != NULL);
 491         ASSERT(mp != NULL && mp->b_rptr != NULL);
 492         ASSERT(sps != NULL);
 493         ASSERT(sps->sps_dlstate == DL_UNBOUND);
 494         ASSERT(!IS_SPS_PIOATTACH(sps));
 495 
 496         qwriter(q, mp, sppp_dl_detach_upper, PERIM_INNER);
 497         return (0);
 498 }
 499 
 500 /*
 501  * sppp_dl_detach_upper()
 502  *
 503  * MT-Perimeters:
 504  *    exclusive inner, shared outer.
 505  *
 506  * Description:
 507  *    Called by qwriter (INNER) from sppp_dldetachreq as the result of
 508  *    receiving a DL_DETACH_REQ message.
 509  */
 510 /* ARGSUSED */
 511 static void
 512 sppp_dl_detach_upper(queue_t *q, mblk_t *mp)
 513 {
 514         spppstr_t       *sps;
 515 
 516         ASSERT(q != NULL && q->q_ptr != NULL);
 517         ASSERT(mp != NULL && mp->b_rptr != NULL);
 518         sps = (spppstr_t *)q->q_ptr;
 519         /*
 520          * We don't actually detach from the PPA until closed or
 521          * reattached.
 522          */
 523         sps->sps_flags &= ~SPS_PROMISC;  /* clear flag anyway */
 524         sps->sps_dlstate = DL_UNATTACHED;
 525         dlokack(q, mp, DL_DETACH_REQ);
 526 }
 527 
 528 /*
 529  * sppp_dlbindreq()
 530  *
 531  * MT-Perimeters:
 532  *    shared inner, shared outer.
 533  *
 534  * Description:
 535  *    Perform DL_BIND_REQ request, called by sppp_mproto.
 536  */
 537 static int
 538 sppp_dlbindreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
 539 {
 540         sppa_t                  *ppa;
 541         union DL_primitives     *dlp;
 542         spppreqsap_t            req_sap;
 543         int                     error = 0;
 544 
 545         ASSERT(q != NULL && q->q_ptr != NULL);
 546         ASSERT(mp != NULL && mp->b_rptr != NULL);
 547         dlp = (union DL_primitives *)mp->b_rptr;
 548         req_sap = dlp->bind_req.dl_sap;
 549         ASSERT(sps != NULL);
 550         ASSERT(!IS_SPS_PIOATTACH(sps));
 551         ASSERT(sps->sps_dlstate == DL_UNBOUND);
 552 
 553         ppa = sps->sps_ppa;
 554         if (ppa == NULL) {
 555                 DBGERROR((CE_CONT, "DLPI bind: no attached ppa\n"));
 556                 error = DL_OUTSTATE;
 557         } else if ((req_sap != ETHERTYPE_IP) && (req_sap != ETHERTYPE_IPV6) &&
 558             (req_sap != ETHERTYPE_ALLSAP)) {
 559                 DBGERROR((CE_CONT, "DLPI bind: unknown SAP %x\n", req_sap));
 560                 error = DL_BADADDR;
 561         }
 562         if (error != 0) {
 563                 dlerrorack(q, mp, dlp->dl_primitive, error, 0);
 564         } else {
 565                 qwriter(q, mp, sppp_dl_bind, PERIM_INNER);
 566         }
 567         return (0);
 568 }
 569 
 570 /*
 571  * sppp_dl_bind()
 572  *
 573  * MT-Perimeters:
 574  *    exclusive inner, shared outer.
 575  *
 576  * Description:
 577  *    Called by qwriter (INNER) from sppp_dlbindreq as the result of
 578  *    receiving a DL_BIND_REQ message.
 579  */
 580 static void
 581 sppp_dl_bind(queue_t *q, mblk_t *mp)
 582 {
 583         spppstr_t               *sps;
 584         sppa_t                  *ppa;
 585         union DL_primitives     *dlp;
 586         t_scalar_t              sap;
 587         spppreqsap_t            req_sap;
 588         mblk_t                  *lsmp;
 589 
 590         ASSERT(q != NULL && q->q_ptr != NULL);
 591         sps = (spppstr_t *)q->q_ptr;
 592         ASSERT(mp != NULL && mp->b_rptr != NULL);
 593         dlp = (union DL_primitives *)mp->b_rptr;
 594         ppa = sps->sps_ppa;
 595         ASSERT(ppa != NULL);
 596         req_sap = dlp->bind_req.dl_sap;
 597         ASSERT((req_sap == ETHERTYPE_IP) || (req_sap == ETHERTYPE_IPV6) ||
 598             (req_sap == ETHERTYPE_ALLSAP));
 599 
 600         if (req_sap == ETHERTYPE_IP) {
 601                 sap = PPP_IP;
 602         } else if (req_sap == ETHERTYPE_IPV6) {
 603                 sap = PPP_IPV6;
 604         } else if (req_sap == ETHERTYPE_ALLSAP) {
 605                 sap = PPP_ALLSAP;
 606         }
 607         /*
 608          * If there's another stream with the same sap has already been bound
 609          * to the same ppa, then return with DL_NOADDR. However, we do make an
 610          * exception for snoop (req_sap=0x00, sap=0xff) since multiple
 611          * instances of snoop may execute an a given device.
 612          */
 613         lsmp = NULL;
 614         if (sap != PPP_ALLSAP) {
 615                 if ((sap == PPP_IP) && (ppa->ppa_ip_cache == NULL)) {
 616                         ppa->ppa_ip_cache = sps;
 617                         if (ppa->ppa_ctl != NULL) {
 618                                 lsmp = create_lsmsg(PPP_LINKSTAT_IPV4_BOUND);
 619                         }
 620                 } else if ((sap == PPP_IPV6) && (ppa->ppa_ip6_cache == NULL)) {
 621                         ppa->ppa_ip6_cache = sps;
 622                         if (ppa->ppa_ctl != NULL) {
 623                                 lsmp = create_lsmsg(PPP_LINKSTAT_IPV6_BOUND);
 624                         }
 625                 } else {
 626                         DBGERROR((CE_CONT, "DLPI bind: bad SAP %x\n", sap));
 627                         dlerrorack(q, mp, dlp->dl_primitive, DL_NOADDR,
 628                             EEXIST);
 629                         return;
 630                 }
 631                 sps->sps_flags |= SPS_CACHED;
 632         }
 633         /*
 634          * Tell the daemon that a DLPI bind has happened on this stream,
 635          * and we'll only do this for PPP_IP or PPP_IPV6 sap (not snoop).
 636          */
 637         if (lsmp != NULL && ppa->ppa_ctl != NULL) {
 638 #ifdef DBG_DLPI
 639                 cmn_err(CE_CONT, "sending up %s\n",
 640                     ((sap == PPP_IP) ? "PPP_LINKSTAT_IPV4_BOUND" :
 641                     "PPP_LINKSTAT_IPV6_BOUND"));
 642 #endif
 643                 putnext(ppa->ppa_ctl->sps_rq, lsmp);
 644         }
 645         DBGDLPI((CE_CONT, "/%d: bound to sap %X (req %X)\n", sps->sps_mn_id,
 646             sap, req_sap));
 647         sps->sps_req_sap = req_sap;
 648         sps->sps_sap = sap;
 649         sps->sps_dlstate = DL_IDLE;
 650         dlbindack(q, mp, req_sap, &sap, sizeof (int32_t), 0, 0);
 651 }
 652 
 653 /*
 654  * sppp_dlunbindreq()
 655  *
 656  * MT-Perimeters:
 657  *    shared inner, shared outer.
 658  *
 659  * Description:
 660  *    Perform DL_UNBIND_REQ request, called by sppp_mproto.
 661  */
 662 /* ARGSUSED */
 663 static int
 664 sppp_dlunbindreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
 665 {
 666         ASSERT(q != NULL && q->q_ptr != NULL);
 667         ASSERT(mp != NULL && mp->b_rptr != NULL);
 668         ASSERT(sps != NULL);
 669         ASSERT(!IS_SPS_PIOATTACH(sps));
 670         ASSERT(sps->sps_dlstate == DL_IDLE);
 671 
 672         qwriter(q, mp, sppp_dl_unbind, PERIM_INNER);
 673         return (0);
 674 }
 675 
 676 /*
 677  * sppp_dl_unbind()
 678  *
 679  * MT-Perimeters:
 680  *    exclusive inner, shared outer.
 681  *
 682  * Description:
 683  *    Called by qwriter (INNER) from sppp_dlunbindreq as the result of
 684  *    receiving a DL_UNBIND_REQ message.
 685  */
 686 static void
 687 sppp_dl_unbind(queue_t *q, mblk_t *mp)
 688 {
 689         spppstr_t       *sps;
 690         sppa_t          *ppa;
 691         t_scalar_t      sap;
 692         mblk_t          *msg;
 693         boolean_t       saydown;
 694 
 695         ASSERT(q != NULL && q->q_ptr != NULL);
 696         sps = (spppstr_t *)q->q_ptr;
 697         ppa = sps->sps_ppa;
 698         ASSERT(mp != NULL && mp->b_rptr != NULL);
 699         sap = sps->sps_sap;
 700         ASSERT((sap == PPP_IP) || (sap == PPP_IPV6) || (sap == PPP_ALLSAP));
 701 
 702         /* Flush messages on unbind, per DLPI specification. */
 703         flushq(WR(q), FLUSHALL);
 704         flushq(RD(q), FLUSHALL);
 705 
 706         if ((ppa != NULL) && IS_SPS_CACHED(sps)) {
 707                 sps->sps_flags &= ~SPS_CACHED;
 708                 msg = NULL;
 709                 saydown = (ppa->ppa_ctl != NULL &&
 710                     (sps->sps_npmode == NPMODE_PASS ||
 711                     sps->sps_npmode == NPMODE_QUEUE));
 712                 if (sap == PPP_IP) {
 713                         ppa->ppa_ip_cache = NULL;
 714                         if (saydown)
 715                                 msg = create_lsmsg(PPP_LINKSTAT_IPV4_UNBOUND);
 716                 } else if (sap == PPP_IPV6) {
 717                         ppa->ppa_ip6_cache = NULL;
 718                         if (saydown)
 719                                 msg = create_lsmsg(PPP_LINKSTAT_IPV6_UNBOUND);
 720                 }
 721                 if (msg != NULL) {
 722 #ifdef DBG_DLPI
 723                         cmn_err(CE_CONT, "sending up %s\n",
 724                             ((sap == PPP_IP) ? "PPP_LINKSTAT_IPV4_UNBOUND" :
 725                             "PPP_LINKSTAT_IPV6_UNBOUND"));
 726 #endif
 727                         putnext(ppa->ppa_ctl->sps_rq, msg);
 728                 }
 729         }
 730         DBGDLPI((CE_CONT, "/%d: unbound from sap %X (req %X)\n", sps->sps_mn_id,
 731             sps->sps_sap, sps->sps_req_sap));
 732         sps->sps_req_sap = 0;
 733         sps->sps_sap = -1;
 734         sps->sps_dlstate = DL_UNBOUND;
 735 
 736         dlokack(q, mp, DL_UNBIND_REQ);
 737 }
 738 
 739 /*
 740  * sppp_dlinforeq()
 741  *
 742  * MT-Perimeters:
 743  *    shared inner, shared outer.
 744  *
 745  * Description:
 746  *    Perform DL_INFO_REQ request, called by sppp_mproto.
 747  */
 748 static int
 749 sppp_dlinforeq(queue_t *q, mblk_t *mp, spppstr_t *sps)
 750 {
 751         dl_info_ack_t   *dlip;
 752         uint32_t        size;
 753         uint32_t        addr_size;
 754         sppa_t          *ppa;
 755 
 756         ASSERT(q != NULL && q->q_ptr != NULL);
 757         ASSERT(mp != NULL && mp->b_rptr != NULL);
 758         ASSERT(sps != NULL);
 759         ppa = sps->sps_ppa;
 760 
 761         /* Exchange current msg for a DL_INFO_ACK. */
 762         addr_size = SPPP_ADDRL;
 763         size = sizeof (dl_info_ack_t) + addr_size;
 764         if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL) {
 765                 DBGERROR((CE_CONT, "DLPI info: mexchange failed\n"));
 766                 /* mexchange already sent up an merror ENOSR */
 767                 return (0);
 768         }
 769         /* Fill in DL_INFO_ACK fields and reply */
 770         dlip = (dl_info_ack_t *)mp->b_rptr;
 771         *dlip = sppp_infoack;
 772         dlip->dl_current_state = sps->sps_dlstate;
 773         dlip->dl_max_sdu = ppa != NULL ? ppa->ppa_mtu : PPP_MAXMTU;
 774 #ifdef DBG_DLPI
 775         {
 776                 const char *cp = state2name(dlip->dl_current_state);
 777                 if (cp != NULL)
 778                         cmn_err(CE_CONT, "info returns state %s, max sdu %d\n",
 779                             cp, dlip->dl_max_sdu);
 780                 else
 781                         cmn_err(CE_CONT, "info returns state %d, max sdu %d\n",
 782                             dlip->dl_current_state, dlip->dl_max_sdu);
 783         }
 784 #endif
 785         qreply(q, mp);
 786         return (0);
 787 }
 788 
 789 /*
 790  * sppp_dlunitdatareq()
 791  *
 792  * MT-Perimeters:
 793  *    shared inner, shared outer.
 794  *
 795  * Description:
 796  *    Handle DL_UNITDATA_REQ request, called by sppp_mproto. This procedure
 797  *    gets called for M_PROTO (DLPI) style of transmission. The fact that we
 798  *    have acknowledged IP's fastpath probing (DL_IOC_HDR_INFO) does not
 799  *    guarantee that IP will always transmit via M_DATA, and it merely implies
 800  *    that such situation _may_ happen. In other words, IP may decide to use
 801  *    M_PROTO (DLPI) for data transmission should it decide to do so.
 802  *    Therefore, we should never place any restrictions or checks against
 803  *    streams marked with SPS_FASTPATH, since it is legal for this procedure
 804  *    to be entered with or without the bit set.
 805  */
 806 static int
 807 sppp_dlunitdatareq(queue_t *q, mblk_t *mp, spppstr_t *sps)
 808 {
 809         sppa_t          *ppa;
 810         mblk_t          *hdrmp;
 811         mblk_t          *pktmp;
 812         dl_unitdata_req_t *dludp;
 813         int             dladdroff;
 814         int             dladdrlen;
 815         int             msize;
 816         int             error = 0;
 817         boolean_t       is_promisc;
 818 
 819         ASSERT(q != NULL && q->q_ptr != NULL);
 820         ASSERT(mp != NULL && mp->b_rptr != NULL);
 821         ASSERT((MTYPE(mp) == M_PCPROTO) || (MTYPE(mp) == M_PROTO));
 822         dludp = (dl_unitdata_req_t *)mp->b_rptr;
 823         dladdroff = dludp->dl_dest_addr_offset;
 824         dladdrlen = dludp->dl_dest_addr_length;
 825         ASSERT(sps != NULL);
 826         ASSERT(!IS_SPS_PIOATTACH(sps));
 827         ASSERT(sps->sps_dlstate == DL_IDLE);
 828         ASSERT(q->q_ptr == sps);
 829         /*
 830          * If this stream is not attached to any ppas, then discard data
 831          * coming down through this stream.
 832          */
 833         ppa = sps->sps_ppa;
 834         if (ppa == NULL) {
 835                 DBGERROR((CE_CONT, "DLPI unitdata: no attached ppa\n"));
 836                 error = ENOLINK;
 837         } else if (mp->b_cont == NULL) {
 838                 DBGERROR((CE_CONT, "DLPI unitdata: missing data\n"));
 839                 error = EPROTO;
 840         }
 841         if (error != 0) {
 842                 dluderrorind(q, mp, mp->b_rptr + dladdroff, dladdrlen,
 843                     DL_BADDATA, error);
 844                 return (0);
 845         }
 846         ASSERT(mp->b_cont->b_rptr != NULL);
 847         /*
 848          * Check if outgoing packet size is larger than allowed. We use
 849          * msgdsize to count all of M_DATA blocks in the message.
 850          */
 851         msize = msgdsize(mp);
 852         if (msize > ppa->ppa_mtu) {
 853                 /* Log, and send it anyway */
 854                 mutex_enter(&ppa->ppa_sta_lock);
 855                 ppa->ppa_otoolongs++;
 856                 mutex_exit(&ppa->ppa_sta_lock);
 857         }
 858         if (IS_SPS_KDEBUG(sps)) {
 859                 SPDEBUG(PPP_DRV_NAME
 860                     "/%d: DL_UNITDATA_REQ (%d bytes) sps=0x%p flags=0x%b "
 861                     "ppa=0x%p flags=0x%b\n", sps->sps_mn_id, msize,
 862                     (void *)sps, sps->sps_flags, SPS_FLAGS_STR,
 863                     (void *)ppa, ppa->ppa_flags, PPA_FLAGS_STR);
 864         }
 865         /* Allocate a message (M_DATA) to contain PPP header bytes. */
 866         if ((hdrmp = allocb(PPP_HDRLEN, BPRI_MED)) == NULL) {
 867                 mutex_enter(&ppa->ppa_sta_lock);
 868                 ppa->ppa_allocbfail++;
 869                 mutex_exit(&ppa->ppa_sta_lock);
 870                 DBGERROR((CE_CONT,
 871                     "DLPI unitdata: can't allocate header buffer\n"));
 872                 dluderrorind(q, mp, mp->b_rptr + dladdroff, dladdrlen,
 873                     DL_SYSERR, ENOSR);
 874                 return (0);
 875         }
 876         /*
 877          * Should there be any promiscuous stream(s), send the data up
 878          * for each promiscuous stream that we recognize.
 879          */
 880         rw_enter(&ppa->ppa_sib_lock, RW_READER);
 881         is_promisc = ppa->ppa_promicnt;
 882         if (is_promisc) {
 883                 ASSERT(ppa->ppa_streams != NULL);
 884                 sppp_dlprsendup(ppa->ppa_streams, mp->b_cont, sps->sps_sap,
 885                     B_FALSE);
 886         }
 887         rw_exit(&ppa->ppa_sib_lock);
 888         /* Discard DLPI header and keep only IP payload (mp->b_cont). */
 889         pktmp = mp->b_cont;
 890         mp->b_cont = NULL;
 891         freemsg(mp);
 892         mp = hdrmp;
 893 
 894         *(uchar_t *)mp->b_wptr++ = PPP_ALLSTATIONS;
 895         *(uchar_t *)mp->b_wptr++ = PPP_UI;
 896         *(uchar_t *)mp->b_wptr++ = ((uint16_t)sps->sps_sap >> 8) & 0xff;
 897         *(uchar_t *)mp->b_wptr++ = ((uint16_t)sps->sps_sap) & 0xff;
 898         ASSERT(MBLKL(mp) == PPP_HDRLEN);
 899 
 900         linkb(mp, pktmp);
 901         /*
 902          * Only time-stamp the packet with hrtime if the upper stream
 903          * is configured to do so.
 904          */
 905         if (IS_PPA_TIMESTAMP(ppa)) {
 906                 ppa->ppa_lasttx = gethrtime();
 907         }
 908         /*
 909          * Just put this back on the queue and allow the write service
 910          * routine to handle it.  We're nested too deeply here to
 911          * rewind the stack sufficiently to prevent overflow.  This is
 912          * the slow path anyway.
 913          */
 914         if (putq(q, mp) == 0) {
 915                 mutex_enter(&ppa->ppa_sta_lock);
 916                 ppa->ppa_oqdropped++;
 917                 mutex_exit(&ppa->ppa_sta_lock);
 918                 freemsg(mp);
 919         } else {
 920                 qenable(q);
 921         }
 922         return (0);
 923 }
 924 
 925 /*
 926  * sppp_dlpromisconreq()
 927  *
 928  * MT-Perimeters:
 929  *    shared inner, shared outer.
 930  *
 931  * Description:
 932  *    Perform DL_PROMISCON_REQ request, called by sppp_mproto.
 933  */
 934 static int
 935 sppp_dlpromisconreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
 936 {
 937         t_uscalar_t     level;
 938 
 939         ASSERT(q != NULL && q->q_ptr != NULL);
 940         ASSERT(mp != NULL && mp->b_rptr != NULL);
 941         level = ((dl_promiscon_req_t *)mp->b_rptr)->dl_level;
 942         ASSERT(sps != NULL);
 943 
 944         /* snoop issues DL_PROMISCON_REQ more than once. */
 945         if (IS_SPS_PROMISC(sps)) {
 946                 dlokack(q, mp, DL_PROMISCON_REQ);
 947         } else if ((level != DL_PROMISC_PHYS) && (level != DL_PROMISC_SAP) &&
 948             (level != DL_PROMISC_MULTI)) {
 949                 DBGERROR((CE_CONT, "DLPI promiscon: bad level %d\n", level));
 950                 dlerrorack(q, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
 951         } else {
 952                 qwriter(q, mp, sppp_dl_promiscon, PERIM_INNER);
 953         }
 954         return (0);
 955 }
 956 
 957 /*
 958  * sppp_dl_promiscon()
 959  *
 960  * MT-Perimeters:
 961  *    exclusive inner, shared outer.
 962  *
 963  * Description:
 964  *    Called by qwriter (INNER) from sppp_dlpromisconreq as the result of
 965  *    receiving a DL_PROMISCON_REQ message.
 966  */
 967 static void
 968 sppp_dl_promiscon(queue_t *q, mblk_t *mp)
 969 {
 970         spppstr_t       *sps;
 971         sppa_t          *ppa;
 972 
 973         ASSERT(q != NULL && q->q_ptr != NULL);
 974         sps = (spppstr_t *)q->q_ptr;
 975         ASSERT(!IS_SPS_PROMISC(sps));
 976         ASSERT(mp != NULL && mp->b_rptr != NULL);
 977         ppa = sps->sps_ppa;
 978 
 979         sps->sps_flags |= SPS_PROMISC;
 980         /*
 981          * We can't be sure that the sps_ppa field is valid, since the DLPI
 982          * spec says that DL_PROMISCON_REQ can be issued at any state, i.e.,
 983          * the request can be issued even before DL_ATTACH_REQ or PPPIO_ATTACH
 984          * be issued to associate this stream with a ppa.
 985          */
 986         if (ppa != NULL) {
 987                 rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
 988                 ppa->ppa_promicnt++;
 989                 rw_exit(&ppa->ppa_sib_lock);
 990         }
 991         DBGDLPI((CE_CONT, "/%d: promiscuous mode on\n", sps->sps_mn_id));
 992         dlokack(q, mp, DL_PROMISCON_REQ);
 993 }
 994 
 995 /*
 996  * sppp_dlpromiscoffreq()
 997  *
 998  * MT-Perimeters:
 999  *    shared inner, shared outer.
1000  *
1001  * Description:
1002  *    Perform DL_PROMISCOFF_REQ request, called by sppp_mproto.
1003  */
1004 static int
1005 sppp_dlpromiscoffreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
1006 {
1007         t_uscalar_t     level;
1008 
1009         ASSERT(q != NULL && q->q_ptr != NULL);
1010         ASSERT(mp != NULL && mp->b_rptr != NULL);
1011         level = ((dl_promiscoff_req_t *)mp->b_rptr)->dl_level;
1012         ASSERT(sps != NULL);
1013 
1014         if (!IS_SPS_PROMISC(sps)) {
1015                 DBGERROR((CE_CONT, "DLPI promiscoff: not promiscuous\n"));
1016                 dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
1017         } else if ((level != DL_PROMISC_PHYS) && (level != DL_PROMISC_SAP) &&
1018             (level != DL_PROMISC_MULTI)) {
1019                 dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
1020                 DBGERROR((CE_CONT, "DLPI promiscoff: bad level %d\n", level));
1021         } else {
1022                 qwriter(q, mp, sppp_dl_promiscoff, PERIM_INNER);
1023         }
1024         return (0);
1025 
1026 }
1027 
1028 /*
1029  * sppp_dl_promiscoff()
1030  *
1031  * MT-Perimeters:
1032  *    exclusive inner, shared outer.
1033  *
1034  * Description:
1035  *    Called by qwriter (INNER) from sppp_dlpromiscoffreq as the result of
1036  *    receiving a DL_PROMISCOFF_REQ message.
1037  */
1038 static void
1039 sppp_dl_promiscoff(queue_t *q, mblk_t *mp)
1040 {
1041         spppstr_t       *sps;
1042         sppa_t          *ppa;
1043 
1044         ASSERT(q != NULL && q->q_ptr != NULL);
1045         sps = (spppstr_t *)q->q_ptr;
1046         ASSERT(IS_SPS_PROMISC(sps));
1047         ASSERT(mp != NULL && mp->b_rptr != NULL);
1048         ppa = sps->sps_ppa;
1049 
1050         sps->sps_flags &= ~SPS_PROMISC;
1051         /*
1052          * We can't be guaranteed that the sps_ppa field is still valid, since
1053          * the control stream might have been closed earlier, in which case
1054          * the close procedure would have NULL'd out the sps_ppa.
1055          */
1056         if (ppa != NULL) {
1057                 rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
1058                 ASSERT(ppa->ppa_promicnt > 0);
1059                 ppa->ppa_promicnt--;
1060                 rw_exit(&ppa->ppa_sib_lock);
1061         }
1062         DBGDLPI((CE_CONT, "/%d: promiscuous mode off\n", sps->sps_mn_id));
1063         dlokack(q, mp, DL_PROMISCOFF_REQ);
1064 }
1065 
1066 /*
1067  * sppp_dlphyreq()
1068  *
1069  * MT-Perimeters:
1070  *    shared inner, shared outer.
1071  *
1072  * Description:
1073  *    Perform DL_PHYS_ADDR_REQ request, called by sppp_mproto. This doesn't
1074  *    return anything useful, but it keeps ifconfig happy.
1075  */
1076 /* ARGSUSED */
1077 static int
1078 sppp_dlphyreq(queue_t *q, mblk_t *mp, spppstr_t *us)
1079 {
1080         static struct ether_addr addr = { 0 };
1081 
1082         dlphysaddrack(q, mp, (char *)&addr, ETHERADDRL);
1083         return (0);
1084 }
1085 
1086 /*
1087  * sppp_dladdether()
1088  *
1089  * Description:
1090  *    Prepend an empty Ethernet header to msg for snoop, et al. Free
1091  *    the original mblk if alloc fails. Only called for the purpose of sending
1092  *    packets up the promiscous stream.
1093  */
1094 /* ARGSUSED */
1095 static mblk_t *
1096 sppp_dladdether(spppstr_t *sps, mblk_t *mp, t_scalar_t proto)
1097 {
1098         mblk_t          *eh;
1099         t_scalar_t      type;
1100 
1101         if ((eh = allocb(sizeof (struct ether_header), BPRI_MED)) == NULL) {
1102                 freemsg(mp);
1103                 return (NULL);
1104         }
1105         if (proto == PPP_IP) {
1106                 type = ETHERTYPE_IP;
1107         } else if (proto == PPP_IPV6) {
1108                 type = ETHERTYPE_IPV6;
1109         } else {
1110                 /*
1111                  * For all other protocols, end this up as an ETHERTYPE_PPP
1112                  * type of packet. Since we've skipped the PPP headers in the
1113                  * caller, make sure that we restore it. We know for sure that
1114                  * the PPP header still exists in the message (only skipped),
1115                  * since the sender of this message is pppd and it must have
1116                  * included the PPP header in front.
1117                  */
1118                 type = ETHERTYPE_PPP;
1119                 mp->b_rptr -= PPP_HDRLEN;
1120                 ASSERT(mp->b_rptr >= mp->b_datap->db_base);
1121         }
1122         eh->b_wptr += sizeof (struct ether_header);
1123         bzero((caddr_t)eh->b_rptr, sizeof (struct ether_header));
1124         ((struct ether_header *)eh->b_rptr)->ether_type = htons((int16_t)type);
1125 
1126         linkb(eh, mp);
1127         return (eh);
1128 }
1129 
1130 /*
1131  * sppp_dladdud()
1132  *
1133  * Description:
1134  *    Prepend DL_UNITDATA_IND mblk to msg, free original alloc fails.
1135  */
1136 /* ARGSUSED */
1137 mblk_t *
1138 sppp_dladdud(spppstr_t *sps, mblk_t *mp, t_scalar_t proto, boolean_t promisc)
1139 {
1140         dl_unitdata_ind_t *dlu;
1141         mblk_t          *dh;
1142         size_t          size;
1143         t_scalar_t      type;
1144 
1145         size = sizeof (dl_unitdata_ind_t) + (2 * SPPP_ADDRL);
1146         if ((dh = allocb(size, BPRI_MED)) == NULL) {
1147                 freemsg(mp);
1148                 return (NULL);
1149         }
1150 
1151         dh->b_datap->db_type = M_PROTO;
1152         dh->b_wptr = dh->b_datap->db_lim;
1153         dh->b_rptr = dh->b_wptr - size;
1154 
1155         dlu = (dl_unitdata_ind_t *)dh->b_rptr;
1156         dlu->dl_primitive = DL_UNITDATA_IND;
1157         dlu->dl_dest_addr_length = SPPP_ADDRL;
1158         dlu->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
1159         dlu->dl_src_addr_length = SPPP_ADDRL;
1160         dlu->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + SPPP_ADDRL;
1161         dlu->dl_group_address = 0;
1162 
1163         if (promisc) {
1164                 if (proto == PPP_IP) {
1165                         type = ETHERTYPE_IP;
1166                 } else if (proto == PPP_IPV6) {
1167                         type = ETHERTYPE_IPV6;
1168                 } else {
1169                         /*
1170                          * For all other protocols, send this up as an
1171                          * ETHERTYPE_PPP type of packet. Since we've skipped
1172                          * the PPP headers in the caller, make sure that we
1173                          * restore it. We know for sure that the PPP header
1174                          * still exists in the message (only skipped), since
1175                          * the sender of this message is pppd and it must
1176                          * have included the PPP header in front.
1177                          */
1178                         type = ETHERTYPE_PPP;
1179                         mp->b_rptr -= PPP_HDRLEN;
1180                         ASSERT(mp->b_rptr >= mp->b_datap->db_base);
1181                 }
1182         } else {
1183                 type = sps->sps_req_sap;
1184         }
1185         /*
1186          * Send the DLPI client the data with the SAP they requested,
1187          * (e.g. ETHERTYPE_IP) rather than the PPP protocol (e.g. PPP_IP).
1188          */
1189         ((spppreqsap_t *)(dlu + 1))[0] = type;
1190         ((spppreqsap_t *)(dlu + 1))[1] = type;
1191 
1192         linkb(dh, mp);
1193         return (dh);
1194 }
1195 
1196 /*
1197  * sppp_dlprsendup()
1198  *
1199  * Description:
1200  *    For any valid promiscuous streams (marked with SPS_PROMISC and its
1201  *    sps_dlstate is DL_IDLE), send data upstream. The caller is expected
1202  *    to hold ppa_sib_lock when calling this procedure.
1203  */
1204 void
1205 sppp_dlprsendup(spppstr_t *sps, mblk_t *mp, t_scalar_t proto, boolean_t header)
1206 {
1207         sppa_t  *ppa;
1208         mblk_t  *dmp;
1209 
1210         ASSERT(sps != NULL);
1211         ASSERT(mp != NULL && mp->b_rptr != NULL);
1212         ppa = sps->sps_ppa;
1213         ASSERT(ppa != NULL);
1214 
1215         /* NOTE: caller must hold ppa_sib_lock in RW_READER mode */
1216         ASSERT(RW_READ_HELD(&ppa->ppa_sib_lock));
1217 
1218         for (; sps != NULL; sps = sps->sps_nextsib) {
1219                 /*
1220                  * We specifically test to ensure that the DLPI state for the
1221                  * promiscous stream is IDLE (DL_IDLE), since such state tells
1222                  * us that the promiscous stream has been bound to PPP_ALLSAP.
1223                  */
1224                 if (IS_SPS_PROMISC(sps) && (sps->sps_dlstate == DL_IDLE) &&
1225                     canputnext(sps->sps_rq)) {
1226                         if ((dmp = dupmsg(mp)) == NULL) {
1227                                 mutex_enter(&ppa->ppa_sta_lock);
1228                                 ppa->ppa_allocbfail++;
1229                                 mutex_exit(&ppa->ppa_sta_lock);
1230                                 continue;
1231                         }
1232                         if (header) {
1233                                 dmp->b_rptr += PPP_HDRLEN;
1234                         }
1235                         if (IS_SPS_RAWDATA(sps)) {
1236                                 /* function frees original message if fails */
1237                                 dmp = sppp_dladdether(sps, dmp, proto);
1238                         } else {
1239                                 /* function frees original message if fails */
1240                                 dmp = sppp_dladdud(sps, dmp, proto, B_TRUE);
1241                         }
1242                         if (dmp != NULL) {
1243                                 putnext(sps->sps_rq, dmp);
1244                         } else {
1245                                 mutex_enter(&ppa->ppa_sta_lock);
1246                                 ppa->ppa_allocbfail++;
1247                                 mutex_exit(&ppa->ppa_sta_lock);
1248                         }
1249                 }
1250         }
1251 }