17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * sppp_dlpi.c - Solaris STREAMS PPP multiplexing pseudo-driver DLPI handlers
37c478bd9Sstevel@tonic-gate *
4*f53eecf5SJames Carlson * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
57c478bd9Sstevel@tonic-gate * Use is subject to license terms.
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its
87c478bd9Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright
97c478bd9Sstevel@tonic-gate * notice appears in all copies.
107c478bd9Sstevel@tonic-gate *
117c478bd9Sstevel@tonic-gate * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
127c478bd9Sstevel@tonic-gate * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
137c478bd9Sstevel@tonic-gate * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
147c478bd9Sstevel@tonic-gate * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
157c478bd9Sstevel@tonic-gate * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
167c478bd9Sstevel@tonic-gate * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
177c478bd9Sstevel@tonic-gate *
187c478bd9Sstevel@tonic-gate * Copyright (c) 1994 The Australian National University.
197c478bd9Sstevel@tonic-gate * All rights reserved.
207c478bd9Sstevel@tonic-gate *
217c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its
227c478bd9Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright
237c478bd9Sstevel@tonic-gate * notice appears in all copies. This software is provided without any
247c478bd9Sstevel@tonic-gate * warranty, express or implied. The Australian National University
257c478bd9Sstevel@tonic-gate * makes no representations about the suitability of this software for
267c478bd9Sstevel@tonic-gate * any purpose.
277c478bd9Sstevel@tonic-gate *
287c478bd9Sstevel@tonic-gate * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
297c478bd9Sstevel@tonic-gate * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
307c478bd9Sstevel@tonic-gate * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
317c478bd9Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
327c478bd9Sstevel@tonic-gate * OF SUCH DAMAGE.
337c478bd9Sstevel@tonic-gate *
347c478bd9Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
357c478bd9Sstevel@tonic-gate * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
367c478bd9Sstevel@tonic-gate * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
377c478bd9Sstevel@tonic-gate * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
387c478bd9Sstevel@tonic-gate * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
397c478bd9Sstevel@tonic-gate * OR MODIFICATIONS.
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * This driver is derived from the original SVR4 STREAMS PPP driver
427c478bd9Sstevel@tonic-gate * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
437c478bd9Sstevel@tonic-gate *
447c478bd9Sstevel@tonic-gate * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
457c478bd9Sstevel@tonic-gate * for improved performance and scalability.
467c478bd9Sstevel@tonic-gate */
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate #define RCSID "$Id: sppp_dlpi.c,v 1.0 2000/05/08 01:10:12 masputra Exp $"
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate #include <sys/types.h>
517c478bd9Sstevel@tonic-gate #include <sys/param.h>
527c478bd9Sstevel@tonic-gate #include <sys/stat.h>
537c478bd9Sstevel@tonic-gate #include <sys/stream.h>
547c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
557c478bd9Sstevel@tonic-gate #include <sys/errno.h>
567c478bd9Sstevel@tonic-gate #include <sys/time.h>
577c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
587c478bd9Sstevel@tonic-gate #include <sys/conf.h>
597c478bd9Sstevel@tonic-gate #include <sys/dlpi.h>
607c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
617c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
62*f53eecf5SJames Carlson #include <sys/strsubr.h>
637c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
647c478bd9Sstevel@tonic-gate #include <sys/ethernet.h>
657c478bd9Sstevel@tonic-gate #include <net/ppp_defs.h>
667c478bd9Sstevel@tonic-gate #include <netinet/in.h>
677c478bd9Sstevel@tonic-gate #include <net/pppio.h>
687c478bd9Sstevel@tonic-gate #include "s_common.h"
697c478bd9Sstevel@tonic-gate #include "sppp.h"
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate static int sppp_dlattachreq(queue_t *, mblk_t *, spppstr_t *);
727c478bd9Sstevel@tonic-gate static int sppp_dldetachreq(queue_t *, mblk_t *, spppstr_t *);
737c478bd9Sstevel@tonic-gate static int sppp_dlbindreq(queue_t *, mblk_t *, spppstr_t *);
747c478bd9Sstevel@tonic-gate static int sppp_dlunbindreq(queue_t *, mblk_t *, spppstr_t *);
757c478bd9Sstevel@tonic-gate static int sppp_dlinforeq(queue_t *, mblk_t *, spppstr_t *);
767c478bd9Sstevel@tonic-gate static int sppp_dlunitdatareq(queue_t *, mblk_t *, spppstr_t *);
777c478bd9Sstevel@tonic-gate static int sppp_dlpromisconreq(queue_t *, mblk_t *, spppstr_t *);
787c478bd9Sstevel@tonic-gate static int sppp_dlpromiscoffreq(queue_t *, mblk_t *, spppstr_t *);
797c478bd9Sstevel@tonic-gate static int sppp_dlphyreq(queue_t *, mblk_t *, spppstr_t *);
807c478bd9Sstevel@tonic-gate static void sppp_dl_attach_upper(queue_t *, mblk_t *);
817c478bd9Sstevel@tonic-gate static void sppp_dl_detach_upper(queue_t *, mblk_t *);
827c478bd9Sstevel@tonic-gate static void sppp_dl_bind(queue_t *, mblk_t *);
837c478bd9Sstevel@tonic-gate static void sppp_dl_unbind(queue_t *, mblk_t *);
847c478bd9Sstevel@tonic-gate static void sppp_dl_promiscon(queue_t *, mblk_t *);
857c478bd9Sstevel@tonic-gate static void sppp_dl_promiscoff(queue_t *, mblk_t *);
867c478bd9Sstevel@tonic-gate static mblk_t *sppp_dladdether(spppstr_t *, mblk_t *, t_scalar_t);
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate static struct sppp_dlpi_pinfo_t dl_pinfo[DL_MAXPRIM + 1];
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate #if 0
917c478bd9Sstevel@tonic-gate #define DBGERROR(x) cmn_err x
927c478bd9Sstevel@tonic-gate #else
937c478bd9Sstevel@tonic-gate #define DBGERROR(x) ((void)0)
947c478bd9Sstevel@tonic-gate #endif
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate /* #define DBG_DLPI 1 */
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
997c478bd9Sstevel@tonic-gate struct sppp_dlpi_entry {
1007c478bd9Sstevel@tonic-gate uint32_t sde_val;
1017c478bd9Sstevel@tonic-gate const char *sde_name;
1027c478bd9Sstevel@tonic-gate };
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate static const struct sppp_dlpi_entry sppp_dlpi_list[] = {
1057c478bd9Sstevel@tonic-gate { DL_INFO_REQ, "DL_INFO_REQ" },
1067c478bd9Sstevel@tonic-gate { DL_INFO_ACK, "DL_INFO_ACK" },
1077c478bd9Sstevel@tonic-gate { DL_ATTACH_REQ, "DL_ATTACH_REQ" },
1087c478bd9Sstevel@tonic-gate { DL_DETACH_REQ, "DL_DETACH_REQ" },
1097c478bd9Sstevel@tonic-gate { DL_BIND_REQ, "DL_BIND_REQ" },
1107c478bd9Sstevel@tonic-gate { DL_BIND_ACK, "DL_BIND_ACK" },
1117c478bd9Sstevel@tonic-gate { DL_UNBIND_REQ, "DL_UNBIND_REQ" },
1127c478bd9Sstevel@tonic-gate { DL_OK_ACK, "DL_OK_ACK" },
1137c478bd9Sstevel@tonic-gate { DL_ERROR_ACK, "DL_ERROR_ACK" },
1147c478bd9Sstevel@tonic-gate { DL_SUBS_BIND_REQ, "DL_SUBS_BIND_REQ" },
1157c478bd9Sstevel@tonic-gate { DL_SUBS_BIND_ACK, "DL_SUBS_BIND_ACK" },
1167c478bd9Sstevel@tonic-gate { DL_SUBS_UNBIND_REQ, "DL_SUBS_UNBIND_REQ" },
1177c478bd9Sstevel@tonic-gate { DL_ENABMULTI_REQ, "DL_ENABMULTI_REQ" },
1187c478bd9Sstevel@tonic-gate { DL_DISABMULTI_REQ, "DL_DISABMULTI_REQ" },
1197c478bd9Sstevel@tonic-gate { DL_PROMISCON_REQ, "DL_PROMISCON_REQ" },
1207c478bd9Sstevel@tonic-gate { DL_PROMISCOFF_REQ, "DL_PROMISCOFF_REQ" },
1217c478bd9Sstevel@tonic-gate { DL_UNITDATA_REQ, "DL_UNITDATA_REQ" },
1227c478bd9Sstevel@tonic-gate { DL_UNITDATA_IND, "DL_UNITDATA_IND" },
1237c478bd9Sstevel@tonic-gate { DL_UDERROR_IND, "DL_UDERROR_IND" },
1247c478bd9Sstevel@tonic-gate { DL_UDQOS_REQ, "DL_UDQOS_REQ" },
1257c478bd9Sstevel@tonic-gate { DL_CONNECT_REQ, "DL_CONNECT_REQ" },
1267c478bd9Sstevel@tonic-gate { DL_CONNECT_IND, "DL_CONNECT_IND" },
1277c478bd9Sstevel@tonic-gate { DL_CONNECT_RES, "DL_CONNECT_RES" },
1287c478bd9Sstevel@tonic-gate { DL_CONNECT_CON, "DL_CONNECT_CON" },
1297c478bd9Sstevel@tonic-gate { DL_TOKEN_REQ, "DL_TOKEN_REQ" },
1307c478bd9Sstevel@tonic-gate { DL_TOKEN_ACK, "DL_TOKEN_ACK" },
1317c478bd9Sstevel@tonic-gate { DL_DISCONNECT_REQ, "DL_DISCONNECT_REQ" },
1327c478bd9Sstevel@tonic-gate { DL_DISCONNECT_IND, "DL_DISCONNECT_IND" },
1337c478bd9Sstevel@tonic-gate { DL_RESET_REQ, "DL_RESET_REQ" },
1347c478bd9Sstevel@tonic-gate { DL_RESET_IND, "DL_RESET_IND" },
1357c478bd9Sstevel@tonic-gate { DL_RESET_RES, "DL_RESET_RES" },
1367c478bd9Sstevel@tonic-gate { DL_RESET_CON, "DL_RESET_CON" },
1377c478bd9Sstevel@tonic-gate { DL_DATA_ACK_REQ, "DL_DATA_ACK_REQ" },
1387c478bd9Sstevel@tonic-gate { DL_DATA_ACK_IND, "DL_DATA_ACK_IND" },
1397c478bd9Sstevel@tonic-gate { DL_DATA_ACK_STATUS_IND, "DL_DATA_ACK_STATUS_IND" },
1407c478bd9Sstevel@tonic-gate { DL_REPLY_REQ, "DL_REPLY_REQ" },
1417c478bd9Sstevel@tonic-gate { DL_REPLY_IND, "DL_REPLY_IND" },
1427c478bd9Sstevel@tonic-gate { DL_REPLY_STATUS_IND, "DL_REPLY_STATUS_IND" },
1437c478bd9Sstevel@tonic-gate { DL_REPLY_UPDATE_REQ, "DL_REPLY_UPDATE_REQ" },
1447c478bd9Sstevel@tonic-gate { DL_REPLY_UPDATE_STATUS_IND, "DL_REPLY_UPDATE_STATUS_IND" },
1457c478bd9Sstevel@tonic-gate { DL_XID_REQ, "DL_XID_REQ" },
1467c478bd9Sstevel@tonic-gate { DL_XID_IND, "DL_XID_IND" },
1477c478bd9Sstevel@tonic-gate { DL_XID_RES, "DL_XID_RES" },
1487c478bd9Sstevel@tonic-gate { DL_XID_CON, "DL_XID_CON" },
1497c478bd9Sstevel@tonic-gate { DL_TEST_REQ, "DL_TEST_REQ" },
1507c478bd9Sstevel@tonic-gate { DL_TEST_IND, "DL_TEST_IND" },
1517c478bd9Sstevel@tonic-gate { DL_TEST_RES, "DL_TEST_RES" },
1527c478bd9Sstevel@tonic-gate { DL_TEST_CON, "DL_TEST_CON" },
1537c478bd9Sstevel@tonic-gate { DL_PHYS_ADDR_REQ, "DL_PHYS_ADDR_REQ" },
1547c478bd9Sstevel@tonic-gate { DL_PHYS_ADDR_ACK, "DL_PHYS_ADDR_ACK" },
1557c478bd9Sstevel@tonic-gate { DL_SET_PHYS_ADDR_REQ, "DL_SET_PHYS_ADDR_REQ" },
1567c478bd9Sstevel@tonic-gate { DL_GET_STATISTICS_REQ, "DL_GET_STATISTICS_REQ" },
1577c478bd9Sstevel@tonic-gate { DL_GET_STATISTICS_ACK, "DL_GET_STATISTICS_ACK" },
1587c478bd9Sstevel@tonic-gate { 0, NULL }
1597c478bd9Sstevel@tonic-gate };
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate static const struct sppp_dlpi_entry sppp_state_list[] = {
1627c478bd9Sstevel@tonic-gate { DL_UNBOUND, "DL_UNBOUND" },
1637c478bd9Sstevel@tonic-gate { DL_BIND_PENDING, "DL_BIND_PENDING" },
1647c478bd9Sstevel@tonic-gate { DL_UNBIND_PENDING, "DL_UNBIND_PENDING" },
1657c478bd9Sstevel@tonic-gate { DL_IDLE, "DL_IDLE" },
1667c478bd9Sstevel@tonic-gate { DL_UNATTACHED, "DL_UNATTACHED" },
1677c478bd9Sstevel@tonic-gate { DL_ATTACH_PENDING, "DL_ATTACH_PENDING" },
1687c478bd9Sstevel@tonic-gate { DL_DETACH_PENDING, "DL_DETACH_PENDING" },
1697c478bd9Sstevel@tonic-gate { DL_UDQOS_PENDING, "DL_UDQOS_PENDING" },
1707c478bd9Sstevel@tonic-gate { DL_OUTCON_PENDING, "DL_OUTCON_PENDING" },
1717c478bd9Sstevel@tonic-gate { DL_INCON_PENDING, "DL_INCON_PENDING" },
1727c478bd9Sstevel@tonic-gate { DL_CONN_RES_PENDING, "DL_CONN_RES_PENDING" },
1737c478bd9Sstevel@tonic-gate { DL_DATAXFER, "DL_DATAXFER" },
1747c478bd9Sstevel@tonic-gate { DL_USER_RESET_PENDING, "DL_USER_RESET_PENDING" },
1757c478bd9Sstevel@tonic-gate { DL_PROV_RESET_PENDING, "DL_PROV_RESET_PENDING" },
1767c478bd9Sstevel@tonic-gate { DL_RESET_RES_PENDING, "DL_RESET_RES_PENDING" },
1777c478bd9Sstevel@tonic-gate { DL_DISCON8_PENDING, "DL_DISCON8_PENDING" },
1787c478bd9Sstevel@tonic-gate { DL_DISCON9_PENDING, "DL_DISCON9_PENDING" },
1797c478bd9Sstevel@tonic-gate { DL_DISCON11_PENDING, "DL_DISCON11_PENDING" },
1807c478bd9Sstevel@tonic-gate { DL_DISCON12_PENDING, "DL_DISCON12_PENDING" },
1817c478bd9Sstevel@tonic-gate { DL_DISCON13_PENDING, "DL_DISCON13_PENDING" },
1827c478bd9Sstevel@tonic-gate { DL_SUBS_BIND_PND, "DL_SUBS_BIND_PND" },
1837c478bd9Sstevel@tonic-gate { DL_SUBS_UNBIND_PND, "DL_SUBS_UNBIND_PND" },
1847c478bd9Sstevel@tonic-gate { 0, NULL }
1857c478bd9Sstevel@tonic-gate };
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate static const char *
prim2name(uint32_t prim)1887c478bd9Sstevel@tonic-gate prim2name(uint32_t prim)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate const struct sppp_dlpi_entry *sde;
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate for (sde = sppp_dlpi_list; sde->sde_name != NULL; sde++)
1937c478bd9Sstevel@tonic-gate if (sde->sde_val == prim)
1947c478bd9Sstevel@tonic-gate break;
1957c478bd9Sstevel@tonic-gate return (sde->sde_name);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate static const char *
state2name(uint32_t state)1997c478bd9Sstevel@tonic-gate state2name(uint32_t state)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate const struct sppp_dlpi_entry *sde;
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate for (sde = sppp_state_list; sde->sde_name != NULL; sde++)
2047c478bd9Sstevel@tonic-gate if (sde->sde_val == state)
2057c478bd9Sstevel@tonic-gate break;
2067c478bd9Sstevel@tonic-gate return (sde->sde_name);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate #define DBGDLPI(x) cmn_err x
2107c478bd9Sstevel@tonic-gate #else
2117c478bd9Sstevel@tonic-gate #define DBGDLPI(x) ((void)0)
2127c478bd9Sstevel@tonic-gate #endif /* DBG_DLPI */
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate * DL_INFO_ACK template for point-to-point interface.
2167c478bd9Sstevel@tonic-gate */
2177c478bd9Sstevel@tonic-gate static dl_info_ack_t sppp_infoack = {
2187c478bd9Sstevel@tonic-gate DL_INFO_ACK, /* dl_primitive */
2197c478bd9Sstevel@tonic-gate PPP_MAXMTU, /* dl_max_sdu */
2207c478bd9Sstevel@tonic-gate 0, /* dl_min_sdu */
2217c478bd9Sstevel@tonic-gate SPPP_ADDRL, /* dl_addr_length */
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate * snoop et. al. don't know about DL_OTHER so this entry
2247c478bd9Sstevel@tonic-gate * was changed to DL_ETHER so ethernet tracing/snooping
2257c478bd9Sstevel@tonic-gate * facilities will work with PPP interfaces.
2267c478bd9Sstevel@tonic-gate */
2277c478bd9Sstevel@tonic-gate DL_ETHER, /* dl_mac_type */
2287c478bd9Sstevel@tonic-gate 0, /* dl_reserved */
2297c478bd9Sstevel@tonic-gate 0, /* dl_current_state */
2307c478bd9Sstevel@tonic-gate SPPP_SAPL, /* dl_sap_length */
2317c478bd9Sstevel@tonic-gate DL_CLDLS, /* dl_service_mode */
2327c478bd9Sstevel@tonic-gate 0, /* dl_qos_length */
2337c478bd9Sstevel@tonic-gate 0, /* dl_qos_offset */
2347c478bd9Sstevel@tonic-gate 0, /* dl_range_length */
2357c478bd9Sstevel@tonic-gate 0, /* dl_range_offset */
2367c478bd9Sstevel@tonic-gate DL_STYLE2, /* dl_provider_style */
2377c478bd9Sstevel@tonic-gate sizeof (dl_info_ack_t), /* dl_addr_offset */
2387c478bd9Sstevel@tonic-gate DL_VERSION_2, /* dl_version */
2397c478bd9Sstevel@tonic-gate 0, /* dl_brdcst_addr_length */
2407c478bd9Sstevel@tonic-gate 0, /* dl_brdcst_addr_offset */
2417c478bd9Sstevel@tonic-gate 0 /* dl_growth */
2427c478bd9Sstevel@tonic-gate };
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate * sppp_dlpi_pinfoinit()
2467c478bd9Sstevel@tonic-gate *
2477c478bd9Sstevel@tonic-gate * Description:
2487c478bd9Sstevel@tonic-gate * Initialize dl_pinfo[], called from sppp_attach.
2497c478bd9Sstevel@tonic-gate */
2507c478bd9Sstevel@tonic-gate void
sppp_dlpi_pinfoinit(void)2517c478bd9Sstevel@tonic-gate sppp_dlpi_pinfoinit(void)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate bzero(dl_pinfo, sizeof (dl_pinfo)); /* Just to be safe */
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate dl_pinfo[DL_ATTACH_REQ].pi_minlen = sizeof (dl_attach_req_t);
2567c478bd9Sstevel@tonic-gate dl_pinfo[DL_ATTACH_REQ].pi_state = DL_UNATTACHED;
2577c478bd9Sstevel@tonic-gate dl_pinfo[DL_ATTACH_REQ].pi_funcp = sppp_dlattachreq;
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate dl_pinfo[DL_DETACH_REQ].pi_minlen = sizeof (dl_detach_req_t);
2607c478bd9Sstevel@tonic-gate dl_pinfo[DL_DETACH_REQ].pi_state = DL_UNBOUND;
2617c478bd9Sstevel@tonic-gate dl_pinfo[DL_DETACH_REQ].pi_funcp = sppp_dldetachreq;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate dl_pinfo[DL_BIND_REQ].pi_minlen = sizeof (dl_bind_req_t);
2647c478bd9Sstevel@tonic-gate dl_pinfo[DL_BIND_REQ].pi_state = DL_UNBOUND;
2657c478bd9Sstevel@tonic-gate dl_pinfo[DL_BIND_REQ].pi_funcp = sppp_dlbindreq;
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate dl_pinfo[DL_UNBIND_REQ].pi_minlen = sizeof (dl_unbind_req_t);
2687c478bd9Sstevel@tonic-gate dl_pinfo[DL_UNBIND_REQ].pi_state = DL_IDLE;
2697c478bd9Sstevel@tonic-gate dl_pinfo[DL_UNBIND_REQ].pi_funcp = sppp_dlunbindreq;
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate dl_pinfo[DL_INFO_REQ].pi_minlen = sizeof (dl_info_req_t);
272*f53eecf5SJames Carlson dl_pinfo[DL_INFO_REQ].pi_state = -1; /* special handling */
2737c478bd9Sstevel@tonic-gate dl_pinfo[DL_INFO_REQ].pi_funcp = sppp_dlinforeq;
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate dl_pinfo[DL_UNITDATA_REQ].pi_minlen = sizeof (dl_unitdata_req_t);
2767c478bd9Sstevel@tonic-gate dl_pinfo[DL_UNITDATA_REQ].pi_state = DL_IDLE;
2777c478bd9Sstevel@tonic-gate dl_pinfo[DL_UNITDATA_REQ].pi_funcp = sppp_dlunitdatareq;
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate dl_pinfo[DL_PROMISCON_REQ].pi_minlen = sizeof (dl_promiscon_req_t);
280*f53eecf5SJames Carlson dl_pinfo[DL_PROMISCON_REQ].pi_state = -1; /* special handling */
2817c478bd9Sstevel@tonic-gate dl_pinfo[DL_PROMISCON_REQ].pi_funcp = sppp_dlpromisconreq;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate dl_pinfo[DL_PROMISCOFF_REQ].pi_minlen = sizeof (dl_promiscoff_req_t);
284*f53eecf5SJames Carlson dl_pinfo[DL_PROMISCOFF_REQ].pi_state = -1; /* special handling */
2857c478bd9Sstevel@tonic-gate dl_pinfo[DL_PROMISCOFF_REQ].pi_funcp = sppp_dlpromiscoffreq;
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate dl_pinfo[DL_PHYS_ADDR_REQ].pi_minlen = sizeof (dl_phys_addr_req_t);
288*f53eecf5SJames Carlson dl_pinfo[DL_PHYS_ADDR_REQ].pi_state = -1; /* special handling */
2897c478bd9Sstevel@tonic-gate dl_pinfo[DL_PHYS_ADDR_REQ].pi_funcp = sppp_dlphyreq;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate * sppp_mproto()
2947c478bd9Sstevel@tonic-gate *
2957c478bd9Sstevel@tonic-gate * MT-Perimeters:
2967c478bd9Sstevel@tonic-gate * shared inner, shared outer.
2977c478bd9Sstevel@tonic-gate *
2987c478bd9Sstevel@tonic-gate * Description:
2997c478bd9Sstevel@tonic-gate * Handle M_PCPROTO/M_PROTO messages, called by sppp_uwput.
3007c478bd9Sstevel@tonic-gate */
3017c478bd9Sstevel@tonic-gate int
sppp_mproto(queue_t * q,mblk_t * mp,spppstr_t * sps)3027c478bd9Sstevel@tonic-gate sppp_mproto(queue_t *q, mblk_t *mp, spppstr_t *sps)
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
3057c478bd9Sstevel@tonic-gate struct sppp_dlpi_pinfo_t *dpi;
3067c478bd9Sstevel@tonic-gate t_uscalar_t prim;
3077c478bd9Sstevel@tonic-gate int len;
3087c478bd9Sstevel@tonic-gate int error = 0;
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate ASSERT(!IS_SPS_CONTROL(sps));
3117c478bd9Sstevel@tonic-gate if ((len = MBLKL(mp)) < sizeof (t_uscalar_t)) {
3127c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "bad mproto: block length %d\n", len));
3137c478bd9Sstevel@tonic-gate merror(q, mp, EPROTO);
3147c478bd9Sstevel@tonic-gate return (0);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
3177c478bd9Sstevel@tonic-gate prim = dlp->dl_primitive;
3187c478bd9Sstevel@tonic-gate if (prim > DL_MAXPRIM) {
3197c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "bad mproto: primitive %d > %d\n", prim,
3207c478bd9Sstevel@tonic-gate DL_MAXPRIM));
3217c478bd9Sstevel@tonic-gate error = DL_BADPRIM;
3227c478bd9Sstevel@tonic-gate } else {
3237c478bd9Sstevel@tonic-gate dpi = &dl_pinfo[prim];
3247c478bd9Sstevel@tonic-gate if (dpi->pi_funcp == NULL) {
3257c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT,
3267c478bd9Sstevel@tonic-gate "bad mproto: primitive %d not supported\n", prim));
3277c478bd9Sstevel@tonic-gate error = DL_NOTSUPPORTED;
3287c478bd9Sstevel@tonic-gate } else if (len < dpi->pi_minlen) {
3297c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT,
3307c478bd9Sstevel@tonic-gate "bad mproto: primitive len %d < %d\n", len,
3317c478bd9Sstevel@tonic-gate dpi->pi_minlen));
3327c478bd9Sstevel@tonic-gate error = DL_BADPRIM;
333*f53eecf5SJames Carlson } else if (dpi->pi_state != -1 &&
334*f53eecf5SJames Carlson sps->sps_dlstate != dpi->pi_state) {
3357c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT,
3367c478bd9Sstevel@tonic-gate "bad state %d != %d for primitive %d\n",
3377c478bd9Sstevel@tonic-gate sps->sps_dlstate, dpi->pi_state, prim));
3387c478bd9Sstevel@tonic-gate error = DL_OUTSTATE;
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate if (error != 0) {
3427c478bd9Sstevel@tonic-gate dlerrorack(q, mp, dlp->dl_primitive, error, 0);
3437c478bd9Sstevel@tonic-gate return (0);
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate const char *cp = prim2name(prim);
3487c478bd9Sstevel@tonic-gate if (cp != NULL)
3497c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "/%d: Dispatching %s\n",
3507c478bd9Sstevel@tonic-gate sps->sps_mn_id, cp);
3517c478bd9Sstevel@tonic-gate else
3527c478bd9Sstevel@tonic-gate cmn_err(CE_CONT,
3537c478bd9Sstevel@tonic-gate "/%d: Dispatching unknown primitive %d\n",
3547c478bd9Sstevel@tonic-gate sps->sps_mn_id, prim);
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate #endif
3577c478bd9Sstevel@tonic-gate return ((*dpi->pi_funcp)(q, mp, sps));
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate * sppp_dlattachreq()
3627c478bd9Sstevel@tonic-gate *
3637c478bd9Sstevel@tonic-gate * MT-Perimeters:
3647c478bd9Sstevel@tonic-gate * shared inner, shared outer.
3657c478bd9Sstevel@tonic-gate *
3667c478bd9Sstevel@tonic-gate * Description:
3677c478bd9Sstevel@tonic-gate * Perform DL_ATTACH_REQ request, called by sppp_mproto.
3687c478bd9Sstevel@tonic-gate */
3697c478bd9Sstevel@tonic-gate static int
sppp_dlattachreq(queue_t * q,mblk_t * mp,spppstr_t * sps)3707c478bd9Sstevel@tonic-gate sppp_dlattachreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate int error = 0;
3737c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
3767c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
3777c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
3787c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
3797c478bd9Sstevel@tonic-gate ASSERT(sps->sps_dlstate == DL_UNATTACHED);
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate if (IS_SPS_PIOATTACH(sps)) {
3827c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI attach: already attached\n"));
3837c478bd9Sstevel@tonic-gate error = EINVAL;
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate if (error != 0) {
3867c478bd9Sstevel@tonic-gate dlerrorack(q, mp, dlp->dl_primitive, DL_OUTSTATE, error);
3877c478bd9Sstevel@tonic-gate } else {
3887c478bd9Sstevel@tonic-gate qwriter(q, mp, sppp_dl_attach_upper, PERIM_OUTER);
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate return (0);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate /*
3947c478bd9Sstevel@tonic-gate * sppp_dl_attach_upper()
3957c478bd9Sstevel@tonic-gate *
3967c478bd9Sstevel@tonic-gate * MT-Perimeters:
3977c478bd9Sstevel@tonic-gate * exclusive inner, exclusive outer.
3987c478bd9Sstevel@tonic-gate *
3997c478bd9Sstevel@tonic-gate * Description:
4007c478bd9Sstevel@tonic-gate * Called by qwriter (INNER) from sppp_dlattachreq as the result of
4017c478bd9Sstevel@tonic-gate * receiving a DL_ATTACH_REQ message.
4027c478bd9Sstevel@tonic-gate */
4037c478bd9Sstevel@tonic-gate static void
sppp_dl_attach_upper(queue_t * q,mblk_t * mp)4047c478bd9Sstevel@tonic-gate sppp_dl_attach_upper(queue_t *q, mblk_t *mp)
4057c478bd9Sstevel@tonic-gate {
4067c478bd9Sstevel@tonic-gate sppa_t *ppa;
407*f53eecf5SJames Carlson spppstr_t *sps = q->q_ptr;
4087c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
409*f53eecf5SJames Carlson int err = ENOMEM;
410*f53eecf5SJames Carlson cred_t *cr;
411*f53eecf5SJames Carlson zoneid_t zoneid;
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate ASSERT(!IS_SPS_PIOATTACH(sps));
4147c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate /* If there's something here, it's detached. */
4177c478bd9Sstevel@tonic-gate if (sps->sps_ppa != NULL) {
4187c478bd9Sstevel@tonic-gate sppp_remove_ppa(sps);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate
421*f53eecf5SJames Carlson if ((cr = msg_getcred(mp, NULL)) == NULL)
422*f53eecf5SJames Carlson zoneid = sps->sps_zoneid;
423*f53eecf5SJames Carlson else
424*f53eecf5SJames Carlson zoneid = crgetzoneid(cr);
425*f53eecf5SJames Carlson
4267c478bd9Sstevel@tonic-gate ppa = sppp_find_ppa(dlp->attach_req.dl_ppa);
427*f53eecf5SJames Carlson if (ppa == NULL) {
428*f53eecf5SJames Carlson ppa = sppp_create_ppa(dlp->attach_req.dl_ppa, zoneid);
429*f53eecf5SJames Carlson } else if (ppa->ppa_zoneid != zoneid) {
430*f53eecf5SJames Carlson ppa = NULL;
431*f53eecf5SJames Carlson err = EPERM;
432*f53eecf5SJames Carlson }
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate /*
435*f53eecf5SJames Carlson * If we can't find or create it, then it's either because we're out of
436*f53eecf5SJames Carlson * memory or because the requested PPA is owned by a different zone.
4377c478bd9Sstevel@tonic-gate */
4387c478bd9Sstevel@tonic-gate if (ppa == NULL) {
4397c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI attach: cannot create ppa %u\n",
4407c478bd9Sstevel@tonic-gate dlp->attach_req.dl_ppa));
441*f53eecf5SJames Carlson dlerrorack(q, mp, dlp->dl_primitive, DL_SYSERR, err);
4427c478bd9Sstevel@tonic-gate return;
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate * Preallocate the hangup message so that we're always able to
4467c478bd9Sstevel@tonic-gate * send this upstream in the event of a catastrophic failure.
4477c478bd9Sstevel@tonic-gate */
4487c478bd9Sstevel@tonic-gate if ((sps->sps_hangup = allocb(1, BPRI_MED)) == NULL) {
4497c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI attach: cannot allocate hangup\n"));
4507c478bd9Sstevel@tonic-gate dlerrorack(q, mp, dlp->dl_primitive, DL_SYSERR, ENOSR);
4517c478bd9Sstevel@tonic-gate return;
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate sps->sps_dlstate = DL_UNBOUND;
4547c478bd9Sstevel@tonic-gate sps->sps_ppa = ppa;
4557c478bd9Sstevel@tonic-gate /*
4567c478bd9Sstevel@tonic-gate * Add this stream to the head of the list of sibling streams
4577c478bd9Sstevel@tonic-gate * which belong to the specified ppa.
4587c478bd9Sstevel@tonic-gate */
4597c478bd9Sstevel@tonic-gate rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
4607c478bd9Sstevel@tonic-gate ppa->ppa_refcnt++;
4617c478bd9Sstevel@tonic-gate sps->sps_nextsib = ppa->ppa_streams;
4627c478bd9Sstevel@tonic-gate ppa->ppa_streams = sps;
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate * And if this stream was marked as promiscuous (SPS_PROMISC), then we
4657c478bd9Sstevel@tonic-gate * need to update the promiscuous streams count. This should only
4667c478bd9Sstevel@tonic-gate * happen when DL_PROMISCON_REQ was issued prior to attachment.
4677c478bd9Sstevel@tonic-gate */
4687c478bd9Sstevel@tonic-gate if (IS_SPS_PROMISC(sps)) {
4697c478bd9Sstevel@tonic-gate ppa->ppa_promicnt++;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate rw_exit(&ppa->ppa_sib_lock);
4727c478bd9Sstevel@tonic-gate DBGDLPI((CE_CONT, "/%d: attached to ppa %d\n", sps->sps_mn_id,
4737c478bd9Sstevel@tonic-gate ppa->ppa_ppa_id));
4747c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_ATTACH_REQ);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate /*
4787c478bd9Sstevel@tonic-gate * sppp_dldetachreq()
4797c478bd9Sstevel@tonic-gate *
4807c478bd9Sstevel@tonic-gate * MT-Perimeters:
4817c478bd9Sstevel@tonic-gate * shared inner, shared outer.
4827c478bd9Sstevel@tonic-gate *
4837c478bd9Sstevel@tonic-gate * Description:
4847c478bd9Sstevel@tonic-gate * Perform DL_DETACH_REQ request, called by sppp_mproto.
4857c478bd9Sstevel@tonic-gate */
4867c478bd9Sstevel@tonic-gate /* ARGSUSED */
4877c478bd9Sstevel@tonic-gate static int
sppp_dldetachreq(queue_t * q,mblk_t * mp,spppstr_t * sps)4887c478bd9Sstevel@tonic-gate sppp_dldetachreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
4897c478bd9Sstevel@tonic-gate {
4907c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
4917c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
4927c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
4937c478bd9Sstevel@tonic-gate ASSERT(sps->sps_dlstate == DL_UNBOUND);
4947c478bd9Sstevel@tonic-gate ASSERT(!IS_SPS_PIOATTACH(sps));
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate qwriter(q, mp, sppp_dl_detach_upper, PERIM_INNER);
4977c478bd9Sstevel@tonic-gate return (0);
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate /*
5017c478bd9Sstevel@tonic-gate * sppp_dl_detach_upper()
5027c478bd9Sstevel@tonic-gate *
5037c478bd9Sstevel@tonic-gate * MT-Perimeters:
5047c478bd9Sstevel@tonic-gate * exclusive inner, shared outer.
5057c478bd9Sstevel@tonic-gate *
5067c478bd9Sstevel@tonic-gate * Description:
5077c478bd9Sstevel@tonic-gate * Called by qwriter (INNER) from sppp_dldetachreq as the result of
5087c478bd9Sstevel@tonic-gate * receiving a DL_DETACH_REQ message.
5097c478bd9Sstevel@tonic-gate */
5107c478bd9Sstevel@tonic-gate /* ARGSUSED */
5117c478bd9Sstevel@tonic-gate static void
sppp_dl_detach_upper(queue_t * q,mblk_t * mp)5127c478bd9Sstevel@tonic-gate sppp_dl_detach_upper(queue_t *q, mblk_t *mp)
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate spppstr_t *sps;
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
5177c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
5187c478bd9Sstevel@tonic-gate sps = (spppstr_t *)q->q_ptr;
5197c478bd9Sstevel@tonic-gate /*
5207c478bd9Sstevel@tonic-gate * We don't actually detach from the PPA until closed or
5217c478bd9Sstevel@tonic-gate * reattached.
5227c478bd9Sstevel@tonic-gate */
5237c478bd9Sstevel@tonic-gate sps->sps_flags &= ~SPS_PROMISC; /* clear flag anyway */
5247c478bd9Sstevel@tonic-gate sps->sps_dlstate = DL_UNATTACHED;
5257c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_DETACH_REQ);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate * sppp_dlbindreq()
5307c478bd9Sstevel@tonic-gate *
5317c478bd9Sstevel@tonic-gate * MT-Perimeters:
5327c478bd9Sstevel@tonic-gate * shared inner, shared outer.
5337c478bd9Sstevel@tonic-gate *
5347c478bd9Sstevel@tonic-gate * Description:
5357c478bd9Sstevel@tonic-gate * Perform DL_BIND_REQ request, called by sppp_mproto.
5367c478bd9Sstevel@tonic-gate */
5377c478bd9Sstevel@tonic-gate static int
sppp_dlbindreq(queue_t * q,mblk_t * mp,spppstr_t * sps)5387c478bd9Sstevel@tonic-gate sppp_dlbindreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
5397c478bd9Sstevel@tonic-gate {
5407c478bd9Sstevel@tonic-gate sppa_t *ppa;
5417c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
5427c478bd9Sstevel@tonic-gate spppreqsap_t req_sap;
5437c478bd9Sstevel@tonic-gate int error = 0;
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
5467c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
5477c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
5487c478bd9Sstevel@tonic-gate req_sap = dlp->bind_req.dl_sap;
5497c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
5507c478bd9Sstevel@tonic-gate ASSERT(!IS_SPS_PIOATTACH(sps));
5517c478bd9Sstevel@tonic-gate ASSERT(sps->sps_dlstate == DL_UNBOUND);
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate ppa = sps->sps_ppa;
5547c478bd9Sstevel@tonic-gate if (ppa == NULL) {
5557c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI bind: no attached ppa\n"));
5567c478bd9Sstevel@tonic-gate error = DL_OUTSTATE;
5577c478bd9Sstevel@tonic-gate } else if ((req_sap != ETHERTYPE_IP) && (req_sap != ETHERTYPE_IPV6) &&
558*f53eecf5SJames Carlson (req_sap != ETHERTYPE_ALLSAP)) {
5597c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI bind: unknown SAP %x\n", req_sap));
5607c478bd9Sstevel@tonic-gate error = DL_BADADDR;
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate if (error != 0) {
5637c478bd9Sstevel@tonic-gate dlerrorack(q, mp, dlp->dl_primitive, error, 0);
5647c478bd9Sstevel@tonic-gate } else {
5657c478bd9Sstevel@tonic-gate qwriter(q, mp, sppp_dl_bind, PERIM_INNER);
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate return (0);
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate /*
5717c478bd9Sstevel@tonic-gate * sppp_dl_bind()
5727c478bd9Sstevel@tonic-gate *
5737c478bd9Sstevel@tonic-gate * MT-Perimeters:
5747c478bd9Sstevel@tonic-gate * exclusive inner, shared outer.
5757c478bd9Sstevel@tonic-gate *
5767c478bd9Sstevel@tonic-gate * Description:
5777c478bd9Sstevel@tonic-gate * Called by qwriter (INNER) from sppp_dlbindreq as the result of
5787c478bd9Sstevel@tonic-gate * receiving a DL_BIND_REQ message.
5797c478bd9Sstevel@tonic-gate */
5807c478bd9Sstevel@tonic-gate static void
sppp_dl_bind(queue_t * q,mblk_t * mp)5817c478bd9Sstevel@tonic-gate sppp_dl_bind(queue_t *q, mblk_t *mp)
5827c478bd9Sstevel@tonic-gate {
5837c478bd9Sstevel@tonic-gate spppstr_t *sps;
5847c478bd9Sstevel@tonic-gate sppa_t *ppa;
5857c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
5867c478bd9Sstevel@tonic-gate t_scalar_t sap;
5877c478bd9Sstevel@tonic-gate spppreqsap_t req_sap;
5887c478bd9Sstevel@tonic-gate mblk_t *lsmp;
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
5917c478bd9Sstevel@tonic-gate sps = (spppstr_t *)q->q_ptr;
5927c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
5937c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
5947c478bd9Sstevel@tonic-gate ppa = sps->sps_ppa;
5957c478bd9Sstevel@tonic-gate ASSERT(ppa != NULL);
5967c478bd9Sstevel@tonic-gate req_sap = dlp->bind_req.dl_sap;
5977c478bd9Sstevel@tonic-gate ASSERT((req_sap == ETHERTYPE_IP) || (req_sap == ETHERTYPE_IPV6) ||
598*f53eecf5SJames Carlson (req_sap == ETHERTYPE_ALLSAP));
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate if (req_sap == ETHERTYPE_IP) {
6017c478bd9Sstevel@tonic-gate sap = PPP_IP;
6027c478bd9Sstevel@tonic-gate } else if (req_sap == ETHERTYPE_IPV6) {
6037c478bd9Sstevel@tonic-gate sap = PPP_IPV6;
6047c478bd9Sstevel@tonic-gate } else if (req_sap == ETHERTYPE_ALLSAP) {
6057c478bd9Sstevel@tonic-gate sap = PPP_ALLSAP;
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate /*
6087c478bd9Sstevel@tonic-gate * If there's another stream with the same sap has already been bound
6097c478bd9Sstevel@tonic-gate * to the same ppa, then return with DL_NOADDR. However, we do make an
6107c478bd9Sstevel@tonic-gate * exception for snoop (req_sap=0x00, sap=0xff) since multiple
6117c478bd9Sstevel@tonic-gate * instances of snoop may execute an a given device.
6127c478bd9Sstevel@tonic-gate */
6137c478bd9Sstevel@tonic-gate lsmp = NULL;
6147c478bd9Sstevel@tonic-gate if (sap != PPP_ALLSAP) {
6157c478bd9Sstevel@tonic-gate if ((sap == PPP_IP) && (ppa->ppa_ip_cache == NULL)) {
6167c478bd9Sstevel@tonic-gate ppa->ppa_ip_cache = sps;
6177c478bd9Sstevel@tonic-gate if (ppa->ppa_ctl != NULL) {
6187c478bd9Sstevel@tonic-gate lsmp = create_lsmsg(PPP_LINKSTAT_IPV4_BOUND);
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate } else if ((sap == PPP_IPV6) && (ppa->ppa_ip6_cache == NULL)) {
6217c478bd9Sstevel@tonic-gate ppa->ppa_ip6_cache = sps;
6227c478bd9Sstevel@tonic-gate if (ppa->ppa_ctl != NULL) {
6237c478bd9Sstevel@tonic-gate lsmp = create_lsmsg(PPP_LINKSTAT_IPV6_BOUND);
6247c478bd9Sstevel@tonic-gate }
6257c478bd9Sstevel@tonic-gate } else {
6267c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI bind: bad SAP %x\n", sap));
6277c478bd9Sstevel@tonic-gate dlerrorack(q, mp, dlp->dl_primitive, DL_NOADDR,
6287c478bd9Sstevel@tonic-gate EEXIST);
6297c478bd9Sstevel@tonic-gate return;
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate sps->sps_flags |= SPS_CACHED;
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate /*
6347c478bd9Sstevel@tonic-gate * Tell the daemon that a DLPI bind has happened on this stream,
6357c478bd9Sstevel@tonic-gate * and we'll only do this for PPP_IP or PPP_IPV6 sap (not snoop).
6367c478bd9Sstevel@tonic-gate */
6377c478bd9Sstevel@tonic-gate if (lsmp != NULL && ppa->ppa_ctl != NULL) {
6387c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
6397c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "sending up %s\n",
6407c478bd9Sstevel@tonic-gate ((sap == PPP_IP) ? "PPP_LINKSTAT_IPV4_BOUND" :
6417c478bd9Sstevel@tonic-gate "PPP_LINKSTAT_IPV6_BOUND"));
6427c478bd9Sstevel@tonic-gate #endif
6437c478bd9Sstevel@tonic-gate putnext(ppa->ppa_ctl->sps_rq, lsmp);
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate DBGDLPI((CE_CONT, "/%d: bound to sap %X (req %X)\n", sps->sps_mn_id,
6467c478bd9Sstevel@tonic-gate sap, req_sap));
6477c478bd9Sstevel@tonic-gate sps->sps_req_sap = req_sap;
6487c478bd9Sstevel@tonic-gate sps->sps_sap = sap;
6497c478bd9Sstevel@tonic-gate sps->sps_dlstate = DL_IDLE;
6507c478bd9Sstevel@tonic-gate dlbindack(q, mp, req_sap, &sap, sizeof (int32_t), 0, 0);
6517c478bd9Sstevel@tonic-gate }
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate /*
6547c478bd9Sstevel@tonic-gate * sppp_dlunbindreq()
6557c478bd9Sstevel@tonic-gate *
6567c478bd9Sstevel@tonic-gate * MT-Perimeters:
6577c478bd9Sstevel@tonic-gate * shared inner, shared outer.
6587c478bd9Sstevel@tonic-gate *
6597c478bd9Sstevel@tonic-gate * Description:
6607c478bd9Sstevel@tonic-gate * Perform DL_UNBIND_REQ request, called by sppp_mproto.
6617c478bd9Sstevel@tonic-gate */
6627c478bd9Sstevel@tonic-gate /* ARGSUSED */
6637c478bd9Sstevel@tonic-gate static int
sppp_dlunbindreq(queue_t * q,mblk_t * mp,spppstr_t * sps)6647c478bd9Sstevel@tonic-gate sppp_dlunbindreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
6677c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
6687c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
6697c478bd9Sstevel@tonic-gate ASSERT(!IS_SPS_PIOATTACH(sps));
6707c478bd9Sstevel@tonic-gate ASSERT(sps->sps_dlstate == DL_IDLE);
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate qwriter(q, mp, sppp_dl_unbind, PERIM_INNER);
6737c478bd9Sstevel@tonic-gate return (0);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate * sppp_dl_unbind()
6787c478bd9Sstevel@tonic-gate *
6797c478bd9Sstevel@tonic-gate * MT-Perimeters:
6807c478bd9Sstevel@tonic-gate * exclusive inner, shared outer.
6817c478bd9Sstevel@tonic-gate *
6827c478bd9Sstevel@tonic-gate * Description:
6837c478bd9Sstevel@tonic-gate * Called by qwriter (INNER) from sppp_dlunbindreq as the result of
6847c478bd9Sstevel@tonic-gate * receiving a DL_UNBIND_REQ message.
6857c478bd9Sstevel@tonic-gate */
6867c478bd9Sstevel@tonic-gate static void
sppp_dl_unbind(queue_t * q,mblk_t * mp)6877c478bd9Sstevel@tonic-gate sppp_dl_unbind(queue_t *q, mblk_t *mp)
6887c478bd9Sstevel@tonic-gate {
6897c478bd9Sstevel@tonic-gate spppstr_t *sps;
6907c478bd9Sstevel@tonic-gate sppa_t *ppa;
6917c478bd9Sstevel@tonic-gate t_scalar_t sap;
6927c478bd9Sstevel@tonic-gate mblk_t *msg;
6937c478bd9Sstevel@tonic-gate boolean_t saydown;
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
6967c478bd9Sstevel@tonic-gate sps = (spppstr_t *)q->q_ptr;
6977c478bd9Sstevel@tonic-gate ppa = sps->sps_ppa;
6987c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
6997c478bd9Sstevel@tonic-gate sap = sps->sps_sap;
7007c478bd9Sstevel@tonic-gate ASSERT((sap == PPP_IP) || (sap == PPP_IPV6) || (sap == PPP_ALLSAP));
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate /* Flush messages on unbind, per DLPI specification. */
7037c478bd9Sstevel@tonic-gate flushq(WR(q), FLUSHALL);
7047c478bd9Sstevel@tonic-gate flushq(RD(q), FLUSHALL);
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate if ((ppa != NULL) && IS_SPS_CACHED(sps)) {
7077c478bd9Sstevel@tonic-gate sps->sps_flags &= ~SPS_CACHED;
7087c478bd9Sstevel@tonic-gate msg = NULL;
7097c478bd9Sstevel@tonic-gate saydown = (ppa->ppa_ctl != NULL &&
7107c478bd9Sstevel@tonic-gate (sps->sps_npmode == NPMODE_PASS ||
711*f53eecf5SJames Carlson sps->sps_npmode == NPMODE_QUEUE));
7127c478bd9Sstevel@tonic-gate if (sap == PPP_IP) {
7137c478bd9Sstevel@tonic-gate ppa->ppa_ip_cache = NULL;
7147c478bd9Sstevel@tonic-gate if (saydown)
7157c478bd9Sstevel@tonic-gate msg = create_lsmsg(PPP_LINKSTAT_IPV4_UNBOUND);
7167c478bd9Sstevel@tonic-gate } else if (sap == PPP_IPV6) {
7177c478bd9Sstevel@tonic-gate ppa->ppa_ip6_cache = NULL;
7187c478bd9Sstevel@tonic-gate if (saydown)
7197c478bd9Sstevel@tonic-gate msg = create_lsmsg(PPP_LINKSTAT_IPV6_UNBOUND);
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate if (msg != NULL) {
7227c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
7237c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "sending up %s\n",
7247c478bd9Sstevel@tonic-gate ((sap == PPP_IP) ? "PPP_LINKSTAT_IPV4_UNBOUND" :
7257c478bd9Sstevel@tonic-gate "PPP_LINKSTAT_IPV6_UNBOUND"));
7267c478bd9Sstevel@tonic-gate #endif
7277c478bd9Sstevel@tonic-gate putnext(ppa->ppa_ctl->sps_rq, msg);
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate DBGDLPI((CE_CONT, "/%d: unbound from sap %X (req %X)\n", sps->sps_mn_id,
7317c478bd9Sstevel@tonic-gate sps->sps_sap, sps->sps_req_sap));
7327c478bd9Sstevel@tonic-gate sps->sps_req_sap = 0;
7337c478bd9Sstevel@tonic-gate sps->sps_sap = -1;
7347c478bd9Sstevel@tonic-gate sps->sps_dlstate = DL_UNBOUND;
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_UNBIND_REQ);
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate /*
7407c478bd9Sstevel@tonic-gate * sppp_dlinforeq()
7417c478bd9Sstevel@tonic-gate *
7427c478bd9Sstevel@tonic-gate * MT-Perimeters:
7437c478bd9Sstevel@tonic-gate * shared inner, shared outer.
7447c478bd9Sstevel@tonic-gate *
7457c478bd9Sstevel@tonic-gate * Description:
7467c478bd9Sstevel@tonic-gate * Perform DL_INFO_REQ request, called by sppp_mproto.
7477c478bd9Sstevel@tonic-gate */
7487c478bd9Sstevel@tonic-gate static int
sppp_dlinforeq(queue_t * q,mblk_t * mp,spppstr_t * sps)7497c478bd9Sstevel@tonic-gate sppp_dlinforeq(queue_t *q, mblk_t *mp, spppstr_t *sps)
7507c478bd9Sstevel@tonic-gate {
7517c478bd9Sstevel@tonic-gate dl_info_ack_t *dlip;
7527c478bd9Sstevel@tonic-gate uint32_t size;
7537c478bd9Sstevel@tonic-gate uint32_t addr_size;
7547c478bd9Sstevel@tonic-gate sppa_t *ppa;
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
7577c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
7587c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
7597c478bd9Sstevel@tonic-gate ppa = sps->sps_ppa;
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate /* Exchange current msg for a DL_INFO_ACK. */
7627c478bd9Sstevel@tonic-gate addr_size = SPPP_ADDRL;
7637c478bd9Sstevel@tonic-gate size = sizeof (dl_info_ack_t) + addr_size;
7647c478bd9Sstevel@tonic-gate if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL) {
7657c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI info: mexchange failed\n"));
7667c478bd9Sstevel@tonic-gate /* mexchange already sent up an merror ENOSR */
7677c478bd9Sstevel@tonic-gate return (0);
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate /* Fill in DL_INFO_ACK fields and reply */
7707c478bd9Sstevel@tonic-gate dlip = (dl_info_ack_t *)mp->b_rptr;
7717c478bd9Sstevel@tonic-gate *dlip = sppp_infoack;
7727c478bd9Sstevel@tonic-gate dlip->dl_current_state = sps->sps_dlstate;
7737c478bd9Sstevel@tonic-gate dlip->dl_max_sdu = ppa != NULL ? ppa->ppa_mtu : PPP_MAXMTU;
7747c478bd9Sstevel@tonic-gate #ifdef DBG_DLPI
7757c478bd9Sstevel@tonic-gate {
7767c478bd9Sstevel@tonic-gate const char *cp = state2name(dlip->dl_current_state);
7777c478bd9Sstevel@tonic-gate if (cp != NULL)
7787c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "info returns state %s, max sdu %d\n",
7797c478bd9Sstevel@tonic-gate cp, dlip->dl_max_sdu);
7807c478bd9Sstevel@tonic-gate else
7817c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "info returns state %d, max sdu %d\n",
7827c478bd9Sstevel@tonic-gate dlip->dl_current_state, dlip->dl_max_sdu);
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate #endif
7857c478bd9Sstevel@tonic-gate qreply(q, mp);
7867c478bd9Sstevel@tonic-gate return (0);
7877c478bd9Sstevel@tonic-gate }
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate /*
7907c478bd9Sstevel@tonic-gate * sppp_dlunitdatareq()
7917c478bd9Sstevel@tonic-gate *
7927c478bd9Sstevel@tonic-gate * MT-Perimeters:
7937c478bd9Sstevel@tonic-gate * shared inner, shared outer.
7947c478bd9Sstevel@tonic-gate *
7957c478bd9Sstevel@tonic-gate * Description:
7967c478bd9Sstevel@tonic-gate * Handle DL_UNITDATA_REQ request, called by sppp_mproto. This procedure
7977c478bd9Sstevel@tonic-gate * gets called for M_PROTO (DLPI) style of transmission. The fact that we
7987c478bd9Sstevel@tonic-gate * have acknowledged IP's fastpath probing (DL_IOC_HDR_INFO) does not
7997c478bd9Sstevel@tonic-gate * guarantee that IP will always transmit via M_DATA, and it merely implies
8007c478bd9Sstevel@tonic-gate * that such situation _may_ happen. In other words, IP may decide to use
8017c478bd9Sstevel@tonic-gate * M_PROTO (DLPI) for data transmission should it decide to do so.
8027c478bd9Sstevel@tonic-gate * Therefore, we should never place any restrictions or checks against
8037c478bd9Sstevel@tonic-gate * streams marked with SPS_FASTPATH, since it is legal for this procedure
8047c478bd9Sstevel@tonic-gate * to be entered with or without the bit set.
8057c478bd9Sstevel@tonic-gate */
8067c478bd9Sstevel@tonic-gate static int
sppp_dlunitdatareq(queue_t * q,mblk_t * mp,spppstr_t * sps)8077c478bd9Sstevel@tonic-gate sppp_dlunitdatareq(queue_t *q, mblk_t *mp, spppstr_t *sps)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate sppa_t *ppa;
8107c478bd9Sstevel@tonic-gate mblk_t *hdrmp;
8117c478bd9Sstevel@tonic-gate mblk_t *pktmp;
8127c478bd9Sstevel@tonic-gate dl_unitdata_req_t *dludp;
8137c478bd9Sstevel@tonic-gate int dladdroff;
8147c478bd9Sstevel@tonic-gate int dladdrlen;
8157c478bd9Sstevel@tonic-gate int msize;
8167c478bd9Sstevel@tonic-gate int error = 0;
8177c478bd9Sstevel@tonic-gate boolean_t is_promisc;
8187c478bd9Sstevel@tonic-gate
8197c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
8207c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
8217c478bd9Sstevel@tonic-gate ASSERT((MTYPE(mp) == M_PCPROTO) || (MTYPE(mp) == M_PROTO));
8227c478bd9Sstevel@tonic-gate dludp = (dl_unitdata_req_t *)mp->b_rptr;
8237c478bd9Sstevel@tonic-gate dladdroff = dludp->dl_dest_addr_offset;
8247c478bd9Sstevel@tonic-gate dladdrlen = dludp->dl_dest_addr_length;
8257c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
8267c478bd9Sstevel@tonic-gate ASSERT(!IS_SPS_PIOATTACH(sps));
8277c478bd9Sstevel@tonic-gate ASSERT(sps->sps_dlstate == DL_IDLE);
8287c478bd9Sstevel@tonic-gate ASSERT(q->q_ptr == sps);
8297c478bd9Sstevel@tonic-gate /*
8307c478bd9Sstevel@tonic-gate * If this stream is not attached to any ppas, then discard data
8317c478bd9Sstevel@tonic-gate * coming down through this stream.
8327c478bd9Sstevel@tonic-gate */
8337c478bd9Sstevel@tonic-gate ppa = sps->sps_ppa;
8347c478bd9Sstevel@tonic-gate if (ppa == NULL) {
8357c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI unitdata: no attached ppa\n"));
8367c478bd9Sstevel@tonic-gate error = ENOLINK;
8377c478bd9Sstevel@tonic-gate } else if (mp->b_cont == NULL) {
8387c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI unitdata: missing data\n"));
8397c478bd9Sstevel@tonic-gate error = EPROTO;
8407c478bd9Sstevel@tonic-gate }
8417c478bd9Sstevel@tonic-gate if (error != 0) {
8427c478bd9Sstevel@tonic-gate dluderrorind(q, mp, mp->b_rptr + dladdroff, dladdrlen,
8437c478bd9Sstevel@tonic-gate DL_BADDATA, error);
8447c478bd9Sstevel@tonic-gate return (0);
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate ASSERT(mp->b_cont->b_rptr != NULL);
8477c478bd9Sstevel@tonic-gate /*
8487c478bd9Sstevel@tonic-gate * Check if outgoing packet size is larger than allowed. We use
8497c478bd9Sstevel@tonic-gate * msgdsize to count all of M_DATA blocks in the message.
8507c478bd9Sstevel@tonic-gate */
8517c478bd9Sstevel@tonic-gate msize = msgdsize(mp);
8527c478bd9Sstevel@tonic-gate if (msize > ppa->ppa_mtu) {
8537c478bd9Sstevel@tonic-gate /* Log, and send it anyway */
8547c478bd9Sstevel@tonic-gate mutex_enter(&ppa->ppa_sta_lock);
8557c478bd9Sstevel@tonic-gate ppa->ppa_otoolongs++;
8567c478bd9Sstevel@tonic-gate mutex_exit(&ppa->ppa_sta_lock);
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate if (IS_SPS_KDEBUG(sps)) {
8597c478bd9Sstevel@tonic-gate SPDEBUG(PPP_DRV_NAME
8607c478bd9Sstevel@tonic-gate "/%d: DL_UNITDATA_REQ (%d bytes) sps=0x%p flags=0x%b "
8617c478bd9Sstevel@tonic-gate "ppa=0x%p flags=0x%b\n", sps->sps_mn_id, msize,
8627c478bd9Sstevel@tonic-gate (void *)sps, sps->sps_flags, SPS_FLAGS_STR,
8637c478bd9Sstevel@tonic-gate (void *)ppa, ppa->ppa_flags, PPA_FLAGS_STR);
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate /* Allocate a message (M_DATA) to contain PPP header bytes. */
8667c478bd9Sstevel@tonic-gate if ((hdrmp = allocb(PPP_HDRLEN, BPRI_MED)) == NULL) {
8677c478bd9Sstevel@tonic-gate mutex_enter(&ppa->ppa_sta_lock);
8687c478bd9Sstevel@tonic-gate ppa->ppa_allocbfail++;
8697c478bd9Sstevel@tonic-gate mutex_exit(&ppa->ppa_sta_lock);
8707c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT,
8717c478bd9Sstevel@tonic-gate "DLPI unitdata: can't allocate header buffer\n"));
8727c478bd9Sstevel@tonic-gate dluderrorind(q, mp, mp->b_rptr + dladdroff, dladdrlen,
8737c478bd9Sstevel@tonic-gate DL_SYSERR, ENOSR);
8747c478bd9Sstevel@tonic-gate return (0);
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate /*
8777c478bd9Sstevel@tonic-gate * Should there be any promiscuous stream(s), send the data up
8787c478bd9Sstevel@tonic-gate * for each promiscuous stream that we recognize.
8797c478bd9Sstevel@tonic-gate */
8807c478bd9Sstevel@tonic-gate rw_enter(&ppa->ppa_sib_lock, RW_READER);
8817c478bd9Sstevel@tonic-gate is_promisc = ppa->ppa_promicnt;
8827c478bd9Sstevel@tonic-gate if (is_promisc) {
8837c478bd9Sstevel@tonic-gate ASSERT(ppa->ppa_streams != NULL);
8847c478bd9Sstevel@tonic-gate sppp_dlprsendup(ppa->ppa_streams, mp->b_cont, sps->sps_sap,
8857c478bd9Sstevel@tonic-gate B_FALSE);
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate rw_exit(&ppa->ppa_sib_lock);
8887c478bd9Sstevel@tonic-gate /* Discard DLPI header and keep only IP payload (mp->b_cont). */
8897c478bd9Sstevel@tonic-gate pktmp = mp->b_cont;
8907c478bd9Sstevel@tonic-gate mp->b_cont = NULL;
8917c478bd9Sstevel@tonic-gate freemsg(mp);
8927c478bd9Sstevel@tonic-gate mp = hdrmp;
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate *(uchar_t *)mp->b_wptr++ = PPP_ALLSTATIONS;
8957c478bd9Sstevel@tonic-gate *(uchar_t *)mp->b_wptr++ = PPP_UI;
8967c478bd9Sstevel@tonic-gate *(uchar_t *)mp->b_wptr++ = ((uint16_t)sps->sps_sap >> 8) & 0xff;
8977c478bd9Sstevel@tonic-gate *(uchar_t *)mp->b_wptr++ = ((uint16_t)sps->sps_sap) & 0xff;
8987c478bd9Sstevel@tonic-gate ASSERT(MBLKL(mp) == PPP_HDRLEN);
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate linkb(mp, pktmp);
9017c478bd9Sstevel@tonic-gate /*
9027c478bd9Sstevel@tonic-gate * Only time-stamp the packet with hrtime if the upper stream
9037c478bd9Sstevel@tonic-gate * is configured to do so.
9047c478bd9Sstevel@tonic-gate */
9057c478bd9Sstevel@tonic-gate if (IS_PPA_TIMESTAMP(ppa)) {
9067c478bd9Sstevel@tonic-gate ppa->ppa_lasttx = gethrtime();
9077c478bd9Sstevel@tonic-gate }
9087c478bd9Sstevel@tonic-gate /*
9097c478bd9Sstevel@tonic-gate * Just put this back on the queue and allow the write service
9107c478bd9Sstevel@tonic-gate * routine to handle it. We're nested too deeply here to
9117c478bd9Sstevel@tonic-gate * rewind the stack sufficiently to prevent overflow. This is
9127c478bd9Sstevel@tonic-gate * the slow path anyway.
9137c478bd9Sstevel@tonic-gate */
9147c478bd9Sstevel@tonic-gate if (putq(q, mp) == 0) {
9157c478bd9Sstevel@tonic-gate mutex_enter(&ppa->ppa_sta_lock);
9167c478bd9Sstevel@tonic-gate ppa->ppa_oqdropped++;
9177c478bd9Sstevel@tonic-gate mutex_exit(&ppa->ppa_sta_lock);
9187c478bd9Sstevel@tonic-gate freemsg(mp);
9197c478bd9Sstevel@tonic-gate } else {
9207c478bd9Sstevel@tonic-gate qenable(q);
9217c478bd9Sstevel@tonic-gate }
9227c478bd9Sstevel@tonic-gate return (0);
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate /*
9267c478bd9Sstevel@tonic-gate * sppp_dlpromisconreq()
9277c478bd9Sstevel@tonic-gate *
9287c478bd9Sstevel@tonic-gate * MT-Perimeters:
9297c478bd9Sstevel@tonic-gate * shared inner, shared outer.
9307c478bd9Sstevel@tonic-gate *
9317c478bd9Sstevel@tonic-gate * Description:
9327c478bd9Sstevel@tonic-gate * Perform DL_PROMISCON_REQ request, called by sppp_mproto.
9337c478bd9Sstevel@tonic-gate */
9347c478bd9Sstevel@tonic-gate static int
sppp_dlpromisconreq(queue_t * q,mblk_t * mp,spppstr_t * sps)9357c478bd9Sstevel@tonic-gate sppp_dlpromisconreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
9367c478bd9Sstevel@tonic-gate {
9377c478bd9Sstevel@tonic-gate t_uscalar_t level;
9387c478bd9Sstevel@tonic-gate
9397c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
9407c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
9417c478bd9Sstevel@tonic-gate level = ((dl_promiscon_req_t *)mp->b_rptr)->dl_level;
9427c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
9437c478bd9Sstevel@tonic-gate
9447c478bd9Sstevel@tonic-gate /* snoop issues DL_PROMISCON_REQ more than once. */
9457c478bd9Sstevel@tonic-gate if (IS_SPS_PROMISC(sps)) {
9467c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_PROMISCON_REQ);
9477c478bd9Sstevel@tonic-gate } else if ((level != DL_PROMISC_PHYS) && (level != DL_PROMISC_SAP) &&
9487c478bd9Sstevel@tonic-gate (level != DL_PROMISC_MULTI)) {
9497c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI promiscon: bad level %d\n", level));
9507c478bd9Sstevel@tonic-gate dlerrorack(q, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
9517c478bd9Sstevel@tonic-gate } else {
9527c478bd9Sstevel@tonic-gate qwriter(q, mp, sppp_dl_promiscon, PERIM_INNER);
9537c478bd9Sstevel@tonic-gate }
9547c478bd9Sstevel@tonic-gate return (0);
9557c478bd9Sstevel@tonic-gate }
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate /*
9587c478bd9Sstevel@tonic-gate * sppp_dl_promiscon()
9597c478bd9Sstevel@tonic-gate *
9607c478bd9Sstevel@tonic-gate * MT-Perimeters:
9617c478bd9Sstevel@tonic-gate * exclusive inner, shared outer.
9627c478bd9Sstevel@tonic-gate *
9637c478bd9Sstevel@tonic-gate * Description:
9647c478bd9Sstevel@tonic-gate * Called by qwriter (INNER) from sppp_dlpromisconreq as the result of
9657c478bd9Sstevel@tonic-gate * receiving a DL_PROMISCON_REQ message.
9667c478bd9Sstevel@tonic-gate */
9677c478bd9Sstevel@tonic-gate static void
sppp_dl_promiscon(queue_t * q,mblk_t * mp)9687c478bd9Sstevel@tonic-gate sppp_dl_promiscon(queue_t *q, mblk_t *mp)
9697c478bd9Sstevel@tonic-gate {
9707c478bd9Sstevel@tonic-gate spppstr_t *sps;
9717c478bd9Sstevel@tonic-gate sppa_t *ppa;
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
9747c478bd9Sstevel@tonic-gate sps = (spppstr_t *)q->q_ptr;
9757c478bd9Sstevel@tonic-gate ASSERT(!IS_SPS_PROMISC(sps));
9767c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
9777c478bd9Sstevel@tonic-gate ppa = sps->sps_ppa;
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate sps->sps_flags |= SPS_PROMISC;
9807c478bd9Sstevel@tonic-gate /*
9817c478bd9Sstevel@tonic-gate * We can't be sure that the sps_ppa field is valid, since the DLPI
9827c478bd9Sstevel@tonic-gate * spec says that DL_PROMISCON_REQ can be issued at any state, i.e.,
9837c478bd9Sstevel@tonic-gate * the request can be issued even before DL_ATTACH_REQ or PPPIO_ATTACH
9847c478bd9Sstevel@tonic-gate * be issued to associate this stream with a ppa.
9857c478bd9Sstevel@tonic-gate */
9867c478bd9Sstevel@tonic-gate if (ppa != NULL) {
9877c478bd9Sstevel@tonic-gate rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
9887c478bd9Sstevel@tonic-gate ppa->ppa_promicnt++;
9897c478bd9Sstevel@tonic-gate rw_exit(&ppa->ppa_sib_lock);
9907c478bd9Sstevel@tonic-gate }
9917c478bd9Sstevel@tonic-gate DBGDLPI((CE_CONT, "/%d: promiscuous mode on\n", sps->sps_mn_id));
9927c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_PROMISCON_REQ);
9937c478bd9Sstevel@tonic-gate }
9947c478bd9Sstevel@tonic-gate
9957c478bd9Sstevel@tonic-gate /*
9967c478bd9Sstevel@tonic-gate * sppp_dlpromiscoffreq()
9977c478bd9Sstevel@tonic-gate *
9987c478bd9Sstevel@tonic-gate * MT-Perimeters:
9997c478bd9Sstevel@tonic-gate * shared inner, shared outer.
10007c478bd9Sstevel@tonic-gate *
10017c478bd9Sstevel@tonic-gate * Description:
10027c478bd9Sstevel@tonic-gate * Perform DL_PROMISCOFF_REQ request, called by sppp_mproto.
10037c478bd9Sstevel@tonic-gate */
10047c478bd9Sstevel@tonic-gate static int
sppp_dlpromiscoffreq(queue_t * q,mblk_t * mp,spppstr_t * sps)10057c478bd9Sstevel@tonic-gate sppp_dlpromiscoffreq(queue_t *q, mblk_t *mp, spppstr_t *sps)
10067c478bd9Sstevel@tonic-gate {
10077c478bd9Sstevel@tonic-gate t_uscalar_t level;
10087c478bd9Sstevel@tonic-gate
10097c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
10107c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
10117c478bd9Sstevel@tonic-gate level = ((dl_promiscoff_req_t *)mp->b_rptr)->dl_level;
10127c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
10137c478bd9Sstevel@tonic-gate
10147c478bd9Sstevel@tonic-gate if (!IS_SPS_PROMISC(sps)) {
10157c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI promiscoff: not promiscuous\n"));
10167c478bd9Sstevel@tonic-gate dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
10177c478bd9Sstevel@tonic-gate } else if ((level != DL_PROMISC_PHYS) && (level != DL_PROMISC_SAP) &&
10187c478bd9Sstevel@tonic-gate (level != DL_PROMISC_MULTI)) {
10197c478bd9Sstevel@tonic-gate dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
10207c478bd9Sstevel@tonic-gate DBGERROR((CE_CONT, "DLPI promiscoff: bad level %d\n", level));
10217c478bd9Sstevel@tonic-gate } else {
10227c478bd9Sstevel@tonic-gate qwriter(q, mp, sppp_dl_promiscoff, PERIM_INNER);
10237c478bd9Sstevel@tonic-gate }
10247c478bd9Sstevel@tonic-gate return (0);
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate /*
10297c478bd9Sstevel@tonic-gate * sppp_dl_promiscoff()
10307c478bd9Sstevel@tonic-gate *
10317c478bd9Sstevel@tonic-gate * MT-Perimeters:
10327c478bd9Sstevel@tonic-gate * exclusive inner, shared outer.
10337c478bd9Sstevel@tonic-gate *
10347c478bd9Sstevel@tonic-gate * Description:
10357c478bd9Sstevel@tonic-gate * Called by qwriter (INNER) from sppp_dlpromiscoffreq as the result of
10367c478bd9Sstevel@tonic-gate * receiving a DL_PROMISCOFF_REQ message.
10377c478bd9Sstevel@tonic-gate */
10387c478bd9Sstevel@tonic-gate static void
sppp_dl_promiscoff(queue_t * q,mblk_t * mp)10397c478bd9Sstevel@tonic-gate sppp_dl_promiscoff(queue_t *q, mblk_t *mp)
10407c478bd9Sstevel@tonic-gate {
10417c478bd9Sstevel@tonic-gate spppstr_t *sps;
10427c478bd9Sstevel@tonic-gate sppa_t *ppa;
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q->q_ptr != NULL);
10457c478bd9Sstevel@tonic-gate sps = (spppstr_t *)q->q_ptr;
10467c478bd9Sstevel@tonic-gate ASSERT(IS_SPS_PROMISC(sps));
10477c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
10487c478bd9Sstevel@tonic-gate ppa = sps->sps_ppa;
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate sps->sps_flags &= ~SPS_PROMISC;
10517c478bd9Sstevel@tonic-gate /*
10527c478bd9Sstevel@tonic-gate * We can't be guaranteed that the sps_ppa field is still valid, since
10537c478bd9Sstevel@tonic-gate * the control stream might have been closed earlier, in which case
10547c478bd9Sstevel@tonic-gate * the close procedure would have NULL'd out the sps_ppa.
10557c478bd9Sstevel@tonic-gate */
10567c478bd9Sstevel@tonic-gate if (ppa != NULL) {
10577c478bd9Sstevel@tonic-gate rw_enter(&ppa->ppa_sib_lock, RW_WRITER);
10587c478bd9Sstevel@tonic-gate ASSERT(ppa->ppa_promicnt > 0);
10597c478bd9Sstevel@tonic-gate ppa->ppa_promicnt--;
10607c478bd9Sstevel@tonic-gate rw_exit(&ppa->ppa_sib_lock);
10617c478bd9Sstevel@tonic-gate }
10627c478bd9Sstevel@tonic-gate DBGDLPI((CE_CONT, "/%d: promiscuous mode off\n", sps->sps_mn_id));
10637c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_PROMISCOFF_REQ);
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate /*
10677c478bd9Sstevel@tonic-gate * sppp_dlphyreq()
10687c478bd9Sstevel@tonic-gate *
10697c478bd9Sstevel@tonic-gate * MT-Perimeters:
10707c478bd9Sstevel@tonic-gate * shared inner, shared outer.
10717c478bd9Sstevel@tonic-gate *
10727c478bd9Sstevel@tonic-gate * Description:
10737c478bd9Sstevel@tonic-gate * Perform DL_PHYS_ADDR_REQ request, called by sppp_mproto. This doesn't
10747c478bd9Sstevel@tonic-gate * return anything useful, but it keeps ifconfig happy.
10757c478bd9Sstevel@tonic-gate */
10767c478bd9Sstevel@tonic-gate /* ARGSUSED */
10777c478bd9Sstevel@tonic-gate static int
sppp_dlphyreq(queue_t * q,mblk_t * mp,spppstr_t * us)10787c478bd9Sstevel@tonic-gate sppp_dlphyreq(queue_t *q, mblk_t *mp, spppstr_t *us)
10797c478bd9Sstevel@tonic-gate {
10807c478bd9Sstevel@tonic-gate static struct ether_addr addr = { 0 };
10817c478bd9Sstevel@tonic-gate
10827c478bd9Sstevel@tonic-gate dlphysaddrack(q, mp, (char *)&addr, ETHERADDRL);
10837c478bd9Sstevel@tonic-gate return (0);
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate
10867c478bd9Sstevel@tonic-gate /*
10877c478bd9Sstevel@tonic-gate * sppp_dladdether()
10887c478bd9Sstevel@tonic-gate *
10897c478bd9Sstevel@tonic-gate * Description:
10907c478bd9Sstevel@tonic-gate * Prepend an empty Ethernet header to msg for snoop, et al. Free
10917c478bd9Sstevel@tonic-gate * the original mblk if alloc fails. Only called for the purpose of sending
10927c478bd9Sstevel@tonic-gate * packets up the promiscous stream.
10937c478bd9Sstevel@tonic-gate */
10947c478bd9Sstevel@tonic-gate /* ARGSUSED */
10957c478bd9Sstevel@tonic-gate static mblk_t *
sppp_dladdether(spppstr_t * sps,mblk_t * mp,t_scalar_t proto)10967c478bd9Sstevel@tonic-gate sppp_dladdether(spppstr_t *sps, mblk_t *mp, t_scalar_t proto)
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate mblk_t *eh;
10997c478bd9Sstevel@tonic-gate t_scalar_t type;
11007c478bd9Sstevel@tonic-gate
11017c478bd9Sstevel@tonic-gate if ((eh = allocb(sizeof (struct ether_header), BPRI_MED)) == NULL) {
11027c478bd9Sstevel@tonic-gate freemsg(mp);
11037c478bd9Sstevel@tonic-gate return (NULL);
11047c478bd9Sstevel@tonic-gate }
11057c478bd9Sstevel@tonic-gate if (proto == PPP_IP) {
11067c478bd9Sstevel@tonic-gate type = ETHERTYPE_IP;
11077c478bd9Sstevel@tonic-gate } else if (proto == PPP_IPV6) {
11087c478bd9Sstevel@tonic-gate type = ETHERTYPE_IPV6;
11097c478bd9Sstevel@tonic-gate } else {
11107c478bd9Sstevel@tonic-gate /*
11117c478bd9Sstevel@tonic-gate * For all other protocols, end this up as an ETHERTYPE_PPP
11127c478bd9Sstevel@tonic-gate * type of packet. Since we've skipped the PPP headers in the
11137c478bd9Sstevel@tonic-gate * caller, make sure that we restore it. We know for sure that
11147c478bd9Sstevel@tonic-gate * the PPP header still exists in the message (only skipped),
11157c478bd9Sstevel@tonic-gate * since the sender of this message is pppd and it must have
11167c478bd9Sstevel@tonic-gate * included the PPP header in front.
11177c478bd9Sstevel@tonic-gate */
11187c478bd9Sstevel@tonic-gate type = ETHERTYPE_PPP;
11197c478bd9Sstevel@tonic-gate mp->b_rptr -= PPP_HDRLEN;
11207c478bd9Sstevel@tonic-gate ASSERT(mp->b_rptr >= mp->b_datap->db_base);
11217c478bd9Sstevel@tonic-gate }
11227c478bd9Sstevel@tonic-gate eh->b_wptr += sizeof (struct ether_header);
11237c478bd9Sstevel@tonic-gate bzero((caddr_t)eh->b_rptr, sizeof (struct ether_header));
11247c478bd9Sstevel@tonic-gate ((struct ether_header *)eh->b_rptr)->ether_type = htons((int16_t)type);
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate linkb(eh, mp);
11277c478bd9Sstevel@tonic-gate return (eh);
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate /*
11317c478bd9Sstevel@tonic-gate * sppp_dladdud()
11327c478bd9Sstevel@tonic-gate *
11337c478bd9Sstevel@tonic-gate * Description:
11347c478bd9Sstevel@tonic-gate * Prepend DL_UNITDATA_IND mblk to msg, free original alloc fails.
11357c478bd9Sstevel@tonic-gate */
11367c478bd9Sstevel@tonic-gate /* ARGSUSED */
11377c478bd9Sstevel@tonic-gate mblk_t *
sppp_dladdud(spppstr_t * sps,mblk_t * mp,t_scalar_t proto,boolean_t promisc)11387c478bd9Sstevel@tonic-gate sppp_dladdud(spppstr_t *sps, mblk_t *mp, t_scalar_t proto, boolean_t promisc)
11397c478bd9Sstevel@tonic-gate {
11407c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *dlu;
11417c478bd9Sstevel@tonic-gate mblk_t *dh;
11427c478bd9Sstevel@tonic-gate size_t size;
11437c478bd9Sstevel@tonic-gate t_scalar_t type;
11447c478bd9Sstevel@tonic-gate
11457c478bd9Sstevel@tonic-gate size = sizeof (dl_unitdata_ind_t) + (2 * SPPP_ADDRL);
11467c478bd9Sstevel@tonic-gate if ((dh = allocb(size, BPRI_MED)) == NULL) {
11477c478bd9Sstevel@tonic-gate freemsg(mp);
11487c478bd9Sstevel@tonic-gate return (NULL);
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate dh->b_datap->db_type = M_PROTO;
11527c478bd9Sstevel@tonic-gate dh->b_wptr = dh->b_datap->db_lim;
11537c478bd9Sstevel@tonic-gate dh->b_rptr = dh->b_wptr - size;
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate dlu = (dl_unitdata_ind_t *)dh->b_rptr;
11567c478bd9Sstevel@tonic-gate dlu->dl_primitive = DL_UNITDATA_IND;
11577c478bd9Sstevel@tonic-gate dlu->dl_dest_addr_length = SPPP_ADDRL;
11587c478bd9Sstevel@tonic-gate dlu->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
11597c478bd9Sstevel@tonic-gate dlu->dl_src_addr_length = SPPP_ADDRL;
11607c478bd9Sstevel@tonic-gate dlu->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + SPPP_ADDRL;
11617c478bd9Sstevel@tonic-gate dlu->dl_group_address = 0;
11627c478bd9Sstevel@tonic-gate
11637c478bd9Sstevel@tonic-gate if (promisc) {
11647c478bd9Sstevel@tonic-gate if (proto == PPP_IP) {
11657c478bd9Sstevel@tonic-gate type = ETHERTYPE_IP;
11667c478bd9Sstevel@tonic-gate } else if (proto == PPP_IPV6) {
11677c478bd9Sstevel@tonic-gate type = ETHERTYPE_IPV6;
11687c478bd9Sstevel@tonic-gate } else {
11697c478bd9Sstevel@tonic-gate /*
11707c478bd9Sstevel@tonic-gate * For all other protocols, send this up as an
11717c478bd9Sstevel@tonic-gate * ETHERTYPE_PPP type of packet. Since we've skipped
11727c478bd9Sstevel@tonic-gate * the PPP headers in the caller, make sure that we
11737c478bd9Sstevel@tonic-gate * restore it. We know for sure that the PPP header
11747c478bd9Sstevel@tonic-gate * still exists in the message (only skipped), since
11757c478bd9Sstevel@tonic-gate * the sender of this message is pppd and it must
11767c478bd9Sstevel@tonic-gate * have included the PPP header in front.
11777c478bd9Sstevel@tonic-gate */
11787c478bd9Sstevel@tonic-gate type = ETHERTYPE_PPP;
11797c478bd9Sstevel@tonic-gate mp->b_rptr -= PPP_HDRLEN;
11807c478bd9Sstevel@tonic-gate ASSERT(mp->b_rptr >= mp->b_datap->db_base);
11817c478bd9Sstevel@tonic-gate }
11827c478bd9Sstevel@tonic-gate } else {
11837c478bd9Sstevel@tonic-gate type = sps->sps_req_sap;
11847c478bd9Sstevel@tonic-gate }
11857c478bd9Sstevel@tonic-gate /*
11867c478bd9Sstevel@tonic-gate * Send the DLPI client the data with the SAP they requested,
11877c478bd9Sstevel@tonic-gate * (e.g. ETHERTYPE_IP) rather than the PPP protocol (e.g. PPP_IP).
11887c478bd9Sstevel@tonic-gate */
11897c478bd9Sstevel@tonic-gate ((spppreqsap_t *)(dlu + 1))[0] = type;
11907c478bd9Sstevel@tonic-gate ((spppreqsap_t *)(dlu + 1))[1] = type;
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate linkb(dh, mp);
11937c478bd9Sstevel@tonic-gate return (dh);
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate
11967c478bd9Sstevel@tonic-gate /*
11977c478bd9Sstevel@tonic-gate * sppp_dlprsendup()
11987c478bd9Sstevel@tonic-gate *
11997c478bd9Sstevel@tonic-gate * Description:
12007c478bd9Sstevel@tonic-gate * For any valid promiscuous streams (marked with SPS_PROMISC and its
12017c478bd9Sstevel@tonic-gate * sps_dlstate is DL_IDLE), send data upstream. The caller is expected
12027c478bd9Sstevel@tonic-gate * to hold ppa_sib_lock when calling this procedure.
12037c478bd9Sstevel@tonic-gate */
12047c478bd9Sstevel@tonic-gate void
sppp_dlprsendup(spppstr_t * sps,mblk_t * mp,t_scalar_t proto,boolean_t header)12057c478bd9Sstevel@tonic-gate sppp_dlprsendup(spppstr_t *sps, mblk_t *mp, t_scalar_t proto, boolean_t header)
12067c478bd9Sstevel@tonic-gate {
12077c478bd9Sstevel@tonic-gate sppa_t *ppa;
12087c478bd9Sstevel@tonic-gate mblk_t *dmp;
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate ASSERT(sps != NULL);
12117c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && mp->b_rptr != NULL);
12127c478bd9Sstevel@tonic-gate ppa = sps->sps_ppa;
12137c478bd9Sstevel@tonic-gate ASSERT(ppa != NULL);
12147c478bd9Sstevel@tonic-gate
12157c478bd9Sstevel@tonic-gate /* NOTE: caller must hold ppa_sib_lock in RW_READER mode */
12167c478bd9Sstevel@tonic-gate ASSERT(RW_READ_HELD(&ppa->ppa_sib_lock));
12177c478bd9Sstevel@tonic-gate
12187c478bd9Sstevel@tonic-gate for (; sps != NULL; sps = sps->sps_nextsib) {
12197c478bd9Sstevel@tonic-gate /*
12207c478bd9Sstevel@tonic-gate * We specifically test to ensure that the DLPI state for the
12217c478bd9Sstevel@tonic-gate * promiscous stream is IDLE (DL_IDLE), since such state tells
12227c478bd9Sstevel@tonic-gate * us that the promiscous stream has been bound to PPP_ALLSAP.
12237c478bd9Sstevel@tonic-gate */
12247c478bd9Sstevel@tonic-gate if (IS_SPS_PROMISC(sps) && (sps->sps_dlstate == DL_IDLE) &&
12257c478bd9Sstevel@tonic-gate canputnext(sps->sps_rq)) {
12267c478bd9Sstevel@tonic-gate if ((dmp = dupmsg(mp)) == NULL) {
12277c478bd9Sstevel@tonic-gate mutex_enter(&ppa->ppa_sta_lock);
12287c478bd9Sstevel@tonic-gate ppa->ppa_allocbfail++;
12297c478bd9Sstevel@tonic-gate mutex_exit(&ppa->ppa_sta_lock);
12307c478bd9Sstevel@tonic-gate continue;
12317c478bd9Sstevel@tonic-gate }
12327c478bd9Sstevel@tonic-gate if (header) {
12337c478bd9Sstevel@tonic-gate dmp->b_rptr += PPP_HDRLEN;
12347c478bd9Sstevel@tonic-gate }
12357c478bd9Sstevel@tonic-gate if (IS_SPS_RAWDATA(sps)) {
12367c478bd9Sstevel@tonic-gate /* function frees original message if fails */
12377c478bd9Sstevel@tonic-gate dmp = sppp_dladdether(sps, dmp, proto);
12387c478bd9Sstevel@tonic-gate } else {
12397c478bd9Sstevel@tonic-gate /* function frees original message if fails */
12407c478bd9Sstevel@tonic-gate dmp = sppp_dladdud(sps, dmp, proto, B_TRUE);
12417c478bd9Sstevel@tonic-gate }
12427c478bd9Sstevel@tonic-gate if (dmp != NULL) {
12437c478bd9Sstevel@tonic-gate putnext(sps->sps_rq, dmp);
12447c478bd9Sstevel@tonic-gate } else {
12457c478bd9Sstevel@tonic-gate mutex_enter(&ppa->ppa_sta_lock);
12467c478bd9Sstevel@tonic-gate ppa->ppa_allocbfail++;
12477c478bd9Sstevel@tonic-gate mutex_exit(&ppa->ppa_sta_lock);
12487c478bd9Sstevel@tonic-gate }
12497c478bd9Sstevel@tonic-gate }
12507c478bd9Sstevel@tonic-gate }
12517c478bd9Sstevel@tonic-gate }
1252