17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*07d06da5SSurya Prakki * Common Development and Distribution License (the "License").
6*07d06da5SSurya Prakki * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*07d06da5SSurya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * IDN DLPI support (based on QE implementation).
287c478bd9Sstevel@tonic-gate */
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/debug.h>
317c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
327c478bd9Sstevel@tonic-gate #include <sys/stream.h>
337c478bd9Sstevel@tonic-gate #include <sys/systm.h>
347c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
357c478bd9Sstevel@tonic-gate #include <sys/errno.h>
367c478bd9Sstevel@tonic-gate #ifdef xxx_trace
377c478bd9Sstevel@tonic-gate #include <sys/vtrace.h>
387c478bd9Sstevel@tonic-gate #endif /* xxx_trace */
397c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
407c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
417c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
427c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
437c478bd9Sstevel@tonic-gate #include <sys/stat.h>
447c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
457c478bd9Sstevel@tonic-gate #include <sys/dlpi.h>
467c478bd9Sstevel@tonic-gate #include <sys/time.h>
477c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate #include <sys/idn.h>
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate #ifdef IPV6
527c478bd9Sstevel@tonic-gate #define IS_ETHERTYPE_IPV4(x) ((x) == ETHERTYPE_IP)
537c478bd9Sstevel@tonic-gate #define IS_ETHERTYPE_IPV6(x) ((x) == ETHERTYPE_IPV6)
547c478bd9Sstevel@tonic-gate #define IS_ETHERTYPE_IP(x) (IS_ETHERTYPE_IPV4(x) || IS_ETHERTYPE_IPV6(x))
557c478bd9Sstevel@tonic-gate #else
567c478bd9Sstevel@tonic-gate #define IS_ETHERTYPE_IPV4(x) ((x) == ETHERTYPE_IP)
577c478bd9Sstevel@tonic-gate #define IS_ETHERTYPE_IPV6(x) (0)
587c478bd9Sstevel@tonic-gate #define IS_ETHERTYPE_IP IS_ETHERTYPE_IPV4
597c478bd9Sstevel@tonic-gate #endif /* IPV6 */
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate #ifdef IDN_TRACE
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate * This stuff should go into <sys/vtrace.h>
647c478bd9Sstevel@tonic-gate */
657c478bd9Sstevel@tonic-gate #define TR_FAC_IDN 100
667c478bd9Sstevel@tonic-gate /*
677c478bd9Sstevel@tonic-gate * TR_FAC_IDN tags
687c478bd9Sstevel@tonic-gate */
697c478bd9Sstevel@tonic-gate #define TR_IDN_OPEN 0
707c478bd9Sstevel@tonic-gate #define TR_IDN_CLOSE 1
717c478bd9Sstevel@tonic-gate #define TR_IDN_WPUT_START 2
727c478bd9Sstevel@tonic-gate #define TR_IDN_WPUT_END 3
737c478bd9Sstevel@tonic-gate #define TR_IDN_WSRV_START 4
747c478bd9Sstevel@tonic-gate #define TR_IDN_WSRV_END 5
757c478bd9Sstevel@tonic-gate #define TR_IDN_START_START 6
767c478bd9Sstevel@tonic-gate #define TR_IDN_START_END 7
777c478bd9Sstevel@tonic-gate #define TR_IDN_INTR_START 8
787c478bd9Sstevel@tonic-gate #define TR_IDN_INTR_END 9
797c478bd9Sstevel@tonic-gate #define TR_IDN_READ_START 10
807c478bd9Sstevel@tonic-gate #define TR_IDN_READ_END 11
817c478bd9Sstevel@tonic-gate #define TR_IDN_SENDUP_START 12
827c478bd9Sstevel@tonic-gate #define TR_IDN_SENDUP_END 13
837c478bd9Sstevel@tonic-gate #define TR_IDN_ADDUDIND_START 14
847c478bd9Sstevel@tonic-gate #define TR_IDN_ADDUDIND_END 15
857c478bd9Sstevel@tonic-gate #define TR_IDN_GETBUF_START 16
867c478bd9Sstevel@tonic-gate #define TR_IDN_GETBUF_END 17
877c478bd9Sstevel@tonic-gate #define TR_IDN_FREEBUF_START 18
887c478bd9Sstevel@tonic-gate #define TR_IDN_FREEBUF_END 19
897c478bd9Sstevel@tonic-gate #define TR_IDN_PROTO_START 20
907c478bd9Sstevel@tonic-gate #define TR_IDN_PROTO_END 21
917c478bd9Sstevel@tonic-gate #define TR_IDN_INIT_START 22
927c478bd9Sstevel@tonic-gate #define TR_IDN_INIT_END 23
937c478bd9Sstevel@tonic-gate #define TR_IDN_PROTO_IN 24
947c478bd9Sstevel@tonic-gate #define TR_IDN_PROTO_OUT 25
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate #define IDNTRACE(fac, tag) (printf("idn.TRACE: "))
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate #define TRACE_0(fac, tag, name) \
997c478bd9Sstevel@tonic-gate IDNTRACE((fac), (tag)); \
1007c478bd9Sstevel@tonic-gate printf(name); printf("\n");
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate #define TRACE_1(fac, tag, name, d1) \
1037c478bd9Sstevel@tonic-gate IDNTRACE((fac), (tag)); \
1047c478bd9Sstevel@tonic-gate printf(name, (d1)); printf("\n");
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate #define TRACE_2(fac, tag, name, d1, d2) \
1077c478bd9Sstevel@tonic-gate IDNTRACE((fac), (tag)); \
1087c478bd9Sstevel@tonic-gate printf(name, (d1), (d2)); printf("\n");
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate #define TRACE_3(fac, tag, name, d1, d2, d3) \
1117c478bd9Sstevel@tonic-gate IDNTRACE((fac), (tag)); \
1127c478bd9Sstevel@tonic-gate printf(name, (d1), (d2), (d3)); printf("\n");
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate #define TRACE_4(fac, tag, name, d1, d2, d3, d4) \
1157c478bd9Sstevel@tonic-gate IDNTRACE((fac), (tag)); \
1167c478bd9Sstevel@tonic-gate printf(name, (d1), (d2), (d3), (d4)); printf("\n");
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate #define TRACE_5(fac, tag, name, d1, d2, d3, d4, d5) \
1197c478bd9Sstevel@tonic-gate IDNTRACE((fac), (tag)); \
1207c478bd9Sstevel@tonic-gate printf(name, (d1), (d2), (d3), (d4), (d5)); printf("\n");
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate #else /* IDN_TRACE */
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate #define TRACE_0(fac, tag, name) {}
1257c478bd9Sstevel@tonic-gate #define TRACE_1(fac, tag, name, d1) {}
1267c478bd9Sstevel@tonic-gate #define TRACE_2(fac, tag, name, d1, d2) {}
1277c478bd9Sstevel@tonic-gate #define TRACE_3(fac, tag, name, d1, d2, d3) {}
1287c478bd9Sstevel@tonic-gate #define TRACE_4(fac, tag, name, d1, d2, d3, d4) {}
1297c478bd9Sstevel@tonic-gate #define TRACE_5(fac, tag, name, d1, d2, d3, d4, d5) {}
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate #endif /* IDN_TRACE */
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate #ifdef DEBUG
1347c478bd9Sstevel@tonic-gate #define DLERRORACK(qq, mm, cc, ee, xx) \
1357c478bd9Sstevel@tonic-gate { \
1367c478bd9Sstevel@tonic-gate PR_DLPI("dlpi: ERRORACK: 0x%x(%s), err = 0x%x(%s)\n", \
1377c478bd9Sstevel@tonic-gate (uint_t)(cc), dlprim2str(cc), \
1387c478bd9Sstevel@tonic-gate (uint_t)(ee), dlerr2str((int)(ee))); \
1397c478bd9Sstevel@tonic-gate dlerrorack((qq), (mm), (cc), (ee), (xx)); \
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate #define DLOKACK(qq, mm, cc) \
1427c478bd9Sstevel@tonic-gate { \
1437c478bd9Sstevel@tonic-gate PR_DLPI("dlpi: OKACK: 0x%x(%s)\n", (cc), dlprim2str(cc)); \
1447c478bd9Sstevel@tonic-gate dlokack((qq), (mm), (cc)); \
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate #define DLBINDACK(qq, mm, ss, aa, ll, xx, yy) \
1477c478bd9Sstevel@tonic-gate { \
1487c478bd9Sstevel@tonic-gate PR_DLPI("dlpi: BINDACK: eth=%x:%x:%x:%x:%x:%x, sap=0x%x, l=%d\n", \
1497c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[0], \
1507c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[1], \
1517c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[2], \
1527c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[3], \
1537c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[4], \
1547c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[5], \
1557c478bd9Sstevel@tonic-gate (uint_t)(ss), (int)(ll)); \
1567c478bd9Sstevel@tonic-gate dlbindack((qq), (mm), (ss), (aa), (ll), (xx), (yy)); \
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate #define DLPHYSADDRACK(qq, mm, aa, ll) \
1597c478bd9Sstevel@tonic-gate { \
1607c478bd9Sstevel@tonic-gate PR_DLPI("dlpi: PHYSACK: eth=%x:%x:%x:%x:%x:%x, l=%d\n", \
1617c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[0], \
1627c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[1], \
1637c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[2], \
1647c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[3], \
1657c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[4], \
1667c478bd9Sstevel@tonic-gate ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[5], \
1677c478bd9Sstevel@tonic-gate (ll)); \
1687c478bd9Sstevel@tonic-gate dlphysaddrack((qq), (mm), (aa), (ll)); \
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate static char *dlerrstr[] = {
1727c478bd9Sstevel@tonic-gate "DL_BADSAP",
1737c478bd9Sstevel@tonic-gate "DL_BADADDR",
1747c478bd9Sstevel@tonic-gate "DL_ACCESS",
1757c478bd9Sstevel@tonic-gate "DL_OUTSTATE",
1767c478bd9Sstevel@tonic-gate "DL_SYSERR",
1777c478bd9Sstevel@tonic-gate "DL_BADCORR",
1787c478bd9Sstevel@tonic-gate "DL_BADDATA",
1797c478bd9Sstevel@tonic-gate "DL_UNSUPPORTED",
1807c478bd9Sstevel@tonic-gate "DL_BADPPA",
1817c478bd9Sstevel@tonic-gate "DL_BADPRIM",
1827c478bd9Sstevel@tonic-gate "DL_BADQOSPARAM",
1837c478bd9Sstevel@tonic-gate "DL_BADQOSTYPE",
1847c478bd9Sstevel@tonic-gate "DL_BADTOKEN",
1857c478bd9Sstevel@tonic-gate "DL_BOUND",
1867c478bd9Sstevel@tonic-gate "DL_INITFAILED",
1877c478bd9Sstevel@tonic-gate "DL_NOADDR",
1887c478bd9Sstevel@tonic-gate "DL_NOTINIT",
1897c478bd9Sstevel@tonic-gate "DL_UNDELIVERABLE",
1907c478bd9Sstevel@tonic-gate "DL_NOTSUPPORTED",
1917c478bd9Sstevel@tonic-gate "DL_TOOMANY",
1927c478bd9Sstevel@tonic-gate "DL_NOTENAB",
1937c478bd9Sstevel@tonic-gate "DL_BUSY",
1947c478bd9Sstevel@tonic-gate "DL_NOAUTO",
1957c478bd9Sstevel@tonic-gate "DL_NOXIDAUTO",
1967c478bd9Sstevel@tonic-gate "DL_NOTESTAUTO",
1977c478bd9Sstevel@tonic-gate "DL_XIDAUTO",
1987c478bd9Sstevel@tonic-gate "DL_TESTAUTO",
1997c478bd9Sstevel@tonic-gate "DL_PENDING"
2007c478bd9Sstevel@tonic-gate };
2017c478bd9Sstevel@tonic-gate static int dlerrnum = (sizeof (dlerrstr) / sizeof (char *));
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate static char *
dlerr2str(int err)2047c478bd9Sstevel@tonic-gate dlerr2str(int err)
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate if ((err < 0) || (err >= dlerrnum))
2077c478bd9Sstevel@tonic-gate return ("unknown");
2087c478bd9Sstevel@tonic-gate else
2097c478bd9Sstevel@tonic-gate return (dlerrstr[err]);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate static char *
dlprim2str(int prim)2137c478bd9Sstevel@tonic-gate dlprim2str(int prim)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate char *pstr;
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate switch (prim) {
2187c478bd9Sstevel@tonic-gate case DL_UNITDATA_REQ: pstr = "UNITDATA_REQ"; break;
2197c478bd9Sstevel@tonic-gate case DL_ATTACH_REQ: pstr = "ATTACH_REQ"; break;
2207c478bd9Sstevel@tonic-gate case DL_DETACH_REQ: pstr = "DETACH_REQ"; break;
2217c478bd9Sstevel@tonic-gate case DL_BIND_REQ: pstr = "BIND_REQ"; break;
2227c478bd9Sstevel@tonic-gate case DL_UNBIND_REQ: pstr = "UNBIND_REQ"; break;
2237c478bd9Sstevel@tonic-gate case DL_INFO_REQ: pstr = "INFO_REQ"; break;
2247c478bd9Sstevel@tonic-gate case DL_PROMISCON_REQ: pstr = "PROMISCON_REQ"; break;
2257c478bd9Sstevel@tonic-gate case DL_PROMISCOFF_REQ: pstr = "PROMISCOFF_REQ"; break;
2267c478bd9Sstevel@tonic-gate case DL_ENABMULTI_REQ: pstr = "ENABMULTI_REQ"; break;
2277c478bd9Sstevel@tonic-gate case DL_DISABMULTI_REQ: pstr = "DISABMULTI_REQ"; break;
2287c478bd9Sstevel@tonic-gate case DL_PHYS_ADDR_REQ: pstr = "PHYS_ADDR_REQ"; break;
2297c478bd9Sstevel@tonic-gate case DL_SET_PHYS_ADDR_REQ:
2307c478bd9Sstevel@tonic-gate pstr = "SET_PHYS_ADDR_REQ"; break;
2317c478bd9Sstevel@tonic-gate default: pstr = "unsupported"; break;
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate return (pstr);
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate #else /* DEBUG */
2367c478bd9Sstevel@tonic-gate #define DLERRORACK(qq, mm, cc, ee, xx) \
2377c478bd9Sstevel@tonic-gate (dlerrorack((qq), (mm), (cc), (ee), (xx)))
2387c478bd9Sstevel@tonic-gate #define DLOKACK(qq, mm, cc) \
2397c478bd9Sstevel@tonic-gate (dlokack((qq), (mm), (cc)))
2407c478bd9Sstevel@tonic-gate #define DLBINDACK(qq, mm, ss, aa, ll, xx, yy) \
2417c478bd9Sstevel@tonic-gate (dlbindack((qq), (mm), (ss), (aa), (ll), (xx), (yy)))
2427c478bd9Sstevel@tonic-gate #define DLPHYSADDRACK(qq, mm, aa, ll) \
2437c478bd9Sstevel@tonic-gate (dlphysaddrack((qq), (mm), (aa), (ll)))
2447c478bd9Sstevel@tonic-gate #endif /* DEBUG */
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate #define IDNDL_ADDR_IS_MULTICAST(ap) (((ap)->ether_addr_octet[0] & 01) == 1)
2477c478bd9Sstevel@tonic-gate /*
2487c478bd9Sstevel@tonic-gate * MIB II broadcast/multicast packets
2497c478bd9Sstevel@tonic-gate */
2507c478bd9Sstevel@tonic-gate #define IS_BROADCAST(ehp) \
2517c478bd9Sstevel@tonic-gate (ether_cmp(&(ehp)->ether_dhost, ðerbroadcastaddr) == 0)
2527c478bd9Sstevel@tonic-gate #define IS_MULTICAST(ehp) \
2537c478bd9Sstevel@tonic-gate IDNDL_ADDR_IS_MULTICAST(&(ehp)->ether_dhost)
2547c478bd9Sstevel@tonic-gate #define BUMP_InNUcast(sip, ehp) \
2557c478bd9Sstevel@tonic-gate if (IS_BROADCAST(ehp)) { \
2567c478bd9Sstevel@tonic-gate (sip)->si_kstat.si_brdcstrcv++; \
2577c478bd9Sstevel@tonic-gate } else if (IS_MULTICAST(ehp)) { \
2587c478bd9Sstevel@tonic-gate (sip)->si_kstat.si_multircv++; \
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate #define BUMP_OutNUcast(sip, ehp) \
2617c478bd9Sstevel@tonic-gate if (IS_BROADCAST(ehp)) { \
2627c478bd9Sstevel@tonic-gate (sip)->si_kstat.si_brdcstxmt++; \
2637c478bd9Sstevel@tonic-gate } else if (IS_MULTICAST(ehp)) { \
2647c478bd9Sstevel@tonic-gate (sip)->si_kstat.si_multixmt++; \
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate * Function prototypes.
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate static int idndl_ioc_hdr_info(queue_t *, mblk_t *, int *);
2717c478bd9Sstevel@tonic-gate static void idndl_areq(queue_t *, mblk_t *);
2727c478bd9Sstevel@tonic-gate static void idndl_dreq(queue_t *, mblk_t *);
2737c478bd9Sstevel@tonic-gate static void idndl_breq(queue_t *, mblk_t *);
2747c478bd9Sstevel@tonic-gate static void idndl_ubreq(queue_t *, mblk_t *);
2757c478bd9Sstevel@tonic-gate static void idndl_ireq(queue_t *, mblk_t *);
2767c478bd9Sstevel@tonic-gate static void idndl_ponreq(queue_t *, mblk_t *);
2777c478bd9Sstevel@tonic-gate static void idndl_poffreq(queue_t *, mblk_t *);
2787c478bd9Sstevel@tonic-gate static void idndl_emreq(queue_t *, mblk_t *);
2797c478bd9Sstevel@tonic-gate static void idndl_dmreq(queue_t *, mblk_t *);
2807c478bd9Sstevel@tonic-gate static void idndl_pareq(queue_t *, mblk_t *);
2817c478bd9Sstevel@tonic-gate #ifdef notdef
2827c478bd9Sstevel@tonic-gate static void idndl_spareq(queue_t *, mblk_t *);
2837c478bd9Sstevel@tonic-gate #endif /* notdef */
2847c478bd9Sstevel@tonic-gate static void idndl_udreq(queue_t *, mblk_t *);
2857c478bd9Sstevel@tonic-gate static void serror(dev_info_t *dip, int idnerr, char *fmt, ...);
2867c478bd9Sstevel@tonic-gate static mblk_t *idndl_addudind(struct idn *, mblk_t *, struct ether_addr *,
2877c478bd9Sstevel@tonic-gate struct ether_addr *, int, ulong_t);
2887c478bd9Sstevel@tonic-gate static void idndl_setipq(struct idn *);
2897c478bd9Sstevel@tonic-gate static int idndl_mcmatch(struct idnstr *, struct ether_addr *);
2907c478bd9Sstevel@tonic-gate static int idndl_stat_kstat_update(kstat_t *ksp, int rw);
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate static int _idndl_ether2domain(struct ether_addr *eap);
2937c478bd9Sstevel@tonic-gate static struct idn *_idndl_ether2sip(struct ether_addr *eap);
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate #define IDNSAPMATCH(sap, type, flags) ((sap == type)? 1 : \
2977c478bd9Sstevel@tonic-gate ((flags & IDNSALLSAP)? 1 : \
2987c478bd9Sstevel@tonic-gate ((sap <= ETHERMTU) && sap && (type <= ETHERMTU))? 1 : 0))
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate /*
3017c478bd9Sstevel@tonic-gate * Our DL_INFO_ACK template.
3027c478bd9Sstevel@tonic-gate */
3037c478bd9Sstevel@tonic-gate static dl_info_ack_t idninfoack = {
3047c478bd9Sstevel@tonic-gate DL_INFO_ACK, /* dl_primitive */
3057c478bd9Sstevel@tonic-gate 0, /* dl_max_sdu (see idndl_dlpi_init()) */
3067c478bd9Sstevel@tonic-gate 0, /* dl_min_sdu */
3077c478bd9Sstevel@tonic-gate IDNADDRL, /* dl_addr_length */
3087c478bd9Sstevel@tonic-gate DL_ETHER, /* DL_OTHER, */ /* dl_mac_type */
3097c478bd9Sstevel@tonic-gate 0, /* dl_reserved */
3107c478bd9Sstevel@tonic-gate 0, /* dl_current_state */
3117c478bd9Sstevel@tonic-gate -2, /* dl_sap_length */
3127c478bd9Sstevel@tonic-gate DL_CLDLS, /* DL_CODLS? */ /* dl_service_mode */
3137c478bd9Sstevel@tonic-gate 0, /* dl_qos_length */
3147c478bd9Sstevel@tonic-gate 0, /* dl_qos_offset */
3157c478bd9Sstevel@tonic-gate 0, /* dl_range_length */
3167c478bd9Sstevel@tonic-gate 0, /* dl_range_offset */
3177c478bd9Sstevel@tonic-gate DL_STYLE2, /* dl_provider_style */
3187c478bd9Sstevel@tonic-gate sizeof (dl_info_ack_t), /* dl_addr_offset */
3197c478bd9Sstevel@tonic-gate DL_VERSION_2, /* dl_version */
3207c478bd9Sstevel@tonic-gate ETHERADDRL, /* dl_brdcst_addr_length */
3217c478bd9Sstevel@tonic-gate sizeof (dl_info_ack_t) + IDNADDRL, /* dl_brdcst_addr_offset */
3227c478bd9Sstevel@tonic-gate 0 /* dl_growth */
3237c478bd9Sstevel@tonic-gate };
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate * Ethernet broadcast address definition.
3277c478bd9Sstevel@tonic-gate */
3287c478bd9Sstevel@tonic-gate static struct ether_addr etherbroadcastaddr = {
3297c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
3307c478bd9Sstevel@tonic-gate };
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate /*
3337c478bd9Sstevel@tonic-gate * --------------------------------------------------
3347c478bd9Sstevel@tonic-gate */
3357c478bd9Sstevel@tonic-gate void
idndl_localetheraddr(struct idn * sip,struct ether_addr * eap)3367c478bd9Sstevel@tonic-gate idndl_localetheraddr(struct idn *sip, struct ether_addr *eap)
3377c478bd9Sstevel@tonic-gate {
3387c478bd9Sstevel@tonic-gate int rv;
3397c478bd9Sstevel@tonic-gate int instance;
3407c478bd9Sstevel@tonic-gate procname_t proc = "idndl_localetheraddr";
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate ASSERT(sip && sip->si_dip && eap);
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate instance = ddi_get_instance(sip->si_dip);
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate PR_DLPI("%s: getting local etheraddr...\n", proc);
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate rv = idndl_domain_etheraddr(idn.localid, instance, eap);
3497c478bd9Sstevel@tonic-gate ASSERT(rv == 0);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate int
idndl_domain_etheraddr(int domid,int channel,struct ether_addr * eap)3537c478bd9Sstevel@tonic-gate idndl_domain_etheraddr(int domid, int channel, struct ether_addr *eap)
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate uchar_t netid;
3567c478bd9Sstevel@tonic-gate procname_t proc = "idndl_domain_etheraddr";
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate if (idn_domain[domid].dcpu == IDN_NIL_DCPU)
3597c478bd9Sstevel@tonic-gate return (-1);
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate netid = (uchar_t)idn_domain[domid].dnetid;
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate PR_DLPI("%s: dnetid = 0x%x, channel = 0x%x\n",
3647c478bd9Sstevel@tonic-gate proc, (uint_t)netid, channel);
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate #ifdef notdef
3677c478bd9Sstevel@tonic-gate localetheraddr(NULL, eap);
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate PR_DLPI("%s: localetheraddr = %x:%x:%x:%x:%x:%x\n",
3707c478bd9Sstevel@tonic-gate proc, eap->ether_addr_octet[0], eap->ether_addr_octet[1],
3717c478bd9Sstevel@tonic-gate eap->ether_addr_octet[2], eap->ether_addr_octet[3],
3727c478bd9Sstevel@tonic-gate eap->ether_addr_octet[4], eap->ether_addr_octet[5]):
3737c478bd9Sstevel@tonic-gate #endif /* notdef */
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate eap->ether_addr_octet[IDNETHER_ZERO] = 0;
3767c478bd9Sstevel@tonic-gate eap->ether_addr_octet[IDNETHER_COOKIE1] = IDNETHER_COOKIE1_VAL;
3777c478bd9Sstevel@tonic-gate eap->ether_addr_octet[IDNETHER_COOKIE2] = IDNETHER_COOKIE2_VAL;
3787c478bd9Sstevel@tonic-gate eap->ether_addr_octet[IDNETHER_NETID] = netid;
3797c478bd9Sstevel@tonic-gate eap->ether_addr_octet[IDNETHER_CHANNEL] = (uchar_t)channel;
3807c478bd9Sstevel@tonic-gate eap->ether_addr_octet[IDNETHER_RESERVED] = IDNETHER_RESERVED_VAL;
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate PR_DLPI("%s: domain %d: etheraddr = %x:%x:%x:%x:%x:%x\n",
3837c478bd9Sstevel@tonic-gate proc, domid,
3847c478bd9Sstevel@tonic-gate eap->ether_addr_octet[0], eap->ether_addr_octet[1],
3857c478bd9Sstevel@tonic-gate eap->ether_addr_octet[2], eap->ether_addr_octet[3],
3867c478bd9Sstevel@tonic-gate eap->ether_addr_octet[4], eap->ether_addr_octet[5]);
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate return (0);
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate #ifdef DEBUG
3927c478bd9Sstevel@tonic-gate /*
3937c478bd9Sstevel@tonic-gate */
3947c478bd9Sstevel@tonic-gate static int
_idndl_ether2domain(struct ether_addr * eap)3957c478bd9Sstevel@tonic-gate _idndl_ether2domain(struct ether_addr *eap)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate uchar_t *eaop;
3987c478bd9Sstevel@tonic-gate
3997c478bd9Sstevel@tonic-gate eaop = eap->ether_addr_octet;
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate ASSERT(IDNDL_ADDR_IS_MULTICAST(eap) ||
4027c478bd9Sstevel@tonic-gate ((eaop[IDNETHER_COOKIE1] == IDNETHER_COOKIE1_VAL) &&
4037c478bd9Sstevel@tonic-gate (eaop[IDNETHER_COOKIE2] == IDNETHER_COOKIE2_VAL)) ||
4047c478bd9Sstevel@tonic-gate ((eaop[IDNETHER_COOKIE1] == 0xff) &&
4057c478bd9Sstevel@tonic-gate (eaop[IDNETHER_COOKIE2] == 0xff)));
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate * Note that (IDN_NIL_DOMID) will be returned if ether address is
4087c478bd9Sstevel@tonic-gate * a broadcast 0xff.
4097c478bd9Sstevel@tonic-gate */
4107c478bd9Sstevel@tonic-gate return (IDN_NETID2DOMID(eaop[IDNETHER_NETID]));
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate */
4157c478bd9Sstevel@tonic-gate static struct idn *
_idndl_ether2sip(struct ether_addr * eap)4167c478bd9Sstevel@tonic-gate _idndl_ether2sip(struct ether_addr *eap)
4177c478bd9Sstevel@tonic-gate {
4187c478bd9Sstevel@tonic-gate int instance;
4197c478bd9Sstevel@tonic-gate struct idn *sip;
4207c478bd9Sstevel@tonic-gate uchar_t *eaop;
4217c478bd9Sstevel@tonic-gate procname_t proc = "_idndl_ether2sip";
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate eaop = eap->ether_addr_octet;
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate if (!IDNDL_ADDR_IS_MULTICAST(eap) &&
4267c478bd9Sstevel@tonic-gate (((eaop[IDNETHER_COOKIE1] != IDNETHER_COOKIE1_VAL) ||
4277c478bd9Sstevel@tonic-gate (eaop[IDNETHER_COOKIE2] != IDNETHER_COOKIE2_VAL)) &&
4287c478bd9Sstevel@tonic-gate ((eaop[IDNETHER_COOKIE1] != 0xff) ||
4297c478bd9Sstevel@tonic-gate (eaop[IDNETHER_COOKIE2] != 0xff)))) {
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
4327c478bd9Sstevel@tonic-gate "IDN: 400: corrupted MAC header "
4337c478bd9Sstevel@tonic-gate "(exp %x or 0xffff, act 0x%x)",
4347c478bd9Sstevel@tonic-gate (IDNETHER_COOKIE1_VAL << 8) |
4357c478bd9Sstevel@tonic-gate IDNETHER_COOKIE2_VAL,
4367c478bd9Sstevel@tonic-gate (eaop[IDNETHER_COOKIE1] << 8) |
4377c478bd9Sstevel@tonic-gate eaop[IDNETHER_COOKIE2]);
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate return (NULL);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate if (IDNDL_ADDR_IS_MULTICAST(eap)) {
4437c478bd9Sstevel@tonic-gate PR_DLPI("%s: MULTICAST ADDR *** ERROR ***\n", proc);
4447c478bd9Sstevel@tonic-gate sip = NULL;
4457c478bd9Sstevel@tonic-gate } else if (eaop[IDNETHER_CHANNEL] == 0xff) {
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate * Received a broadcast. Need to manually
4487c478bd9Sstevel@tonic-gate * find anybody the first running sip and use it.
4497c478bd9Sstevel@tonic-gate * XXX - kind of kludgy - single threads broadcasts.
4507c478bd9Sstevel@tonic-gate */
4517c478bd9Sstevel@tonic-gate PR_DLPI("%s: BROADCAST CHANNEL *** ERROR ***\n", proc);
4527c478bd9Sstevel@tonic-gate sip = NULL;
4537c478bd9Sstevel@tonic-gate } else {
4547c478bd9Sstevel@tonic-gate instance = (int)eaop[IDNETHER_CHANNEL];
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate sip = IDN_INST2SIP(instance);
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate return (sip);
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate #endif /* DEBUG */
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate void
idndl_dlpi_init()4647c478bd9Sstevel@tonic-gate idndl_dlpi_init()
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate procname_t proc = "idndl_dlpi_init";
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate PR_DLPI("%s: setting dl_max_sdu to %ld (0x%lx) bytes\n",
4697c478bd9Sstevel@tonic-gate proc, IDN_MTU, IDN_MTU);
4707c478bd9Sstevel@tonic-gate /*
4717c478bd9Sstevel@tonic-gate * This field is dynamic because the user may
4727c478bd9Sstevel@tonic-gate * want to dynamically set it _before_ an IDNnet
4737c478bd9Sstevel@tonic-gate * has been established via ndd(1M).
4747c478bd9Sstevel@tonic-gate */
4757c478bd9Sstevel@tonic-gate idninfoack.dl_max_sdu = IDN_MTU;
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate static int
idndl_stat_kstat_update(kstat_t * ksp,int rw)4797c478bd9Sstevel@tonic-gate idndl_stat_kstat_update(kstat_t *ksp, int rw)
4807c478bd9Sstevel@tonic-gate {
4817c478bd9Sstevel@tonic-gate struct idn *sip;
4827c478bd9Sstevel@tonic-gate struct idn_kstat_named *skp;
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate sip = (struct idn *)ksp->ks_private;
4857c478bd9Sstevel@tonic-gate skp = (struct idn_kstat_named *)ksp->ks_data;
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate if (rw == KSTAT_WRITE) {
4887c478bd9Sstevel@tonic-gate #if 0
4897c478bd9Sstevel@tonic-gate bzero(&sg_kstat.gk_kstat, sizeof (sg_kstat.gk_kstat));
4907c478bd9Sstevel@tonic-gate #endif /* 0 */
4917c478bd9Sstevel@tonic-gate bzero(&sip->si_kstat, sizeof (sip->si_kstat));
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate sip->si_kstat.si_ipackets = skp->sk_ipackets.value.ul;
4947c478bd9Sstevel@tonic-gate sip->si_kstat.si_ierrors = skp->sk_ierrors.value.ul;
4957c478bd9Sstevel@tonic-gate sip->si_kstat.si_opackets = skp->sk_opackets.value.ul;
4967c478bd9Sstevel@tonic-gate sip->si_kstat.si_oerrors = skp->sk_oerrors.value.ul;
4977c478bd9Sstevel@tonic-gate sip->si_kstat.si_txcoll = skp->sk_txcoll.value.ul;
4987c478bd9Sstevel@tonic-gate sip->si_kstat.si_rxcoll = skp->sk_rxcoll.value.ul;
4997c478bd9Sstevel@tonic-gate sip->si_kstat.si_crc = skp->sk_crc.value.ul;
5007c478bd9Sstevel@tonic-gate sip->si_kstat.si_buff = skp->sk_buff.value.ul;
5017c478bd9Sstevel@tonic-gate sip->si_kstat.si_nolink = skp->sk_nolink.value.ul;
5027c478bd9Sstevel@tonic-gate sip->si_kstat.si_linkdown = skp->sk_linkdown.value.ul;
5037c478bd9Sstevel@tonic-gate sip->si_kstat.si_inits = skp->sk_inits.value.ul;
5047c478bd9Sstevel@tonic-gate sip->si_kstat.si_nocanput = skp->sk_nocanput.value.ul;
5057c478bd9Sstevel@tonic-gate sip->si_kstat.si_allocbfail = skp->sk_allocbfail.value.ul;
5067c478bd9Sstevel@tonic-gate sip->si_kstat.si_notbufs = skp->sk_notbufs.value.ul;
5077c478bd9Sstevel@tonic-gate sip->si_kstat.si_reclaim = skp->sk_reclaim.value.ul;
5087c478bd9Sstevel@tonic-gate sip->si_kstat.si_smraddr = skp->sk_smraddr.value.ul;
5097c478bd9Sstevel@tonic-gate sip->si_kstat.si_txmax = skp->sk_txmax.value.ul;
5107c478bd9Sstevel@tonic-gate sip->si_kstat.si_txfull = skp->sk_txfull.value.ul;
5117c478bd9Sstevel@tonic-gate sip->si_kstat.si_xdcall = skp->sk_xdcall.value.ul;
5127c478bd9Sstevel@tonic-gate sip->si_kstat.si_sigsvr = skp->sk_sigsvr.value.ul;
5137c478bd9Sstevel@tonic-gate sip->si_kstat.si_mboxcrc = skp->sk_mboxcrc.value.ul;
5147c478bd9Sstevel@tonic-gate /*
5157c478bd9Sstevel@tonic-gate * MIB II kstat variables
5167c478bd9Sstevel@tonic-gate */
5177c478bd9Sstevel@tonic-gate sip->si_kstat.si_rcvbytes = skp->sk_rcvbytes.value.ul;
5187c478bd9Sstevel@tonic-gate sip->si_kstat.si_xmtbytes = skp->sk_xmtbytes.value.ul;
5197c478bd9Sstevel@tonic-gate sip->si_kstat.si_multircv = skp->sk_multircv.value.ul;
5207c478bd9Sstevel@tonic-gate sip->si_kstat.si_multixmt = skp->sk_multixmt.value.ul;
5217c478bd9Sstevel@tonic-gate sip->si_kstat.si_brdcstrcv = skp->sk_brdcstrcv.value.ul;
5227c478bd9Sstevel@tonic-gate sip->si_kstat.si_brdcstxmt = skp->sk_brdcstxmt.value.ul;
5237c478bd9Sstevel@tonic-gate sip->si_kstat.si_norcvbuf = skp->sk_norcvbuf.value.ul;
5247c478bd9Sstevel@tonic-gate sip->si_kstat.si_noxmtbuf = skp->sk_noxmtbuf.value.ul;
5257c478bd9Sstevel@tonic-gate /*
5267c478bd9Sstevel@tonic-gate * PSARC 1997/198 : 64bit kstats
5277c478bd9Sstevel@tonic-gate */
5287c478bd9Sstevel@tonic-gate sip->si_kstat.si_ipackets64 = skp->sk_ipackets64.value.ull;
5297c478bd9Sstevel@tonic-gate sip->si_kstat.si_opackets64 = skp->sk_opackets64.value.ull;
5307c478bd9Sstevel@tonic-gate sip->si_kstat.si_rbytes64 = skp->sk_rbytes64.value.ull;
5317c478bd9Sstevel@tonic-gate sip->si_kstat.si_obytes64 = skp->sk_obytes64.value.ull;
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate * PSARC 1997/247 : RFC 1643
5347c478bd9Sstevel@tonic-gate */
5357c478bd9Sstevel@tonic-gate sip->si_kstat.si_fcs_errors = skp->sk_fcs_errors.value.ul;
5367c478bd9Sstevel@tonic-gate sip->si_kstat.si_macxmt_errors =
5377c478bd9Sstevel@tonic-gate skp->sk_macxmt_errors.value.ul;
5387c478bd9Sstevel@tonic-gate sip->si_kstat.si_toolong_errors =
5397c478bd9Sstevel@tonic-gate skp->sk_toolong_errors.value.ul;
5407c478bd9Sstevel@tonic-gate sip->si_kstat.si_macrcv_errors =
5417c478bd9Sstevel@tonic-gate skp->sk_macrcv_errors.value.ul;
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate return (0);
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate skp->sk_ipackets.value.ul = sip->si_kstat.si_ipackets;
5477c478bd9Sstevel@tonic-gate skp->sk_ierrors.value.ul = sip->si_kstat.si_ierrors;
5487c478bd9Sstevel@tonic-gate skp->sk_opackets.value.ul = sip->si_kstat.si_opackets;
5497c478bd9Sstevel@tonic-gate skp->sk_oerrors.value.ul = sip->si_kstat.si_oerrors;
5507c478bd9Sstevel@tonic-gate skp->sk_txcoll.value.ul = sip->si_kstat.si_txcoll;
5517c478bd9Sstevel@tonic-gate skp->sk_rxcoll.value.ul = sip->si_kstat.si_rxcoll;
5527c478bd9Sstevel@tonic-gate skp->sk_crc.value.ul = sip->si_kstat.si_crc;
5537c478bd9Sstevel@tonic-gate skp->sk_buff.value.ul = sip->si_kstat.si_buff;
5547c478bd9Sstevel@tonic-gate skp->sk_nolink.value.ul = sip->si_kstat.si_nolink;
5557c478bd9Sstevel@tonic-gate skp->sk_linkdown.value.ul = sip->si_kstat.si_linkdown;
5567c478bd9Sstevel@tonic-gate skp->sk_inits.value.ul = sip->si_kstat.si_inits;
5577c478bd9Sstevel@tonic-gate skp->sk_nocanput.value.ul = sip->si_kstat.si_nocanput;
5587c478bd9Sstevel@tonic-gate skp->sk_allocbfail.value.ul = sip->si_kstat.si_allocbfail;
5597c478bd9Sstevel@tonic-gate skp->sk_notbufs.value.ul = sip->si_kstat.si_notbufs;
5607c478bd9Sstevel@tonic-gate skp->sk_reclaim.value.ul = sip->si_kstat.si_reclaim;
5617c478bd9Sstevel@tonic-gate skp->sk_smraddr.value.ul = sip->si_kstat.si_smraddr;
5627c478bd9Sstevel@tonic-gate skp->sk_txfull.value.ul = sip->si_kstat.si_txfull;
5637c478bd9Sstevel@tonic-gate skp->sk_txmax.value.ul = sip->si_kstat.si_txmax;
5647c478bd9Sstevel@tonic-gate skp->sk_xdcall.value.ul = sip->si_kstat.si_xdcall;
5657c478bd9Sstevel@tonic-gate skp->sk_sigsvr.value.ul = sip->si_kstat.si_sigsvr;
5667c478bd9Sstevel@tonic-gate skp->sk_mboxcrc.value.ul = sip->si_kstat.si_mboxcrc;
5677c478bd9Sstevel@tonic-gate /*
5687c478bd9Sstevel@tonic-gate * MIB II kstat variables
5697c478bd9Sstevel@tonic-gate */
5707c478bd9Sstevel@tonic-gate skp->sk_rcvbytes.value.ul = sip->si_kstat.si_rcvbytes;
5717c478bd9Sstevel@tonic-gate skp->sk_xmtbytes.value.ul = sip->si_kstat.si_xmtbytes;
5727c478bd9Sstevel@tonic-gate skp->sk_multircv.value.ul = sip->si_kstat.si_multircv;
5737c478bd9Sstevel@tonic-gate skp->sk_multixmt.value.ul = sip->si_kstat.si_multixmt;
5747c478bd9Sstevel@tonic-gate skp->sk_brdcstrcv.value.ul = sip->si_kstat.si_brdcstrcv;
5757c478bd9Sstevel@tonic-gate skp->sk_brdcstxmt.value.ul = sip->si_kstat.si_brdcstxmt;
5767c478bd9Sstevel@tonic-gate skp->sk_norcvbuf.value.ul = sip->si_kstat.si_norcvbuf;
5777c478bd9Sstevel@tonic-gate skp->sk_noxmtbuf.value.ul = sip->si_kstat.si_noxmtbuf;
5787c478bd9Sstevel@tonic-gate /*
5797c478bd9Sstevel@tonic-gate * PSARC 1997/198 : 64bit kstats
5807c478bd9Sstevel@tonic-gate */
5817c478bd9Sstevel@tonic-gate skp->sk_ipackets64.value.ull = sip->si_kstat.si_ipackets64;
5827c478bd9Sstevel@tonic-gate skp->sk_opackets64.value.ull = sip->si_kstat.si_opackets64;
5837c478bd9Sstevel@tonic-gate skp->sk_rbytes64.value.ull = sip->si_kstat.si_rbytes64;
5847c478bd9Sstevel@tonic-gate skp->sk_obytes64.value.ull = sip->si_kstat.si_obytes64;
5857c478bd9Sstevel@tonic-gate /*
5867c478bd9Sstevel@tonic-gate * PSARC 1997/247 : RFC 1643
5877c478bd9Sstevel@tonic-gate */
5887c478bd9Sstevel@tonic-gate skp->sk_fcs_errors.value.ul = sip->si_kstat.si_fcs_errors;
5897c478bd9Sstevel@tonic-gate skp->sk_macxmt_errors.value.ul = sip->si_kstat.si_macxmt_errors;
5907c478bd9Sstevel@tonic-gate skp->sk_toolong_errors.value.ul = sip->si_kstat.si_toolong_errors;
5917c478bd9Sstevel@tonic-gate skp->sk_macrcv_errors.value.ul = sip->si_kstat.si_macrcv_errors;
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate return (0);
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate void
idndl_statinit(struct idn * sip)5977c478bd9Sstevel@tonic-gate idndl_statinit(struct idn *sip)
5987c478bd9Sstevel@tonic-gate {
5997c478bd9Sstevel@tonic-gate struct kstat *ksp;
6007c478bd9Sstevel@tonic-gate struct idn_kstat_named *skp;
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate #ifdef kstat
6037c478bd9Sstevel@tonic-gate if ((ksp = kstat_create(IDNNAME, ddi_get_instance(sip->si_dip),
6047c478bd9Sstevel@tonic-gate NULL, "net", KSTAT_TYPE_NAMED,
6057c478bd9Sstevel@tonic-gate sizeof (struct idn_kstat_named) / sizeof (kstat_named_t),
6067c478bd9Sstevel@tonic-gate KSTAT_FLAG_PERSISTENT)) == NULL) {
6077c478bd9Sstevel@tonic-gate #else
6087c478bd9Sstevel@tonic-gate if ((ksp = kstat_create(IDNNAME, ddi_get_instance(sip->si_dip),
6097c478bd9Sstevel@tonic-gate NULL, "net", KSTAT_TYPE_NAMED,
6107c478bd9Sstevel@tonic-gate sizeof (struct idn_kstat_named) /
6117c478bd9Sstevel@tonic-gate sizeof (kstat_named_t), 0)) == NULL) {
6127c478bd9Sstevel@tonic-gate #endif /* kstat */
6137c478bd9Sstevel@tonic-gate serror(sip->si_dip, 450, "kstat_create failed");
6147c478bd9Sstevel@tonic-gate return;
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate sip->si_ksp = ksp;
6187c478bd9Sstevel@tonic-gate skp = (struct idn_kstat_named *)(ksp->ks_data);
6197c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_ipackets, "ipackets",
6207c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6217c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_ierrors, "ierrors",
6227c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6237c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_opackets, "opackets",
6247c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6257c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_oerrors, "oerrors",
6267c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6277c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_txcoll, "collisions",
6287c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6297c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_rxcoll, "rx_collisions",
6307c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6317c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_crc, "crc",
6327c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6337c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_buff, "buff",
6347c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6357c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_nolink, "nolink",
6367c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6377c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_linkdown, "linkdown",
6387c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6397c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_inits, "inits",
6407c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6417c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_nocanput, "nocanput",
6427c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6437c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_allocbfail, "allocbfail",
6447c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6457c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_notbufs, "notbufs",
6467c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6477c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_reclaim, "reclaim",
6487c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6497c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_smraddr, "smraddr",
6507c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6517c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_txmax, "txmax",
6527c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6537c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_txfull, "txfull",
6547c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6557c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_xdcall, "xdcall",
6567c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6577c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_sigsvr, "sigsvr",
6587c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6597c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_mboxcrc, "mboxcrc",
6607c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6617c478bd9Sstevel@tonic-gate /*
6627c478bd9Sstevel@tonic-gate * MIB II kstat variables
6637c478bd9Sstevel@tonic-gate */
6647c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_rcvbytes, "rbytes",
6657c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6667c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_xmtbytes, "obytes",
6677c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6687c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_multircv, "multircv",
6697c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6707c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_multixmt, "multixmt",
6717c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6727c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_brdcstrcv, "brdcstrcv",
6737c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6747c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_brdcstxmt, "brdcstxmt",
6757c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6767c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_norcvbuf, "norcvbuf",
6777c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6787c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_noxmtbuf, "noxmtbuf",
6797c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6807c478bd9Sstevel@tonic-gate /*
6817c478bd9Sstevel@tonic-gate * PSARC 1997/198 : 64bit kstats
6827c478bd9Sstevel@tonic-gate */
6837c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_ipackets64, "ipackets64",
6847c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONGLONG);
6857c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_opackets64, "opackets64",
6867c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONGLONG);
6877c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_rbytes64, "rbytes64",
6887c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONGLONG);
6897c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_obytes64, "obytes64",
6907c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONGLONG);
6917c478bd9Sstevel@tonic-gate /*
6927c478bd9Sstevel@tonic-gate * PSARC 1997/247 : RFC 1643
6937c478bd9Sstevel@tonic-gate */
6947c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_fcs_errors, "fcs_errors",
6957c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6967c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_macxmt_errors, "macxmt_errors",
6977c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
6987c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_toolong_errors, "toolong_errors",
6997c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
7007c478bd9Sstevel@tonic-gate kstat_named_init(&skp->sk_macrcv_errors, "macrcv_errors",
7017c478bd9Sstevel@tonic-gate KSTAT_DATA_ULONG);
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate ksp->ks_update = idndl_stat_kstat_update;
7047c478bd9Sstevel@tonic-gate ksp->ks_private = (void *)sip;
7057c478bd9Sstevel@tonic-gate kstat_install(ksp);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate void
7097c478bd9Sstevel@tonic-gate idndl_proto(queue_t *wq, mblk_t *mp)
7107c478bd9Sstevel@tonic-gate {
7117c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
7127c478bd9Sstevel@tonic-gate struct idnstr *stp;
7137c478bd9Sstevel@tonic-gate t_uscalar_t prim;
7147c478bd9Sstevel@tonic-gate procname_t proc = "idndl_proto";
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
7177c478bd9Sstevel@tonic-gate if (MBLKL(mp) < sizeof (t_uscalar_t)) {
7187c478bd9Sstevel@tonic-gate /*
7197c478bd9Sstevel@tonic-gate * Gotta at least have enough room to hold
7207c478bd9Sstevel@tonic-gate * the primitive!
7217c478bd9Sstevel@tonic-gate */
7227c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, -1, DL_BADPRIM, 0);
7237c478bd9Sstevel@tonic-gate return;
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
7267c478bd9Sstevel@tonic-gate prim = dlp->dl_primitive;
7277c478bd9Sstevel@tonic-gate
7287c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_IDN, TR_IDN_PROTO_START,
7297c478bd9Sstevel@tonic-gate "idndl_proto start: wq %p dlprim %X", wq, prim);
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate #ifdef DEBUG
732bf30efa4Smathue PR_DLPI("%s: stp = 0x%p, wq = 0x%p, dlprim = 0x%x(%s)\n",
733*07d06da5SSurya Prakki proc, (void *)stp, (void *)wq, prim, dlprim2str(prim));
7347c478bd9Sstevel@tonic-gate #endif /* DEBUG */
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate rw_enter(&stp->ss_rwlock, RW_WRITER);
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate switch (prim) {
7397c478bd9Sstevel@tonic-gate case DL_UNITDATA_REQ:
7407c478bd9Sstevel@tonic-gate idndl_udreq(wq, mp);
7417c478bd9Sstevel@tonic-gate break;
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate case DL_ATTACH_REQ:
7447c478bd9Sstevel@tonic-gate idndl_areq(wq, mp);
7457c478bd9Sstevel@tonic-gate break;
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate case DL_DETACH_REQ:
7487c478bd9Sstevel@tonic-gate idndl_dreq(wq, mp);
7497c478bd9Sstevel@tonic-gate break;
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate case DL_BIND_REQ:
7527c478bd9Sstevel@tonic-gate idndl_breq(wq, mp);
7537c478bd9Sstevel@tonic-gate break;
7547c478bd9Sstevel@tonic-gate
7557c478bd9Sstevel@tonic-gate case DL_UNBIND_REQ:
7567c478bd9Sstevel@tonic-gate idndl_ubreq(wq, mp);
7577c478bd9Sstevel@tonic-gate break;
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate case DL_INFO_REQ:
7607c478bd9Sstevel@tonic-gate idndl_ireq(wq, mp);
7617c478bd9Sstevel@tonic-gate break;
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate case DL_PROMISCON_REQ:
7647c478bd9Sstevel@tonic-gate idndl_ponreq(wq, mp);
7657c478bd9Sstevel@tonic-gate break;
7667c478bd9Sstevel@tonic-gate
7677c478bd9Sstevel@tonic-gate case DL_PROMISCOFF_REQ:
7687c478bd9Sstevel@tonic-gate idndl_poffreq(wq, mp);
7697c478bd9Sstevel@tonic-gate break;
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate case DL_ENABMULTI_REQ:
7727c478bd9Sstevel@tonic-gate idndl_emreq(wq, mp);
7737c478bd9Sstevel@tonic-gate break;
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate case DL_DISABMULTI_REQ:
7767c478bd9Sstevel@tonic-gate idndl_dmreq(wq, mp);
7777c478bd9Sstevel@tonic-gate break;
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate case DL_PHYS_ADDR_REQ:
7807c478bd9Sstevel@tonic-gate idndl_pareq(wq, mp);
7817c478bd9Sstevel@tonic-gate break;
7827c478bd9Sstevel@tonic-gate
7837c478bd9Sstevel@tonic-gate #ifdef notdef
7847c478bd9Sstevel@tonic-gate /*
7857c478bd9Sstevel@tonic-gate * We cannot allow this in IDN-land because we
7867c478bd9Sstevel@tonic-gate * rely on the ethernet (physical) address to determine
7877c478bd9Sstevel@tonic-gate * where to target the message. Recall that unlike
7887c478bd9Sstevel@tonic-gate * ethernet we simply cannot dump junk on the wire and
7897c478bd9Sstevel@tonic-gate * expect it to automatically find its destination.
7907c478bd9Sstevel@tonic-gate * In the IDN we need to target the destination.
7917c478bd9Sstevel@tonic-gate * Note that if we used POINT-TO-POINT then we wouldn't
7927c478bd9Sstevel@tonic-gate * have to worry about the physical address since each
7937c478bd9Sstevel@tonic-gate * domain connection would have a separate queue.
7947c478bd9Sstevel@tonic-gate * However, ptp then requires multiple interfaces at
7957c478bd9Sstevel@tonic-gate * the appl level as opposed to a single one for all
7967c478bd9Sstevel@tonic-gate * of idn. We opt for the simpler single interface (idn0).
7977c478bd9Sstevel@tonic-gate */
7987c478bd9Sstevel@tonic-gate case DL_SET_PHYS_ADDR_REQ:
7997c478bd9Sstevel@tonic-gate idndl_spareq(wq, mp);
8007c478bd9Sstevel@tonic-gate break;
8017c478bd9Sstevel@tonic-gate #endif /* notdef */
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate default:
8047c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, prim, DL_UNSUPPORTED, 0);
8057c478bd9Sstevel@tonic-gate break;
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_IDN, TR_IDN_PROTO_END,
8097c478bd9Sstevel@tonic-gate "idnproto end: wq %p dlprim %X", wq, prim);
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate rw_exit(&stp->ss_rwlock);
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate int
8157c478bd9Sstevel@tonic-gate idnioc_dlpi(queue_t *wq, mblk_t *mp, int *argsizep)
8167c478bd9Sstevel@tonic-gate {
8177c478bd9Sstevel@tonic-gate int rv = 0;
8187c478bd9Sstevel@tonic-gate struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
8197c478bd9Sstevel@tonic-gate struct idnstr *stp = (struct idnstr *)wq->q_ptr;
8207c478bd9Sstevel@tonic-gate procname_t proc = "idnioc_dlpi";
8217c478bd9Sstevel@tonic-gate
8227c478bd9Sstevel@tonic-gate *argsizep = 0;
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) {
8257c478bd9Sstevel@tonic-gate case DLIOCRAW: /* raw M_DATA mode */
8267c478bd9Sstevel@tonic-gate PR_DLPI("%s: cmd = DLIOCRAW\n", proc);
8277c478bd9Sstevel@tonic-gate stp->ss_flags |= IDNSRAW;
8287c478bd9Sstevel@tonic-gate break;
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate case DL_IOC_HDR_INFO: /* M_DATA "fastpath" info request */
8317c478bd9Sstevel@tonic-gate PR_DLPI("%s: cmd = DL_IOC_HDR_INFO\n", proc);
8327c478bd9Sstevel@tonic-gate rv = idndl_ioc_hdr_info(wq, mp, argsizep);
8337c478bd9Sstevel@tonic-gate break;
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate default:
8367c478bd9Sstevel@tonic-gate PR_DLPI("%s: invalid cmd 0x%x\n", proc, iocp->ioc_cmd);
8377c478bd9Sstevel@tonic-gate rv = EINVAL;
8387c478bd9Sstevel@tonic-gate break;
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate return (rv);
8417c478bd9Sstevel@tonic-gate }
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate /*
8447c478bd9Sstevel@tonic-gate * M_DATA "fastpath" info request.
8457c478bd9Sstevel@tonic-gate * Following the M_IOCTL mblk should come a DL_UNITDATA_REQ mblk.
8467c478bd9Sstevel@tonic-gate * We ack with an M_IOCACK pointing to the original DL_UNITDATA_REQ mblk
8477c478bd9Sstevel@tonic-gate * followed by an mblk containing the raw ethernet header corresponding
8487c478bd9Sstevel@tonic-gate * to the destination address. Subsequently, we may receive M_DATA
8497c478bd9Sstevel@tonic-gate * msgs which start with this header and may send up
8507c478bd9Sstevel@tonic-gate * up M_DATA msgs with b_rptr pointing to a (ulong) group address
8517c478bd9Sstevel@tonic-gate * indicator followed by the network-layer data (IP packet header).
8527c478bd9Sstevel@tonic-gate * This is all selectable on a per-Stream basis.
8537c478bd9Sstevel@tonic-gate */
8547c478bd9Sstevel@tonic-gate static int
8557c478bd9Sstevel@tonic-gate idndl_ioc_hdr_info(queue_t *wq, mblk_t *mp, int *argsizep)
8567c478bd9Sstevel@tonic-gate {
8577c478bd9Sstevel@tonic-gate mblk_t *nmp;
8587c478bd9Sstevel@tonic-gate struct idnstr *stp;
8597c478bd9Sstevel@tonic-gate struct idndladdr *dlap;
8607c478bd9Sstevel@tonic-gate dl_unitdata_req_t *dludp;
8617c478bd9Sstevel@tonic-gate struct ether_header *headerp;
8627c478bd9Sstevel@tonic-gate struct idn *sip;
8637c478bd9Sstevel@tonic-gate int off, len;
8647c478bd9Sstevel@tonic-gate int padding = 0;
8657c478bd9Sstevel@tonic-gate int error;
8667c478bd9Sstevel@tonic-gate procname_t proc = "idndl_ioc_hdr_info";
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
8697c478bd9Sstevel@tonic-gate sip = stp->ss_sip;
8707c478bd9Sstevel@tonic-gate if (sip == NULL) {
8717c478bd9Sstevel@tonic-gate PR_DLPI("%s: NULL sip (ret EINVAL)\n", proc);
8727c478bd9Sstevel@tonic-gate return (EINVAL);
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (dl_unitdata_req_t) + IDNADDRL);
8767c478bd9Sstevel@tonic-gate if (error != 0) {
8777c478bd9Sstevel@tonic-gate PR_DLPI("%s: sanity error (ret %d)\n", proc, error);
8787c478bd9Sstevel@tonic-gate return (error);
8797c478bd9Sstevel@tonic-gate }
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate /*
8827c478bd9Sstevel@tonic-gate * Sanity check the DL_UNITDATA_REQ destination address
8837c478bd9Sstevel@tonic-gate * offset and length values.
8847c478bd9Sstevel@tonic-gate */
8857c478bd9Sstevel@tonic-gate dludp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
8867c478bd9Sstevel@tonic-gate off = dludp->dl_dest_addr_offset;
8877c478bd9Sstevel@tonic-gate len = dludp->dl_dest_addr_length;
8887c478bd9Sstevel@tonic-gate if (dludp->dl_primitive != DL_UNITDATA_REQ ||
8897c478bd9Sstevel@tonic-gate !MBLKIN(mp->b_cont, off, len) || len != IDNADDRL) {
8907c478bd9Sstevel@tonic-gate PR_DLPI("%s: off(0x%x)/len(%d) error (ret EINVAL)\n",
8917c478bd9Sstevel@tonic-gate proc, off, len);
8927c478bd9Sstevel@tonic-gate return (EINVAL);
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate dlap = (struct idndladdr *)(mp->b_cont->b_rptr + off);
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate /*
8987c478bd9Sstevel@tonic-gate * Allocate a new mblk to hold the ether header.
8997c478bd9Sstevel@tonic-gate */
9007c478bd9Sstevel@tonic-gate nmp = allocb(sizeof (struct ether_header) + padding, BPRI_MED);
9017c478bd9Sstevel@tonic-gate if (nmp == NULL) {
9027c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_allocbfail);
9037c478bd9Sstevel@tonic-gate return (ENOMEM);
9047c478bd9Sstevel@tonic-gate }
9057c478bd9Sstevel@tonic-gate nmp->b_rptr += padding;
9067c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + sizeof (struct ether_header);
9077c478bd9Sstevel@tonic-gate
9087c478bd9Sstevel@tonic-gate /*
9097c478bd9Sstevel@tonic-gate * Fill in the ether header.
9107c478bd9Sstevel@tonic-gate */
9117c478bd9Sstevel@tonic-gate headerp = (struct ether_header *)nmp->b_rptr;
9127c478bd9Sstevel@tonic-gate ether_copy(&dlap->dl_phys, &headerp->ether_dhost);
9137c478bd9Sstevel@tonic-gate ether_copy(&sip->si_ouraddr, &headerp->ether_shost);
9147c478bd9Sstevel@tonic-gate headerp->ether_type = dlap->dl_sap;
9157c478bd9Sstevel@tonic-gate
9167c478bd9Sstevel@tonic-gate /*
9177c478bd9Sstevel@tonic-gate * Link new mblk in after the "request" mblks.
9187c478bd9Sstevel@tonic-gate */
9197c478bd9Sstevel@tonic-gate linkb(mp, nmp);
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate stp->ss_flags |= IDNSFAST;
9227c478bd9Sstevel@tonic-gate
9237c478bd9Sstevel@tonic-gate /*
9247c478bd9Sstevel@tonic-gate * XXX Don't bother calling idndl_setipq() here.
9257c478bd9Sstevel@tonic-gate */
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate if (argsizep)
9287c478bd9Sstevel@tonic-gate *argsizep = msgsize(mp->b_cont);
9297c478bd9Sstevel@tonic-gate
9307c478bd9Sstevel@tonic-gate return (0);
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate static void
9347c478bd9Sstevel@tonic-gate idndl_areq(queue_t *wq, mblk_t *mp)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate struct idnstr *stp;
9377c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
9387c478bd9Sstevel@tonic-gate struct idn *sip;
9397c478bd9Sstevel@tonic-gate int ppa;
9407c478bd9Sstevel@tonic-gate procname_t proc = "idndl_areq";
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
9437c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
9467c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_ATTACH_REQ, DL_BADPRIM, 0);
9477c478bd9Sstevel@tonic-gate return;
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate if (stp->ss_state != DL_UNATTACHED) {
9517c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_ATTACH_REQ, DL_OUTSTATE, 0);
9527c478bd9Sstevel@tonic-gate return;
9537c478bd9Sstevel@tonic-gate }
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate ppa = dlp->attach_req.dl_ppa;
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate /*
9587c478bd9Sstevel@tonic-gate * Valid ppa?
9597c478bd9Sstevel@tonic-gate */
9607c478bd9Sstevel@tonic-gate if (ppa == -1 || qassociate(wq, ppa) != 0) {
9617c478bd9Sstevel@tonic-gate PR_DLPI("%s: bad ppa %d\n", proc, ppa);
9627c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, dlp->dl_primitive, DL_BADPPA, 0);
9637c478bd9Sstevel@tonic-gate return;
9647c478bd9Sstevel@tonic-gate }
9657c478bd9Sstevel@tonic-gate mutex_enter(&idn.siplock);
9667c478bd9Sstevel@tonic-gate for (sip = idn.sip; sip; sip = sip->si_nextp) {
9677c478bd9Sstevel@tonic-gate if (ppa == ddi_get_instance(sip->si_dip))
9687c478bd9Sstevel@tonic-gate break;
9697c478bd9Sstevel@tonic-gate }
9707c478bd9Sstevel@tonic-gate mutex_exit(&idn.siplock);
9717c478bd9Sstevel@tonic-gate ASSERT(sip != NULL); /* qassociate() succeeded */
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate /*
9747c478bd9Sstevel@tonic-gate * Has device been initialized? Do so if necessary.
9757c478bd9Sstevel@tonic-gate */
9767c478bd9Sstevel@tonic-gate if ((sip->si_flags & IDNRUNNING) == 0) {
9777c478bd9Sstevel@tonic-gate if (idndl_init(sip)) {
9787c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, dlp->dl_primitive,
9797c478bd9Sstevel@tonic-gate DL_INITFAILED, 0);
9807c478bd9Sstevel@tonic-gate (void) qassociate(wq, -1);
9817c478bd9Sstevel@tonic-gate return;
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate /*
9867c478bd9Sstevel@tonic-gate * Set link to device and update our state.
9877c478bd9Sstevel@tonic-gate */
9887c478bd9Sstevel@tonic-gate stp->ss_sip = sip;
9897c478bd9Sstevel@tonic-gate stp->ss_state = DL_UNBOUND;
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_ATTACH_REQ);
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate static void
9957c478bd9Sstevel@tonic-gate idndl_dreq(queue_t *wq, mblk_t *mp)
9967c478bd9Sstevel@tonic-gate {
9977c478bd9Sstevel@tonic-gate struct idnstr *stp;
9987c478bd9Sstevel@tonic-gate
9997c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
10007c478bd9Sstevel@tonic-gate
10017c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_DETACH_REQ_SIZE) {
10027c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
10037c478bd9Sstevel@tonic-gate return;
10047c478bd9Sstevel@tonic-gate }
10057c478bd9Sstevel@tonic-gate
10067c478bd9Sstevel@tonic-gate if (stp->ss_state != DL_UNBOUND) {
10077c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0);
10087c478bd9Sstevel@tonic-gate return;
10097c478bd9Sstevel@tonic-gate }
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate idndl_dodetach(stp);
10127c478bd9Sstevel@tonic-gate (void) qassociate(wq, -1);
10137c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_DETACH_REQ);
10147c478bd9Sstevel@tonic-gate }
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate /*
10177c478bd9Sstevel@tonic-gate * Detach a Stream from an interface.
10187c478bd9Sstevel@tonic-gate */
10197c478bd9Sstevel@tonic-gate void
10207c478bd9Sstevel@tonic-gate idndl_dodetach(struct idnstr *stp)
10217c478bd9Sstevel@tonic-gate {
10227c478bd9Sstevel@tonic-gate struct idnstr *tstp;
10237c478bd9Sstevel@tonic-gate struct idn *sip;
10247c478bd9Sstevel@tonic-gate int reinit = 0;
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate ASSERT(stp->ss_sip);
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate sip = stp->ss_sip;
10297c478bd9Sstevel@tonic-gate stp->ss_sip = NULL;
10307c478bd9Sstevel@tonic-gate
10317c478bd9Sstevel@tonic-gate /*
10327c478bd9Sstevel@tonic-gate * Disable promiscuous mode if on.
10337c478bd9Sstevel@tonic-gate */
10347c478bd9Sstevel@tonic-gate if (stp->ss_flags & IDNSALLPHYS) {
10357c478bd9Sstevel@tonic-gate stp->ss_flags &= ~IDNSALLPHYS;
10367c478bd9Sstevel@tonic-gate reinit = 1;
10377c478bd9Sstevel@tonic-gate }
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate /*
10407c478bd9Sstevel@tonic-gate * Disable ALLMULTI mode if on.
10417c478bd9Sstevel@tonic-gate */
10427c478bd9Sstevel@tonic-gate if (stp->ss_flags & IDNSALLMULTI) {
10437c478bd9Sstevel@tonic-gate stp->ss_flags &= ~IDNSALLMULTI;
10447c478bd9Sstevel@tonic-gate reinit = 1;
10457c478bd9Sstevel@tonic-gate }
10467c478bd9Sstevel@tonic-gate
10477c478bd9Sstevel@tonic-gate /*
10487c478bd9Sstevel@tonic-gate * Disable any Multicast Addresses.
10497c478bd9Sstevel@tonic-gate */
10507c478bd9Sstevel@tonic-gate stp->ss_mccount = 0;
10517c478bd9Sstevel@tonic-gate if (stp->ss_mctab) {
10527c478bd9Sstevel@tonic-gate kmem_free(stp->ss_mctab, IDNMCALLOC);
10537c478bd9Sstevel@tonic-gate stp->ss_mctab = NULL;
10547c478bd9Sstevel@tonic-gate reinit = 1;
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate /*
10587c478bd9Sstevel@tonic-gate * Detach from device structure.
10597c478bd9Sstevel@tonic-gate * Uninit the device when no other streams are attached to it.
10607c478bd9Sstevel@tonic-gate */
10617c478bd9Sstevel@tonic-gate rw_enter(&idn.struprwlock, RW_READER);
10627c478bd9Sstevel@tonic-gate for (tstp = idn.strup; tstp; tstp = tstp->ss_nextp)
10637c478bd9Sstevel@tonic-gate if (tstp->ss_sip == sip)
10647c478bd9Sstevel@tonic-gate break;
10657c478bd9Sstevel@tonic-gate rw_exit(&idn.struprwlock);
10667c478bd9Sstevel@tonic-gate
10677c478bd9Sstevel@tonic-gate if (tstp == NULL)
10687c478bd9Sstevel@tonic-gate idndl_uninit(sip);
10697c478bd9Sstevel@tonic-gate else if (reinit)
10707c478bd9Sstevel@tonic-gate (void) idndl_init(sip);
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate stp->ss_state = DL_UNATTACHED;
10737c478bd9Sstevel@tonic-gate
10747c478bd9Sstevel@tonic-gate idndl_setipq(sip);
10757c478bd9Sstevel@tonic-gate }
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate static void
10787c478bd9Sstevel@tonic-gate idndl_breq(queue_t *wq, mblk_t *mp)
10797c478bd9Sstevel@tonic-gate {
10807c478bd9Sstevel@tonic-gate struct idnstr *stp;
10817c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
10827c478bd9Sstevel@tonic-gate struct idn *sip;
10837c478bd9Sstevel@tonic-gate struct idndladdr idnaddr;
10847c478bd9Sstevel@tonic-gate t_uscalar_t sap;
10857c478bd9Sstevel@tonic-gate int xidtest;
10867c478bd9Sstevel@tonic-gate procname_t proc = "idndl_breq";
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
10917c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
10927c478bd9Sstevel@tonic-gate return;
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate if (stp->ss_state != DL_UNBOUND) {
10967c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
10977c478bd9Sstevel@tonic-gate return;
10987c478bd9Sstevel@tonic-gate }
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
11017c478bd9Sstevel@tonic-gate
11027c478bd9Sstevel@tonic-gate if (dlp->bind_req.dl_service_mode != idninfoack.dl_service_mode) {
11037c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0);
11047c478bd9Sstevel@tonic-gate return;
11057c478bd9Sstevel@tonic-gate }
11067c478bd9Sstevel@tonic-gate
11077c478bd9Sstevel@tonic-gate sip = stp->ss_sip;
11087c478bd9Sstevel@tonic-gate sap = dlp->bind_req.dl_sap;
11097c478bd9Sstevel@tonic-gate xidtest = dlp->bind_req.dl_xidtest_flg;
11107c478bd9Sstevel@tonic-gate
11117c478bd9Sstevel@tonic-gate ASSERT(sip);
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate if (xidtest) {
11147c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_BIND_REQ, DL_NOAUTO, 0);
11157c478bd9Sstevel@tonic-gate return;
11167c478bd9Sstevel@tonic-gate }
11177c478bd9Sstevel@tonic-gate
11187c478bd9Sstevel@tonic-gate if (sap > ETHERTYPE_MAX) {
11197c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, dlp->dl_primitive, DL_BADSAP, 0);
11207c478bd9Sstevel@tonic-gate return;
11217c478bd9Sstevel@tonic-gate }
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate /*
11247c478bd9Sstevel@tonic-gate * Save SAP value for this Stream and change state.
11257c478bd9Sstevel@tonic-gate */
11267c478bd9Sstevel@tonic-gate stp->ss_sap = sap;
11277c478bd9Sstevel@tonic-gate stp->ss_state = DL_IDLE;
11287c478bd9Sstevel@tonic-gate
11297c478bd9Sstevel@tonic-gate idnaddr.dl_sap = sap;
11307c478bd9Sstevel@tonic-gate ether_copy(&sip->si_ouraddr, &idnaddr.dl_phys);
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate if (IS_ETHERTYPE_IP(sap)) {
11337c478bd9Sstevel@tonic-gate int channel;
11347c478bd9Sstevel@tonic-gate
11357c478bd9Sstevel@tonic-gate channel =
11367c478bd9Sstevel@tonic-gate (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL];
11377c478bd9Sstevel@tonic-gate PR_DLPI("%s: IP SAP, opening channel %d\n", proc, channel);
11387c478bd9Sstevel@tonic-gate if (idn_open_channel(channel)) {
11397c478bd9Sstevel@tonic-gate PR_DLPI("%s: FAILED TO OPEN CHANNEL %d\n",
11407c478bd9Sstevel@tonic-gate proc, channel);
11417c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, dlp->dl_primitive, DL_NOADDR, 0);
11427c478bd9Sstevel@tonic-gate return;
11437c478bd9Sstevel@tonic-gate }
11447c478bd9Sstevel@tonic-gate }
11457c478bd9Sstevel@tonic-gate DLBINDACK(wq, mp, sap, &idnaddr, IDNADDRL, 0, 0);
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate idndl_setipq(sip);
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate
11507c478bd9Sstevel@tonic-gate static void
11517c478bd9Sstevel@tonic-gate idndl_ubreq(queue_t *wq, mblk_t *mp)
11527c478bd9Sstevel@tonic-gate {
11537c478bd9Sstevel@tonic-gate struct idnstr *stp;
11547c478bd9Sstevel@tonic-gate procname_t proc = "idndl_ubreq";
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
11577c478bd9Sstevel@tonic-gate
11587c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
11597c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_UNBIND_REQ, DL_BADPRIM, 0);
11607c478bd9Sstevel@tonic-gate return;
11617c478bd9Sstevel@tonic-gate }
11627c478bd9Sstevel@tonic-gate
11637c478bd9Sstevel@tonic-gate if (stp->ss_state != DL_IDLE) {
11647c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
11657c478bd9Sstevel@tonic-gate return;
11667c478bd9Sstevel@tonic-gate }
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate stp->ss_state = DL_UNBOUND;
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate if (IS_ETHERTYPE_IP(stp->ss_sap)) {
11717c478bd9Sstevel@tonic-gate struct idn *sip;
11727c478bd9Sstevel@tonic-gate int channel;
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate sip = stp->ss_sip;
11757c478bd9Sstevel@tonic-gate channel =
11767c478bd9Sstevel@tonic-gate (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL];
11777c478bd9Sstevel@tonic-gate PR_DLPI("%s: IP SAP, unbinding channel %d\n", proc, channel);
11787c478bd9Sstevel@tonic-gate /*
11797c478bd9Sstevel@tonic-gate * We need to do an "soft" close since there's a
11807c478bd9Sstevel@tonic-gate * potential that we've been called by one of the
11817c478bd9Sstevel@tonic-gate * IDN data server/dispatcher threads! We'll deadlock
11827c478bd9Sstevel@tonic-gate * if we attempt a "hard" close of the channel from here.
11837c478bd9Sstevel@tonic-gate */
11847c478bd9Sstevel@tonic-gate idn_close_channel(channel, IDNCHAN_SOFT_CLOSE);
11857c478bd9Sstevel@tonic-gate }
11867c478bd9Sstevel@tonic-gate
11877c478bd9Sstevel@tonic-gate stp->ss_sap = 0;
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_UNBIND_REQ);
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate idndl_setipq(stp->ss_sip);
11927c478bd9Sstevel@tonic-gate }
11937c478bd9Sstevel@tonic-gate
11947c478bd9Sstevel@tonic-gate static void
11957c478bd9Sstevel@tonic-gate idndl_ireq(queue_t *wq, mblk_t *mp)
11967c478bd9Sstevel@tonic-gate {
11977c478bd9Sstevel@tonic-gate struct idnstr *stp;
11987c478bd9Sstevel@tonic-gate dl_info_ack_t *dlip;
11997c478bd9Sstevel@tonic-gate struct idndladdr *dlap;
12007c478bd9Sstevel@tonic-gate struct ether_addr *ep;
12017c478bd9Sstevel@tonic-gate int size;
12027c478bd9Sstevel@tonic-gate
12037c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_INFO_REQ_SIZE) {
12067c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_INFO_REQ, DL_BADPRIM, 0);
12077c478bd9Sstevel@tonic-gate return;
12087c478bd9Sstevel@tonic-gate }
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate /*
12117c478bd9Sstevel@tonic-gate * Exchange current msg for a DL_INFO_ACK.
12127c478bd9Sstevel@tonic-gate */
12137c478bd9Sstevel@tonic-gate size = sizeof (dl_info_ack_t) + IDNADDRL + ETHERADDRL;
12147c478bd9Sstevel@tonic-gate if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL)
12157c478bd9Sstevel@tonic-gate return;
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate /*
12187c478bd9Sstevel@tonic-gate * Fill in the DL_INFO_ACK fields and reply.
12197c478bd9Sstevel@tonic-gate */
12207c478bd9Sstevel@tonic-gate dlip = (dl_info_ack_t *)mp->b_rptr;
12217c478bd9Sstevel@tonic-gate ASSERT(idninfoack.dl_max_sdu);
12227c478bd9Sstevel@tonic-gate *dlip = idninfoack;
12237c478bd9Sstevel@tonic-gate dlip->dl_current_state = stp->ss_state;
12247c478bd9Sstevel@tonic-gate dlap = (struct idndladdr *)(mp->b_rptr + dlip->dl_addr_offset);
12257c478bd9Sstevel@tonic-gate dlap->dl_sap = stp->ss_sap;
12267c478bd9Sstevel@tonic-gate if (stp->ss_sip) {
12277c478bd9Sstevel@tonic-gate ether_copy(&stp->ss_sip->si_ouraddr, &dlap->dl_phys);
12287c478bd9Sstevel@tonic-gate } else {
12297c478bd9Sstevel@tonic-gate bzero(&dlap->dl_phys, ETHERADDRL);
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate ep = (struct ether_addr *)(mp->b_rptr + dlip->dl_brdcst_addr_offset);
12327c478bd9Sstevel@tonic-gate ether_copy(ðerbroadcastaddr, ep);
12337c478bd9Sstevel@tonic-gate
12347c478bd9Sstevel@tonic-gate qreply(wq, mp);
12357c478bd9Sstevel@tonic-gate }
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate static void
12387c478bd9Sstevel@tonic-gate idndl_ponreq(queue_t *wq, mblk_t *mp)
12397c478bd9Sstevel@tonic-gate {
12407c478bd9Sstevel@tonic-gate struct idnstr *stp;
12417c478bd9Sstevel@tonic-gate
12427c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
12437c478bd9Sstevel@tonic-gate
12447c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_PROMISCON_REQ_SIZE) {
12457c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0);
12467c478bd9Sstevel@tonic-gate return;
12477c478bd9Sstevel@tonic-gate }
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate switch (((dl_promiscon_req_t *)mp->b_rptr)->dl_level) {
12507c478bd9Sstevel@tonic-gate case DL_PROMISC_PHYS:
12517c478bd9Sstevel@tonic-gate stp->ss_flags |= IDNSALLPHYS;
12527c478bd9Sstevel@tonic-gate break;
12537c478bd9Sstevel@tonic-gate
12547c478bd9Sstevel@tonic-gate case DL_PROMISC_SAP:
12557c478bd9Sstevel@tonic-gate stp->ss_flags |= IDNSALLSAP;
12567c478bd9Sstevel@tonic-gate break;
12577c478bd9Sstevel@tonic-gate
12587c478bd9Sstevel@tonic-gate case DL_PROMISC_MULTI:
12597c478bd9Sstevel@tonic-gate stp->ss_flags |= IDNSALLMULTI;
12607c478bd9Sstevel@tonic-gate break;
12617c478bd9Sstevel@tonic-gate
12627c478bd9Sstevel@tonic-gate default:
12637c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
12647c478bd9Sstevel@tonic-gate return;
12657c478bd9Sstevel@tonic-gate }
12667c478bd9Sstevel@tonic-gate
12677c478bd9Sstevel@tonic-gate if (stp->ss_sip)
12687c478bd9Sstevel@tonic-gate (void) idndl_init(stp->ss_sip);
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate if (stp->ss_sip)
12717c478bd9Sstevel@tonic-gate idndl_setipq(stp->ss_sip);
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_PROMISCON_REQ);
12747c478bd9Sstevel@tonic-gate }
12757c478bd9Sstevel@tonic-gate
12767c478bd9Sstevel@tonic-gate static void
12777c478bd9Sstevel@tonic-gate idndl_poffreq(queue_t *wq, mblk_t *mp)
12787c478bd9Sstevel@tonic-gate {
12797c478bd9Sstevel@tonic-gate struct idnstr *stp;
12807c478bd9Sstevel@tonic-gate int flag;
12817c478bd9Sstevel@tonic-gate
12827c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
12837c478bd9Sstevel@tonic-gate
12847c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_PROMISCOFF_REQ_SIZE) {
12857c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0);
12867c478bd9Sstevel@tonic-gate return;
12877c478bd9Sstevel@tonic-gate }
12887c478bd9Sstevel@tonic-gate
12897c478bd9Sstevel@tonic-gate switch (((dl_promiscoff_req_t *)mp->b_rptr)->dl_level) {
12907c478bd9Sstevel@tonic-gate case DL_PROMISC_PHYS:
12917c478bd9Sstevel@tonic-gate flag = IDNSALLPHYS;
12927c478bd9Sstevel@tonic-gate break;
12937c478bd9Sstevel@tonic-gate
12947c478bd9Sstevel@tonic-gate case DL_PROMISC_SAP:
12957c478bd9Sstevel@tonic-gate flag = IDNSALLSAP;
12967c478bd9Sstevel@tonic-gate break;
12977c478bd9Sstevel@tonic-gate
12987c478bd9Sstevel@tonic-gate case DL_PROMISC_MULTI:
12997c478bd9Sstevel@tonic-gate flag = IDNSALLMULTI;
13007c478bd9Sstevel@tonic-gate break;
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate default:
13037c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
13047c478bd9Sstevel@tonic-gate return;
13057c478bd9Sstevel@tonic-gate }
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate if ((stp->ss_flags & flag) == 0) {
13087c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
13097c478bd9Sstevel@tonic-gate return;
13107c478bd9Sstevel@tonic-gate }
13117c478bd9Sstevel@tonic-gate
13127c478bd9Sstevel@tonic-gate stp->ss_flags &= ~flag;
13137c478bd9Sstevel@tonic-gate
13147c478bd9Sstevel@tonic-gate if (stp->ss_sip)
13157c478bd9Sstevel@tonic-gate (void) idndl_init(stp->ss_sip);
13167c478bd9Sstevel@tonic-gate
13177c478bd9Sstevel@tonic-gate if (stp->ss_sip)
13187c478bd9Sstevel@tonic-gate idndl_setipq(stp->ss_sip);
13197c478bd9Sstevel@tonic-gate
13207c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_PROMISCOFF_REQ);
13217c478bd9Sstevel@tonic-gate }
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate static void
13247c478bd9Sstevel@tonic-gate idndl_emreq(queue_t *wq, mblk_t *mp)
13257c478bd9Sstevel@tonic-gate {
13267c478bd9Sstevel@tonic-gate struct idnstr *stp;
13277c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
13287c478bd9Sstevel@tonic-gate struct ether_addr *addrp;
13297c478bd9Sstevel@tonic-gate int off;
13307c478bd9Sstevel@tonic-gate int len;
13317c478bd9Sstevel@tonic-gate int i;
13327c478bd9Sstevel@tonic-gate
13337c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_ENABMULTI_REQ_SIZE) {
13367c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_BADPRIM, 0);
13377c478bd9Sstevel@tonic-gate return;
13387c478bd9Sstevel@tonic-gate }
13397c478bd9Sstevel@tonic-gate
13407c478bd9Sstevel@tonic-gate if (stp->ss_state == DL_UNATTACHED) {
13417c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0);
13427c478bd9Sstevel@tonic-gate return;
13437c478bd9Sstevel@tonic-gate }
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
13467c478bd9Sstevel@tonic-gate len = dlp->enabmulti_req.dl_addr_length;
13477c478bd9Sstevel@tonic-gate off = dlp->enabmulti_req.dl_addr_offset;
13487c478bd9Sstevel@tonic-gate addrp = (struct ether_addr *)(mp->b_rptr + off);
13497c478bd9Sstevel@tonic-gate
13507c478bd9Sstevel@tonic-gate if ((len != ETHERADDRL) ||
13517c478bd9Sstevel@tonic-gate !MBLKIN(mp, off, len) ||
13527c478bd9Sstevel@tonic-gate !IDNDL_ADDR_IS_MULTICAST(addrp)) {
13537c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
13547c478bd9Sstevel@tonic-gate return;
13557c478bd9Sstevel@tonic-gate }
13567c478bd9Sstevel@tonic-gate
13577c478bd9Sstevel@tonic-gate if ((stp->ss_mccount + 1) >= IDNMAXMC) {
13587c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_TOOMANY, 0);
13597c478bd9Sstevel@tonic-gate return;
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate
13627c478bd9Sstevel@tonic-gate /*
13637c478bd9Sstevel@tonic-gate * Allocate table on first request.
13647c478bd9Sstevel@tonic-gate */
13657c478bd9Sstevel@tonic-gate if (stp->ss_mctab == NULL)
13667c478bd9Sstevel@tonic-gate stp->ss_mctab = kmem_alloc(IDNMCALLOC, KM_SLEEP);
13677c478bd9Sstevel@tonic-gate
13687c478bd9Sstevel@tonic-gate /*
13697c478bd9Sstevel@tonic-gate * Check to see if the address is already in the table.
13707c478bd9Sstevel@tonic-gate * Bug 1209733:
13717c478bd9Sstevel@tonic-gate * If present in the table, add the entry to the end of the table
13727c478bd9Sstevel@tonic-gate * and return without initializing the hardware.
13737c478bd9Sstevel@tonic-gate */
13747c478bd9Sstevel@tonic-gate for (i = 0; i < stp->ss_mccount; i++) {
13757c478bd9Sstevel@tonic-gate if (ether_cmp(&stp->ss_mctab[i], addrp) == 0) {
13767c478bd9Sstevel@tonic-gate stp->ss_mctab[stp->ss_mccount++] = *addrp;
13777c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_ENABMULTI_REQ);
13787c478bd9Sstevel@tonic-gate return;
13797c478bd9Sstevel@tonic-gate }
13807c478bd9Sstevel@tonic-gate }
13817c478bd9Sstevel@tonic-gate
13827c478bd9Sstevel@tonic-gate stp->ss_mctab[stp->ss_mccount++] = *addrp;
13837c478bd9Sstevel@tonic-gate
13847c478bd9Sstevel@tonic-gate (void) idndl_init(stp->ss_sip);
13857c478bd9Sstevel@tonic-gate
13867c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_ENABMULTI_REQ);
13877c478bd9Sstevel@tonic-gate }
13887c478bd9Sstevel@tonic-gate
13897c478bd9Sstevel@tonic-gate static void
13907c478bd9Sstevel@tonic-gate idndl_dmreq(queue_t *wq, mblk_t *mp)
13917c478bd9Sstevel@tonic-gate {
13927c478bd9Sstevel@tonic-gate struct idnstr *stp;
13937c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
13947c478bd9Sstevel@tonic-gate struct ether_addr *addrp;
13957c478bd9Sstevel@tonic-gate int off;
13967c478bd9Sstevel@tonic-gate int len;
13977c478bd9Sstevel@tonic-gate int i;
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_DISABMULTI_REQ_SIZE) {
14027c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0);
14037c478bd9Sstevel@tonic-gate return;
14047c478bd9Sstevel@tonic-gate }
14057c478bd9Sstevel@tonic-gate
14067c478bd9Sstevel@tonic-gate if (stp->ss_state == DL_UNATTACHED) {
14077c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_OUTSTATE, 0);
14087c478bd9Sstevel@tonic-gate return;
14097c478bd9Sstevel@tonic-gate }
14107c478bd9Sstevel@tonic-gate
14117c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
14127c478bd9Sstevel@tonic-gate len = dlp->disabmulti_req.dl_addr_length;
14137c478bd9Sstevel@tonic-gate off = dlp->disabmulti_req.dl_addr_offset;
14147c478bd9Sstevel@tonic-gate addrp = (struct ether_addr *)(mp->b_rptr + off);
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate if ((len != ETHERADDRL) || !MBLKIN(mp, off, len)) {
14177c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0);
14187c478bd9Sstevel@tonic-gate return;
14197c478bd9Sstevel@tonic-gate }
14207c478bd9Sstevel@tonic-gate
14217c478bd9Sstevel@tonic-gate /*
14227c478bd9Sstevel@tonic-gate * Find the address in the multicast table for this Stream
14237c478bd9Sstevel@tonic-gate * and delete it by shifting all subsequent multicast
14247c478bd9Sstevel@tonic-gate * table entries over one.
14257c478bd9Sstevel@tonic-gate */
14267c478bd9Sstevel@tonic-gate for (i = 0; i < stp->ss_mccount; i++)
14277c478bd9Sstevel@tonic-gate if (ether_cmp(addrp, &stp->ss_mctab[i]) == 0) {
14287c478bd9Sstevel@tonic-gate bcopy(&stp->ss_mctab[i+1],
14297c478bd9Sstevel@tonic-gate &stp->ss_mctab[i],
14307c478bd9Sstevel@tonic-gate ((stp->ss_mccount - i) *
14317c478bd9Sstevel@tonic-gate sizeof (struct ether_addr)));
14327c478bd9Sstevel@tonic-gate stp->ss_mccount--;
14337c478bd9Sstevel@tonic-gate (void) idndl_init(stp->ss_sip);
14347c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_DISABMULTI_REQ);
14357c478bd9Sstevel@tonic-gate return;
14367c478bd9Sstevel@tonic-gate }
14377c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_NOTENAB, 0);
14387c478bd9Sstevel@tonic-gate }
14397c478bd9Sstevel@tonic-gate
14407c478bd9Sstevel@tonic-gate static void
14417c478bd9Sstevel@tonic-gate idndl_pareq(queue_t *wq, mblk_t *mp)
14427c478bd9Sstevel@tonic-gate {
14437c478bd9Sstevel@tonic-gate struct idnstr *stp;
14447c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
14457c478bd9Sstevel@tonic-gate int type;
14467c478bd9Sstevel@tonic-gate struct idn *sip;
14477c478bd9Sstevel@tonic-gate struct ether_addr addr;
14487c478bd9Sstevel@tonic-gate
14497c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
14507c478bd9Sstevel@tonic-gate
14517c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_PHYS_ADDR_REQ_SIZE) {
14527c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0);
14537c478bd9Sstevel@tonic-gate return;
14547c478bd9Sstevel@tonic-gate }
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
14577c478bd9Sstevel@tonic-gate type = dlp->physaddr_req.dl_addr_type;
14587c478bd9Sstevel@tonic-gate sip = stp->ss_sip;
14597c478bd9Sstevel@tonic-gate
14607c478bd9Sstevel@tonic-gate if (sip == NULL) {
14617c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
14627c478bd9Sstevel@tonic-gate return;
14637c478bd9Sstevel@tonic-gate }
14647c478bd9Sstevel@tonic-gate
14657c478bd9Sstevel@tonic-gate switch (type) {
14667c478bd9Sstevel@tonic-gate case DL_FACT_PHYS_ADDR:
14677c478bd9Sstevel@tonic-gate idndl_localetheraddr(sip, &addr);
14687c478bd9Sstevel@tonic-gate break;
14697c478bd9Sstevel@tonic-gate
14707c478bd9Sstevel@tonic-gate case DL_CURR_PHYS_ADDR:
14717c478bd9Sstevel@tonic-gate ether_copy(&sip->si_ouraddr, &addr);
14727c478bd9Sstevel@tonic-gate break;
14737c478bd9Sstevel@tonic-gate
14747c478bd9Sstevel@tonic-gate default:
14757c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0);
14767c478bd9Sstevel@tonic-gate return;
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate
14797c478bd9Sstevel@tonic-gate DLPHYSADDRACK(wq, mp, &addr, ETHERADDRL);
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate
14827c478bd9Sstevel@tonic-gate #ifdef notdef
14837c478bd9Sstevel@tonic-gate static void
14847c478bd9Sstevel@tonic-gate idndl_spareq(queue_t *wq, mblk_t *mp)
14857c478bd9Sstevel@tonic-gate {
14867c478bd9Sstevel@tonic-gate struct idnstr *stp;
14877c478bd9Sstevel@tonic-gate union DL_primitives *dlp;
14887c478bd9Sstevel@tonic-gate int off;
14897c478bd9Sstevel@tonic-gate int len;
14907c478bd9Sstevel@tonic-gate struct ether_addr *addrp;
14917c478bd9Sstevel@tonic-gate struct idn *sip;
14927c478bd9Sstevel@tonic-gate
14937c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
14947c478bd9Sstevel@tonic-gate
14957c478bd9Sstevel@tonic-gate if (MBLKL(mp) < DL_SET_PHYS_ADDR_REQ_SIZE) {
14967c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
14977c478bd9Sstevel@tonic-gate return;
14987c478bd9Sstevel@tonic-gate }
14997c478bd9Sstevel@tonic-gate
15007c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr;
15017c478bd9Sstevel@tonic-gate len = dlp->set_physaddr_req.dl_addr_length;
15027c478bd9Sstevel@tonic-gate off = dlp->set_physaddr_req.dl_addr_offset;
15037c478bd9Sstevel@tonic-gate
15047c478bd9Sstevel@tonic-gate if (!MBLKIN(mp, off, len)) {
15057c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
15067c478bd9Sstevel@tonic-gate return;
15077c478bd9Sstevel@tonic-gate }
15087c478bd9Sstevel@tonic-gate
15097c478bd9Sstevel@tonic-gate addrp = (struct ether_addr *)(mp->b_rptr + off);
15107c478bd9Sstevel@tonic-gate
15117c478bd9Sstevel@tonic-gate /*
15127c478bd9Sstevel@tonic-gate * Error if length of address isn't right or the address
15137c478bd9Sstevel@tonic-gate * specified is a multicast or broadcast address.
15147c478bd9Sstevel@tonic-gate */
15157c478bd9Sstevel@tonic-gate if ((len != ETHERADDRL) ||
15167c478bd9Sstevel@tonic-gate IDNDL_ADDR_IS_MULTICAST(addrp) ||
15177c478bd9Sstevel@tonic-gate (ether_cmp(addrp, ðerbroadcastaddr) == 0)) {
15187c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
15197c478bd9Sstevel@tonic-gate return;
15207c478bd9Sstevel@tonic-gate }
15217c478bd9Sstevel@tonic-gate
15227c478bd9Sstevel@tonic-gate /*
15237c478bd9Sstevel@tonic-gate * Error if this stream is not attached to a device.
15247c478bd9Sstevel@tonic-gate */
15257c478bd9Sstevel@tonic-gate if ((sip = stp->ss_sip) == NULL) {
15267c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
15277c478bd9Sstevel@tonic-gate return;
15287c478bd9Sstevel@tonic-gate }
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate /*
15317c478bd9Sstevel@tonic-gate * Set new interface local address and re-init device.
15327c478bd9Sstevel@tonic-gate * This is destructive to any other streams attached
15337c478bd9Sstevel@tonic-gate * to this device.
15347c478bd9Sstevel@tonic-gate */
15357c478bd9Sstevel@tonic-gate ether_copy(addrp, &sip->si_ouraddr);
15367c478bd9Sstevel@tonic-gate (void) idndl_init(stp->ss_sip);
15377c478bd9Sstevel@tonic-gate
15387c478bd9Sstevel@tonic-gate DLOKACK(wq, mp, DL_SET_PHYS_ADDR_REQ);
15397c478bd9Sstevel@tonic-gate }
15407c478bd9Sstevel@tonic-gate #endif /* notdef */
15417c478bd9Sstevel@tonic-gate
15427c478bd9Sstevel@tonic-gate static void
15437c478bd9Sstevel@tonic-gate idndl_udreq(queue_t *wq, mblk_t *mp)
15447c478bd9Sstevel@tonic-gate {
15457c478bd9Sstevel@tonic-gate struct idnstr *stp;
15467c478bd9Sstevel@tonic-gate register struct idn *sip;
15477c478bd9Sstevel@tonic-gate register dl_unitdata_req_t *dludp;
15487c478bd9Sstevel@tonic-gate mblk_t *nmp;
15497c478bd9Sstevel@tonic-gate struct idndladdr *dlap;
15507c478bd9Sstevel@tonic-gate struct ether_header *headerp;
15517c478bd9Sstevel@tonic-gate t_uscalar_t off, len;
15527c478bd9Sstevel@tonic-gate t_uscalar_t sap;
15537c478bd9Sstevel@tonic-gate
15547c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
15557c478bd9Sstevel@tonic-gate sip = stp->ss_sip;
15567c478bd9Sstevel@tonic-gate
15577c478bd9Sstevel@tonic-gate if (stp->ss_state != DL_IDLE) {
15587c478bd9Sstevel@tonic-gate DLERRORACK(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
15597c478bd9Sstevel@tonic-gate return;
15607c478bd9Sstevel@tonic-gate }
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate dludp = (dl_unitdata_req_t *)mp->b_rptr;
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate off = dludp->dl_dest_addr_offset;
15657c478bd9Sstevel@tonic-gate len = dludp->dl_dest_addr_length;
15667c478bd9Sstevel@tonic-gate
15677c478bd9Sstevel@tonic-gate /*
15687c478bd9Sstevel@tonic-gate * Validate destination address format.
15697c478bd9Sstevel@tonic-gate */
15707c478bd9Sstevel@tonic-gate if (!MBLKIN(mp, off, len) || (len != IDNADDRL)) {
15717c478bd9Sstevel@tonic-gate dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADADDR, 0);
15727c478bd9Sstevel@tonic-gate return;
15737c478bd9Sstevel@tonic-gate }
15747c478bd9Sstevel@tonic-gate
15757c478bd9Sstevel@tonic-gate /*
15767c478bd9Sstevel@tonic-gate * Error if no M_DATA follows.
15777c478bd9Sstevel@tonic-gate */
15787c478bd9Sstevel@tonic-gate nmp = mp->b_cont;
15797c478bd9Sstevel@tonic-gate if (nmp == NULL) {
15807c478bd9Sstevel@tonic-gate dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADDATA, 0);
15817c478bd9Sstevel@tonic-gate return;
15827c478bd9Sstevel@tonic-gate }
15837c478bd9Sstevel@tonic-gate
15847c478bd9Sstevel@tonic-gate dlap = (struct idndladdr *)(mp->b_rptr + off);
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate /*
15877c478bd9Sstevel@tonic-gate * Create ethernet header by either prepending it onto the
15887c478bd9Sstevel@tonic-gate * next mblk if potential, or reusing the M_PROTO block if not.
15897c478bd9Sstevel@tonic-gate */
15907c478bd9Sstevel@tonic-gate if ((DB_REF(nmp) == 1) &&
15917c478bd9Sstevel@tonic-gate (MBLKHEAD(nmp) >= sizeof (struct ether_header)) &&
15927c478bd9Sstevel@tonic-gate (((ulong_t)nmp->b_rptr & 0x1) == 0)) {
15937c478bd9Sstevel@tonic-gate nmp->b_rptr -= sizeof (struct ether_header);
15947c478bd9Sstevel@tonic-gate headerp = (struct ether_header *)nmp->b_rptr;
15957c478bd9Sstevel@tonic-gate ether_copy(&dlap->dl_phys, &headerp->ether_dhost);
15967c478bd9Sstevel@tonic-gate ether_copy(&sip->si_ouraddr, &headerp->ether_shost);
15977c478bd9Sstevel@tonic-gate sap = dlap->dl_sap;
15987c478bd9Sstevel@tonic-gate freeb(mp);
15997c478bd9Sstevel@tonic-gate mp = nmp;
16007c478bd9Sstevel@tonic-gate } else {
16017c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_DATA;
16027c478bd9Sstevel@tonic-gate headerp = (struct ether_header *)mp->b_rptr;
16037c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct ether_header);
16047c478bd9Sstevel@tonic-gate ether_copy(&dlap->dl_phys, &headerp->ether_dhost);
16057c478bd9Sstevel@tonic-gate ether_copy(&sip->si_ouraddr, &headerp->ether_shost);
16067c478bd9Sstevel@tonic-gate sap = dlap->dl_sap;
16077c478bd9Sstevel@tonic-gate }
16087c478bd9Sstevel@tonic-gate
16097c478bd9Sstevel@tonic-gate /*
16107c478bd9Sstevel@tonic-gate * For transmitting, the driver looks at the
16117c478bd9Sstevel@tonic-gate * sap field of the DL_BIND_REQ being 0 in addition to the type
16127c478bd9Sstevel@tonic-gate * field in the range [0-1500]. If either is true, then the driver
16137c478bd9Sstevel@tonic-gate * computes the length of the message, not including initial M_PROTO
16147c478bd9Sstevel@tonic-gate * mblk (message block), of all subsequent DL_UNITDATA_REQ messages and
16157c478bd9Sstevel@tonic-gate * transmits 802.3 frames that have this value in the MAC frame header
16167c478bd9Sstevel@tonic-gate * length field.
16177c478bd9Sstevel@tonic-gate */
16187c478bd9Sstevel@tonic-gate if ((sap <= ETHERMTU) || (stp->ss_sap == 0))
16197c478bd9Sstevel@tonic-gate headerp->ether_type = (msgsize(mp) -
16207c478bd9Sstevel@tonic-gate sizeof (struct ether_header));
16217c478bd9Sstevel@tonic-gate else
16227c478bd9Sstevel@tonic-gate headerp->ether_type = sap;
16237c478bd9Sstevel@tonic-gate
16247c478bd9Sstevel@tonic-gate /*
16257c478bd9Sstevel@tonic-gate * The data transfer code requires only READ access (idn_wput_data).
16267c478bd9Sstevel@tonic-gate */
16277c478bd9Sstevel@tonic-gate rw_downgrade(&stp->ss_rwlock);
16287c478bd9Sstevel@tonic-gate (void) idndl_start(wq, mp, sip);
16297c478bd9Sstevel@tonic-gate }
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate int
16327c478bd9Sstevel@tonic-gate idndl_start(queue_t *wq, register mblk_t *mp, register struct idn *sip)
16337c478bd9Sstevel@tonic-gate {
16347c478bd9Sstevel@tonic-gate int rv = 0;
16357c478bd9Sstevel@tonic-gate int flags;
16367c478bd9Sstevel@tonic-gate int broadcast = 0;
16377c478bd9Sstevel@tonic-gate int goagain = 0;
16387c478bd9Sstevel@tonic-gate int goqueue = 0;
16397c478bd9Sstevel@tonic-gate int msgcount;
16407c478bd9Sstevel@tonic-gate char channel;
16417c478bd9Sstevel@tonic-gate mblk_t *nmp = NULL;
16427c478bd9Sstevel@tonic-gate int domid;
16437c478bd9Sstevel@tonic-gate domainset_t domset;
16447c478bd9Sstevel@tonic-gate idn_netaddr_t netaddr;
16457c478bd9Sstevel@tonic-gate struct idnstr *stp;
16467c478bd9Sstevel@tonic-gate struct ether_header *ehp;
16477c478bd9Sstevel@tonic-gate procname_t proc = "idndl_start";
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate ASSERT(DB_TYPE(mp) == M_DATA);
16507c478bd9Sstevel@tonic-gate
16517c478bd9Sstevel@tonic-gate stp = (struct idnstr *)wq->q_ptr;
16527c478bd9Sstevel@tonic-gate ASSERT(sip == stp->ss_sip);
16537c478bd9Sstevel@tonic-gate flags = sip->si_flags;
16547c478bd9Sstevel@tonic-gate channel = (char)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL];
16557c478bd9Sstevel@tonic-gate
16567c478bd9Sstevel@tonic-gate ASSERT(RW_READ_HELD(&stp->ss_rwlock));
16577c478bd9Sstevel@tonic-gate
16587c478bd9Sstevel@tonic-gate if ((flags & (IDNRUNNING|IDNPROMISC)) != IDNRUNNING) {
16597c478bd9Sstevel@tonic-gate if (!(flags & IDNRUNNING))
16607c478bd9Sstevel@tonic-gate goto requeue;
16617c478bd9Sstevel@tonic-gate }
16627c478bd9Sstevel@tonic-gate
16637c478bd9Sstevel@tonic-gate /*
16647c478bd9Sstevel@tonic-gate * Translate an IDN ethernet address into a domainid
16657c478bd9Sstevel@tonic-gate * and idnaddr.
16667c478bd9Sstevel@tonic-gate */
16677c478bd9Sstevel@tonic-gate ehp = (struct ether_header *)mp->b_rptr;
16687c478bd9Sstevel@tonic-gate domid = IDNDL_ETHER2DOMAIN(&ehp->ether_dhost);
16697c478bd9Sstevel@tonic-gate
16707c478bd9Sstevel@tonic-gate /*
16717c478bd9Sstevel@tonic-gate * update MIB II statistics
16727c478bd9Sstevel@tonic-gate */
16737c478bd9Sstevel@tonic-gate BUMP_OutNUcast(sip, ehp);
16747c478bd9Sstevel@tonic-gate
16757c478bd9Sstevel@tonic-gate PR_DLPI("%s: ether %x:%x:%x:%x:%x:%x (domid = %d)\n",
16767c478bd9Sstevel@tonic-gate proc, ehp->ether_dhost.ether_addr_octet[0],
16777c478bd9Sstevel@tonic-gate ehp->ether_dhost.ether_addr_octet[1],
16787c478bd9Sstevel@tonic-gate ehp->ether_dhost.ether_addr_octet[2],
16797c478bd9Sstevel@tonic-gate ehp->ether_dhost.ether_addr_octet[3],
16807c478bd9Sstevel@tonic-gate ehp->ether_dhost.ether_addr_octet[4],
16817c478bd9Sstevel@tonic-gate ehp->ether_dhost.ether_addr_octet[5],
16827c478bd9Sstevel@tonic-gate domid);
16837c478bd9Sstevel@tonic-gate
16847c478bd9Sstevel@tonic-gate netaddr.net.chan = channel;
16857c478bd9Sstevel@tonic-gate PR_DLPI("%s: source channel = %d\n", proc, (int)channel);
16867c478bd9Sstevel@tonic-gate
16877c478bd9Sstevel@tonic-gate if ((ether_cmp(&ehp->ether_dhost, ðerbroadcastaddr) == 0) ||
16887c478bd9Sstevel@tonic-gate IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost)) {
16897c478bd9Sstevel@tonic-gate /*
16907c478bd9Sstevel@tonic-gate * Caller wants to broadcast!
16917c478bd9Sstevel@tonic-gate * XXX - Send to everybody but ourself???
16927c478bd9Sstevel@tonic-gate */
16937c478bd9Sstevel@tonic-gate PR_DLPI("%s: broadcast/multicast requested!!!\n", proc);
16947c478bd9Sstevel@tonic-gate domset = ~DOMAINSET(idn.localid);
16957c478bd9Sstevel@tonic-gate broadcast = 1;
16967c478bd9Sstevel@tonic-gate netaddr.net.netid = IDN_BROADCAST_ALLNETID;
16977c478bd9Sstevel@tonic-gate if ((flags & IDNPROMISC) &&
16987c478bd9Sstevel@tonic-gate ((nmp = copymsg(mp)) == NULL)) {
16997c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_allocbfail);
17007c478bd9Sstevel@tonic-gate }
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate } else if (domid != IDN_NIL_DOMID) {
17037c478bd9Sstevel@tonic-gate domset = DOMAINSET(domid);
17047c478bd9Sstevel@tonic-gate netaddr.net.netid = idn_domain[domid].dnetid;
17057c478bd9Sstevel@tonic-gate if ((flags & IDNPROMISC) &&
17067c478bd9Sstevel@tonic-gate ((nmp = copymsg(mp)) == NULL)) {
17077c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_allocbfail);
17087c478bd9Sstevel@tonic-gate }
17097c478bd9Sstevel@tonic-gate } else {
17107c478bd9Sstevel@tonic-gate #ifdef DEBUG
17117c478bd9Sstevel@tonic-gate int netid;
17127c478bd9Sstevel@tonic-gate
17137c478bd9Sstevel@tonic-gate netid = (int)
17147c478bd9Sstevel@tonic-gate ehp->ether_dhost.ether_addr_octet[IDNETHER_NETID];
17157c478bd9Sstevel@tonic-gate PR_DLPI("%s: no domain found for netid 0x%x\n",
17167c478bd9Sstevel@tonic-gate proc, netid);
17177c478bd9Sstevel@tonic-gate #endif /* DEBUG */
17187c478bd9Sstevel@tonic-gate goto bad;
17197c478bd9Sstevel@tonic-gate }
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate PR_DLPI("%s: target domainset = 0x%x\n", proc, domset);
17227c478bd9Sstevel@tonic-gate
17237c478bd9Sstevel@tonic-gate if ((domset == 0) && (domid == IDN_NIL_DOMID)) {
17247c478bd9Sstevel@tonic-gate PR_DLPI("%s: not connected to any domains!! Bailing\n",
17257c478bd9Sstevel@tonic-gate proc);
17267c478bd9Sstevel@tonic-gate goto bad;
17277c478bd9Sstevel@tonic-gate }
17287c478bd9Sstevel@tonic-gate /*
17297c478bd9Sstevel@tonic-gate * XXX - Need to find a better way to handle broadcasting.
17307c478bd9Sstevel@tonic-gate * Should be able to take advantage of the fact that
17317c478bd9Sstevel@tonic-gate * we can broadcast XDC's (xdc_some). Need to use
17327c478bd9Sstevel@tonic-gate * atomic counter (semaphore) instead of binary
17337c478bd9Sstevel@tonic-gate * "owner" flag, or perhaps domain specific owner bytes.
17347c478bd9Sstevel@tonic-gate *
17357c478bd9Sstevel@tonic-gate * Transfer the data.
17367c478bd9Sstevel@tonic-gate */
17377c478bd9Sstevel@tonic-gate msgcount = 0;
17387c478bd9Sstevel@tonic-gate if (!broadcast)
17397c478bd9Sstevel@tonic-gate goto noloop;
17407c478bd9Sstevel@tonic-gate
17417c478bd9Sstevel@tonic-gate for (domid = 0; domid < MAX_DOMAINS; domid++) {
17427c478bd9Sstevel@tonic-gate if (!DOMAIN_IN_SET(domset, domid))
17437c478bd9Sstevel@tonic-gate continue;
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate noloop:
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate if (idn_domain[domid].dcpu == IDN_NIL_DCPU) {
17487c478bd9Sstevel@tonic-gate if (broadcast)
17497c478bd9Sstevel@tonic-gate continue;
17507c478bd9Sstevel@tonic-gate else
17517c478bd9Sstevel@tonic-gate break;
17527c478bd9Sstevel@tonic-gate }
17537c478bd9Sstevel@tonic-gate
17547c478bd9Sstevel@tonic-gate rv = idn_send_data(domid, netaddr, wq, mp);
17557c478bd9Sstevel@tonic-gate
17567c478bd9Sstevel@tonic-gate switch (rv) {
17577c478bd9Sstevel@tonic-gate case IDNXMIT_LOOP: /* handled in loopback */
17587c478bd9Sstevel@tonic-gate msgcount++;
17597c478bd9Sstevel@tonic-gate break;
17607c478bd9Sstevel@tonic-gate
17617c478bd9Sstevel@tonic-gate case IDNXMIT_OKAY: /* handled, okay to free */
17627c478bd9Sstevel@tonic-gate msgcount++;
17637c478bd9Sstevel@tonic-gate break;
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate case IDNXMIT_RETRY:
17667c478bd9Sstevel@tonic-gate if (!broadcast)
17677c478bd9Sstevel@tonic-gate goto tryagain;
17687c478bd9Sstevel@tonic-gate goagain++;
17697c478bd9Sstevel@tonic-gate break;
17707c478bd9Sstevel@tonic-gate
17717c478bd9Sstevel@tonic-gate case IDNXMIT_REQUEUE:
17727c478bd9Sstevel@tonic-gate if (!broadcast)
17737c478bd9Sstevel@tonic-gate goto requeue;
17747c478bd9Sstevel@tonic-gate goqueue++;
17757c478bd9Sstevel@tonic-gate break;
17767c478bd9Sstevel@tonic-gate
17777c478bd9Sstevel@tonic-gate default:
17787c478bd9Sstevel@tonic-gate if (!broadcast)
17797c478bd9Sstevel@tonic-gate goto bad;
17807c478bd9Sstevel@tonic-gate break;
17817c478bd9Sstevel@tonic-gate }
17827c478bd9Sstevel@tonic-gate if (!broadcast)
17837c478bd9Sstevel@tonic-gate break;
17847c478bd9Sstevel@tonic-gate }
17857c478bd9Sstevel@tonic-gate
17867c478bd9Sstevel@tonic-gate if (msgcount == 0)
17877c478bd9Sstevel@tonic-gate if (goqueue)
17887c478bd9Sstevel@tonic-gate goto requeue;
17897c478bd9Sstevel@tonic-gate else if (goagain)
17907c478bd9Sstevel@tonic-gate goto tryagain;
17917c478bd9Sstevel@tonic-gate else
17927c478bd9Sstevel@tonic-gate goto bad;
17937c478bd9Sstevel@tonic-gate
17947c478bd9Sstevel@tonic-gate if ((flags & IDNPROMISC) && nmp)
17957c478bd9Sstevel@tonic-gate idndl_sendup(sip, nmp, idndl_paccept);
17967c478bd9Sstevel@tonic-gate
17977c478bd9Sstevel@tonic-gate freemsg(mp);
17987c478bd9Sstevel@tonic-gate
17997c478bd9Sstevel@tonic-gate PR_DLPI("%s: successful transmit to domainset 0x%x.\n",
18007c478bd9Sstevel@tonic-gate proc, domset);
18017c478bd9Sstevel@tonic-gate
18027c478bd9Sstevel@tonic-gate return (0);
18037c478bd9Sstevel@tonic-gate
18047c478bd9Sstevel@tonic-gate bad:
18057c478bd9Sstevel@tonic-gate PR_DLPI("%s: bad transmission to domainset 0x%x, dropping msg.\n",
18067c478bd9Sstevel@tonic-gate proc, domset);
18077c478bd9Sstevel@tonic-gate if (nmp)
18087c478bd9Sstevel@tonic-gate freemsg(nmp);
18097c478bd9Sstevel@tonic-gate freemsg(mp);
18107c478bd9Sstevel@tonic-gate qenable(wq);
18117c478bd9Sstevel@tonic-gate return (1);
18127c478bd9Sstevel@tonic-gate
18137c478bd9Sstevel@tonic-gate requeue:
18147c478bd9Sstevel@tonic-gate PR_DLPI("%s: requeue for domainset 0x%x, no qenable\n",
18157c478bd9Sstevel@tonic-gate proc, domset);
18167c478bd9Sstevel@tonic-gate if (nmp)
18177c478bd9Sstevel@tonic-gate freemsg(nmp);
18187c478bd9Sstevel@tonic-gate if (putbq(wq, mp) == 0)
18197c478bd9Sstevel@tonic-gate freemsg(mp);
18207c478bd9Sstevel@tonic-gate return (1);
18217c478bd9Sstevel@tonic-gate
18227c478bd9Sstevel@tonic-gate tryagain:
18237c478bd9Sstevel@tonic-gate PR_DLPI("%s: try again to domainset 0x%x, putbq.\n",
18247c478bd9Sstevel@tonic-gate proc, domset);
18257c478bd9Sstevel@tonic-gate if (nmp)
18267c478bd9Sstevel@tonic-gate freemsg(nmp);
18277c478bd9Sstevel@tonic-gate if (putbq(wq, mp) == 0)
18287c478bd9Sstevel@tonic-gate freemsg(mp);
18297c478bd9Sstevel@tonic-gate qenable(wq);
18307c478bd9Sstevel@tonic-gate return (1);
18317c478bd9Sstevel@tonic-gate }
18327c478bd9Sstevel@tonic-gate
18337c478bd9Sstevel@tonic-gate /*
18347c478bd9Sstevel@tonic-gate * Called by: idnh_recv_data, idn_recv_mboxdata.
18357c478bd9Sstevel@tonic-gate */
18367c478bd9Sstevel@tonic-gate void
18377c478bd9Sstevel@tonic-gate idndl_read(struct idn *sip, mblk_t *mp)
18387c478bd9Sstevel@tonic-gate {
18397c478bd9Sstevel@tonic-gate struct ether_header *ehp;
18407c478bd9Sstevel@tonic-gate queue_t *ip4q;
18417c478bd9Sstevel@tonic-gate queue_t *ip6q;
18427c478bd9Sstevel@tonic-gate int pktlen;
18437c478bd9Sstevel@tonic-gate procname_t proc = "idndl_read";
18447c478bd9Sstevel@tonic-gate
1845bf30efa4Smathue PR_DLPI("%s: incoming msgsize = %lu, msgdsize = %lu\n",
18467c478bd9Sstevel@tonic-gate proc, msgsize(mp), msgdsize(mp));
18477c478bd9Sstevel@tonic-gate
18487c478bd9Sstevel@tonic-gate ehp = (struct ether_header *)mp->b_rptr;
18497c478bd9Sstevel@tonic-gate if (sip == NULL)
18507c478bd9Sstevel@tonic-gate sip = IDNDL_ETHER2SIP(&ehp->ether_dhost);
18517c478bd9Sstevel@tonic-gate if (sip == NULL) {
18527c478bd9Sstevel@tonic-gate /*
18537c478bd9Sstevel@tonic-gate * If the sip is NULL, then I don't have a connection
18547c478bd9Sstevel@tonic-gate * for this network. No point in sending the message
18557c478bd9Sstevel@tonic-gate * up.
18567c478bd9Sstevel@tonic-gate */
18577c478bd9Sstevel@tonic-gate PR_DLPI("%s: no plumbing to send message through.\n",
18587c478bd9Sstevel@tonic-gate proc);
18597c478bd9Sstevel@tonic-gate freemsg(mp);
18607c478bd9Sstevel@tonic-gate return;
18617c478bd9Sstevel@tonic-gate }
18627c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_ipackets);
18637c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_ipackets64);
18647c478bd9Sstevel@tonic-gate /*
18657c478bd9Sstevel@tonic-gate * update MIB II statistics
18667c478bd9Sstevel@tonic-gate */
18677c478bd9Sstevel@tonic-gate pktlen = mp->b_wptr - mp->b_rptr;
18687c478bd9Sstevel@tonic-gate BUMP_InNUcast(sip, ehp);
18697c478bd9Sstevel@tonic-gate IDN_KSTAT_ADD(sip, si_rcvbytes, pktlen);
18707c478bd9Sstevel@tonic-gate IDN_KSTAT_ADD(sip, si_rbytes64, (uint64_t)pktlen);
18717c478bd9Sstevel@tonic-gate
18727c478bd9Sstevel@tonic-gate ip4q = sip->si_ip4q;
18737c478bd9Sstevel@tonic-gate ip6q = sip->si_ip6q;
18747c478bd9Sstevel@tonic-gate
18757c478bd9Sstevel@tonic-gate if (IS_ETHERTYPE_IPV4(ehp->ether_type) &&
18767c478bd9Sstevel@tonic-gate !IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost) &&
18777c478bd9Sstevel@tonic-gate ip4q &&
18787c478bd9Sstevel@tonic-gate canputnext(ip4q)) {
18797c478bd9Sstevel@tonic-gate mp->b_rptr += sizeof (struct ether_header);
18807c478bd9Sstevel@tonic-gate (void) putnext(ip4q, mp);
18817c478bd9Sstevel@tonic-gate /*LINTED*/
18827c478bd9Sstevel@tonic-gate } else if (IS_ETHERTYPE_IPV6(ehp->ether_type) &&
18837c478bd9Sstevel@tonic-gate !IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost) &&
18847c478bd9Sstevel@tonic-gate ip6q &&
18857c478bd9Sstevel@tonic-gate canputnext(ip6q)) {
18867c478bd9Sstevel@tonic-gate mp->b_rptr += sizeof (struct ether_header);
18877c478bd9Sstevel@tonic-gate (void) putnext(ip6q, mp);
18887c478bd9Sstevel@tonic-gate } else {
18897c478bd9Sstevel@tonic-gate /*
18907c478bd9Sstevel@tonic-gate * Strip the PADs for 802.3
18917c478bd9Sstevel@tonic-gate */
18927c478bd9Sstevel@tonic-gate pktlen = ehp->ether_type + sizeof (struct ether_header);
18937c478bd9Sstevel@tonic-gate PR_DLPI("%s: stripping PADs for 802.3 (pktlen=%d)\n",
18947c478bd9Sstevel@tonic-gate proc, pktlen);
18957c478bd9Sstevel@tonic-gate if (pktlen < ETHERMIN)
18967c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + pktlen;
18977c478bd9Sstevel@tonic-gate idndl_sendup(sip, mp, idndl_accept);
18987c478bd9Sstevel@tonic-gate }
18997c478bd9Sstevel@tonic-gate }
19007c478bd9Sstevel@tonic-gate
19017c478bd9Sstevel@tonic-gate int
19027c478bd9Sstevel@tonic-gate idndl_init(struct idn *sip)
19037c478bd9Sstevel@tonic-gate {
19047c478bd9Sstevel@tonic-gate struct idnstr *stp;
19057c478bd9Sstevel@tonic-gate
19067c478bd9Sstevel@tonic-gate if (sip->si_flags & IDNSUSPENDED)
19077c478bd9Sstevel@tonic-gate (void) ddi_dev_is_needed(sip->si_dip, 0, 1);
19087c478bd9Sstevel@tonic-gate
19097c478bd9Sstevel@tonic-gate sip->si_flags = 0;
19107c478bd9Sstevel@tonic-gate sip->si_wantw = 0;
19117c478bd9Sstevel@tonic-gate
19127c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_inits);
19137c478bd9Sstevel@tonic-gate
19147c478bd9Sstevel@tonic-gate rw_enter(&idn.struprwlock, RW_WRITER);
19157c478bd9Sstevel@tonic-gate
19167c478bd9Sstevel@tonic-gate for (stp = idn.strup; stp; stp = stp->ss_nextp) {
19177c478bd9Sstevel@tonic-gate if ((stp->ss_sip == sip) && (stp->ss_flags & IDNSALLPHYS)) {
19187c478bd9Sstevel@tonic-gate sip->si_flags |= IDNPROMISC;
19197c478bd9Sstevel@tonic-gate break;
19207c478bd9Sstevel@tonic-gate }
19217c478bd9Sstevel@tonic-gate }
19227c478bd9Sstevel@tonic-gate
19237c478bd9Sstevel@tonic-gate sip->si_flags |= IDNRUNNING;
19247c478bd9Sstevel@tonic-gate
19257c478bd9Sstevel@tonic-gate mutex_enter(&idn.sipwenlock);
19267c478bd9Sstevel@tonic-gate idndl_wenable(sip);
19277c478bd9Sstevel@tonic-gate mutex_exit(&idn.sipwenlock);
19287c478bd9Sstevel@tonic-gate
19297c478bd9Sstevel@tonic-gate rw_exit(&idn.struprwlock);
19307c478bd9Sstevel@tonic-gate
19317c478bd9Sstevel@tonic-gate return (!(sip->si_flags & IDNRUNNING));
19327c478bd9Sstevel@tonic-gate }
19337c478bd9Sstevel@tonic-gate
19347c478bd9Sstevel@tonic-gate void
19357c478bd9Sstevel@tonic-gate idndl_uninit(struct idn *sip)
19367c478bd9Sstevel@tonic-gate {
19377c478bd9Sstevel@tonic-gate int channel;
19387c478bd9Sstevel@tonic-gate procname_t proc = "idndl_uninit";
19397c478bd9Sstevel@tonic-gate
19407c478bd9Sstevel@tonic-gate sip->si_flags &= ~IDNRUNNING;
19417c478bd9Sstevel@tonic-gate
19427c478bd9Sstevel@tonic-gate channel = (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL];
19437c478bd9Sstevel@tonic-gate PR_DLPI("%s: IP SAP, uninit channel %d\n", proc, channel);
19447c478bd9Sstevel@tonic-gate /*
19457c478bd9Sstevel@tonic-gate * A uninit is a hard close of an interface.
19467c478bd9Sstevel@tonic-gate */
19477c478bd9Sstevel@tonic-gate idn_close_channel(channel, IDNCHAN_HARD_CLOSE);
19487c478bd9Sstevel@tonic-gate }
19497c478bd9Sstevel@tonic-gate
19507c478bd9Sstevel@tonic-gate /*
19517c478bd9Sstevel@tonic-gate * Send packet upstream.
19527c478bd9Sstevel@tonic-gate * Assume mp->b_rptr points to ether_header.
19537c478bd9Sstevel@tonic-gate */
19547c478bd9Sstevel@tonic-gate void
19557c478bd9Sstevel@tonic-gate idndl_sendup(struct idn *sip, mblk_t *mp, struct idnstr *(*acceptfunc)())
19567c478bd9Sstevel@tonic-gate {
19577c478bd9Sstevel@tonic-gate int type;
19587c478bd9Sstevel@tonic-gate struct ether_addr *dhostp, *shostp;
19597c478bd9Sstevel@tonic-gate struct idnstr *stp, *nstp;
19607c478bd9Sstevel@tonic-gate mblk_t *nmp;
19617c478bd9Sstevel@tonic-gate ulong_t isgroupaddr;
19627c478bd9Sstevel@tonic-gate
19637c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_START, "idnsendup start");
19647c478bd9Sstevel@tonic-gate
19657c478bd9Sstevel@tonic-gate dhostp = &((struct ether_header *)mp->b_rptr)->ether_dhost;
19667c478bd9Sstevel@tonic-gate shostp = &((struct ether_header *)mp->b_rptr)->ether_shost;
19677c478bd9Sstevel@tonic-gate type = ((struct ether_header *)mp->b_rptr)->ether_type;
19687c478bd9Sstevel@tonic-gate
19697c478bd9Sstevel@tonic-gate isgroupaddr = IDNDL_ADDR_IS_MULTICAST(dhostp);
19707c478bd9Sstevel@tonic-gate
19717c478bd9Sstevel@tonic-gate /*
19727c478bd9Sstevel@tonic-gate * While holding a reader lock on the linked list of streams structures,
19737c478bd9Sstevel@tonic-gate * attempt to match the address criteria for each stream
19747c478bd9Sstevel@tonic-gate * and pass up the raw M_DATA ("fastpath") or a DL_UNITDATA_IND.
19757c478bd9Sstevel@tonic-gate */
19767c478bd9Sstevel@tonic-gate
19777c478bd9Sstevel@tonic-gate rw_enter(&idn.struprwlock, RW_READER);
19787c478bd9Sstevel@tonic-gate
19797c478bd9Sstevel@tonic-gate if ((stp = (*acceptfunc)(idn.strup, sip, type, dhostp)) == NULL) {
19807c478bd9Sstevel@tonic-gate rw_exit(&idn.struprwlock);
19817c478bd9Sstevel@tonic-gate freemsg(mp);
19827c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_END, "idnsendup end");
19837c478bd9Sstevel@tonic-gate return;
19847c478bd9Sstevel@tonic-gate }
19857c478bd9Sstevel@tonic-gate
19867c478bd9Sstevel@tonic-gate /*
19877c478bd9Sstevel@tonic-gate * Loop on matching open streams until (*acceptfunc)() returns NULL.
19887c478bd9Sstevel@tonic-gate */
19897c478bd9Sstevel@tonic-gate for (; nstp = (*acceptfunc)(stp->ss_nextp, sip, type, dhostp);
19907c478bd9Sstevel@tonic-gate stp = nstp) {
19917c478bd9Sstevel@tonic-gate
19927c478bd9Sstevel@tonic-gate if (canputnext(stp->ss_rq) == 0) {
19937c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_nocanput);
19947c478bd9Sstevel@tonic-gate continue;
19957c478bd9Sstevel@tonic-gate }
19967c478bd9Sstevel@tonic-gate if ((nmp = dupmsg(mp)) == NULL)
19977c478bd9Sstevel@tonic-gate nmp = copymsg(mp);
19987c478bd9Sstevel@tonic-gate if (nmp) {
19997c478bd9Sstevel@tonic-gate if ((stp->ss_flags & IDNSFAST) && !isgroupaddr) {
20007c478bd9Sstevel@tonic-gate nmp->b_rptr += sizeof (struct ether_header);
20017c478bd9Sstevel@tonic-gate (void) putnext(stp->ss_rq, nmp);
20027c478bd9Sstevel@tonic-gate } else if (stp->ss_flags & IDNSRAW) {
20037c478bd9Sstevel@tonic-gate (void) putnext(stp->ss_rq, nmp);
20047c478bd9Sstevel@tonic-gate } else if ((nmp = idndl_addudind(sip, nmp, shostp,
20057c478bd9Sstevel@tonic-gate dhostp, type, isgroupaddr))) {
20067c478bd9Sstevel@tonic-gate (void) putnext(stp->ss_rq, nmp);
20077c478bd9Sstevel@tonic-gate }
20087c478bd9Sstevel@tonic-gate } else {
20097c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_allocbfail);
20107c478bd9Sstevel@tonic-gate }
20117c478bd9Sstevel@tonic-gate }
20127c478bd9Sstevel@tonic-gate
20137c478bd9Sstevel@tonic-gate
20147c478bd9Sstevel@tonic-gate /*
20157c478bd9Sstevel@tonic-gate * Do the last one.
20167c478bd9Sstevel@tonic-gate */
20177c478bd9Sstevel@tonic-gate if (canputnext(stp->ss_rq)) {
20187c478bd9Sstevel@tonic-gate if ((stp->ss_flags & IDNSFAST) && !isgroupaddr) {
20197c478bd9Sstevel@tonic-gate mp->b_rptr += sizeof (struct ether_header);
20207c478bd9Sstevel@tonic-gate (void) putnext(stp->ss_rq, mp);
20217c478bd9Sstevel@tonic-gate } else if (stp->ss_flags & IDNSRAW) {
20227c478bd9Sstevel@tonic-gate (void) putnext(stp->ss_rq, mp);
20237c478bd9Sstevel@tonic-gate } else if ((mp = idndl_addudind(sip, mp, shostp, dhostp,
20247c478bd9Sstevel@tonic-gate type, isgroupaddr))) {
20257c478bd9Sstevel@tonic-gate (void) putnext(stp->ss_rq, mp);
20267c478bd9Sstevel@tonic-gate }
20277c478bd9Sstevel@tonic-gate } else {
20287c478bd9Sstevel@tonic-gate freemsg(mp);
20297c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_nocanput);
20307c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_norcvbuf); /* MIB II */
20317c478bd9Sstevel@tonic-gate }
20327c478bd9Sstevel@tonic-gate
20337c478bd9Sstevel@tonic-gate rw_exit(&idn.struprwlock);
20347c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_END, "idnsendup end");
20357c478bd9Sstevel@tonic-gate }
20367c478bd9Sstevel@tonic-gate
20377c478bd9Sstevel@tonic-gate /*
20387c478bd9Sstevel@tonic-gate * Test upstream destination sap and address match.
20397c478bd9Sstevel@tonic-gate */
20407c478bd9Sstevel@tonic-gate struct idnstr *
20417c478bd9Sstevel@tonic-gate idndl_accept(register struct idnstr *stp, register struct idn *sip,
20427c478bd9Sstevel@tonic-gate int type, struct ether_addr *addrp)
20437c478bd9Sstevel@tonic-gate {
20447c478bd9Sstevel@tonic-gate t_uscalar_t sap;
20457c478bd9Sstevel@tonic-gate uint_t flags;
20467c478bd9Sstevel@tonic-gate
20477c478bd9Sstevel@tonic-gate for (; stp; stp = stp->ss_nextp) {
20487c478bd9Sstevel@tonic-gate sap = stp->ss_sap;
20497c478bd9Sstevel@tonic-gate flags = stp->ss_flags;
20507c478bd9Sstevel@tonic-gate
20517c478bd9Sstevel@tonic-gate if ((stp->ss_sip == sip) && IDNSAPMATCH(sap, type, flags))
20527c478bd9Sstevel@tonic-gate if ((ether_cmp(addrp, &sip->si_ouraddr) == 0) ||
20537c478bd9Sstevel@tonic-gate (ether_cmp(addrp, ðerbroadcastaddr) == 0) ||
20547c478bd9Sstevel@tonic-gate (flags & IDNSALLPHYS) ||
20557c478bd9Sstevel@tonic-gate idndl_mcmatch(stp, addrp))
20567c478bd9Sstevel@tonic-gate return (stp);
20577c478bd9Sstevel@tonic-gate }
20587c478bd9Sstevel@tonic-gate
20597c478bd9Sstevel@tonic-gate return (NULL);
20607c478bd9Sstevel@tonic-gate }
20617c478bd9Sstevel@tonic-gate
20627c478bd9Sstevel@tonic-gate /*
20637c478bd9Sstevel@tonic-gate * Test upstream destination sap and address match for IDNSALLPHYS only.
20647c478bd9Sstevel@tonic-gate */
20657c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
20667c478bd9Sstevel@tonic-gate struct idnstr *
20677c478bd9Sstevel@tonic-gate idndl_paccept(register struct idnstr *stp, register struct idn *sip,
20687c478bd9Sstevel@tonic-gate int type, struct ether_addr *addrp)
20697c478bd9Sstevel@tonic-gate {
20707c478bd9Sstevel@tonic-gate t_uscalar_t sap;
20717c478bd9Sstevel@tonic-gate uint_t flags;
20727c478bd9Sstevel@tonic-gate
20737c478bd9Sstevel@tonic-gate for (; stp; stp = stp->ss_nextp) {
20747c478bd9Sstevel@tonic-gate sap = stp->ss_sap;
20757c478bd9Sstevel@tonic-gate flags = stp->ss_flags;
20767c478bd9Sstevel@tonic-gate
20777c478bd9Sstevel@tonic-gate if ((stp->ss_sip == sip) &&
20787c478bd9Sstevel@tonic-gate IDNSAPMATCH(sap, type, flags) &&
20797c478bd9Sstevel@tonic-gate (flags & IDNSALLPHYS))
20807c478bd9Sstevel@tonic-gate return (stp);
20817c478bd9Sstevel@tonic-gate }
20827c478bd9Sstevel@tonic-gate
20837c478bd9Sstevel@tonic-gate return (NULL);
20847c478bd9Sstevel@tonic-gate }
20857c478bd9Sstevel@tonic-gate
20867c478bd9Sstevel@tonic-gate /*
20877c478bd9Sstevel@tonic-gate * Set or clear the device ipq pointer.
20887c478bd9Sstevel@tonic-gate * Assumes IPv4 and IPv6 are IDNSFAST.
20897c478bd9Sstevel@tonic-gate */
20907c478bd9Sstevel@tonic-gate static void
20917c478bd9Sstevel@tonic-gate idndl_setipq(struct idn *sip)
20927c478bd9Sstevel@tonic-gate {
20937c478bd9Sstevel@tonic-gate struct idnstr *stp;
20947c478bd9Sstevel@tonic-gate int ok4 = 1;
20957c478bd9Sstevel@tonic-gate int ok6 = 1;
20967c478bd9Sstevel@tonic-gate queue_t *ip4q = NULL;
20977c478bd9Sstevel@tonic-gate queue_t *ip6q = NULL;
20987c478bd9Sstevel@tonic-gate
20997c478bd9Sstevel@tonic-gate rw_enter(&idn.struprwlock, RW_READER);
21007c478bd9Sstevel@tonic-gate
21017c478bd9Sstevel@tonic-gate for (stp = idn.strup; stp; stp = stp->ss_nextp) {
21027c478bd9Sstevel@tonic-gate if (stp->ss_sip == sip) {
21037c478bd9Sstevel@tonic-gate if (stp->ss_flags & (IDNSALLPHYS|IDNSALLSAP)) {
21047c478bd9Sstevel@tonic-gate ok4 = 0;
21057c478bd9Sstevel@tonic-gate ok6 = 0;
21067c478bd9Sstevel@tonic-gate break;
21077c478bd9Sstevel@tonic-gate }
21087c478bd9Sstevel@tonic-gate if (IS_ETHERTYPE_IPV4(stp->ss_sap)) {
21097c478bd9Sstevel@tonic-gate if (ip4q == NULL)
21107c478bd9Sstevel@tonic-gate ip4q = stp->ss_rq;
21117c478bd9Sstevel@tonic-gate else
21127c478bd9Sstevel@tonic-gate ok4 = 0;
21137c478bd9Sstevel@tonic-gate /*LINTED*/
21147c478bd9Sstevel@tonic-gate } else if (IS_ETHERTYPE_IPV6(stp->ss_sap)) {
21157c478bd9Sstevel@tonic-gate if (ip6q == NULL)
21167c478bd9Sstevel@tonic-gate ip6q = stp->ss_rq;
21177c478bd9Sstevel@tonic-gate else
21187c478bd9Sstevel@tonic-gate ok6 = 0;
21197c478bd9Sstevel@tonic-gate }
21207c478bd9Sstevel@tonic-gate }
21217c478bd9Sstevel@tonic-gate }
21227c478bd9Sstevel@tonic-gate
21237c478bd9Sstevel@tonic-gate rw_exit(&idn.struprwlock);
21247c478bd9Sstevel@tonic-gate
21257c478bd9Sstevel@tonic-gate if (ok4)
21267c478bd9Sstevel@tonic-gate sip->si_ip4q = ip4q;
21277c478bd9Sstevel@tonic-gate else
21287c478bd9Sstevel@tonic-gate sip->si_ip4q = NULL;
21297c478bd9Sstevel@tonic-gate if (ok6)
21307c478bd9Sstevel@tonic-gate sip->si_ip6q = ip6q;
21317c478bd9Sstevel@tonic-gate else
21327c478bd9Sstevel@tonic-gate sip->si_ip6q = NULL;
21337c478bd9Sstevel@tonic-gate }
21347c478bd9Sstevel@tonic-gate
21357c478bd9Sstevel@tonic-gate /*
21367c478bd9Sstevel@tonic-gate * Prefix msg with a DL_UNITDATA_IND mblk and return the new msg.
21377c478bd9Sstevel@tonic-gate */
21387c478bd9Sstevel@tonic-gate static mblk_t *
21397c478bd9Sstevel@tonic-gate idndl_addudind(struct idn *sip, mblk_t *mp,
21407c478bd9Sstevel@tonic-gate struct ether_addr *shostp, struct ether_addr *dhostp,
21417c478bd9Sstevel@tonic-gate int type, ulong_t isgroupaddr)
21427c478bd9Sstevel@tonic-gate {
21437c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *dludindp;
21447c478bd9Sstevel@tonic-gate struct idndladdr *dlap;
21457c478bd9Sstevel@tonic-gate mblk_t *nmp;
21467c478bd9Sstevel@tonic-gate int size;
21477c478bd9Sstevel@tonic-gate
21487c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_START, "idndl_addudind start");
21497c478bd9Sstevel@tonic-gate
21507c478bd9Sstevel@tonic-gate mp->b_rptr += sizeof (struct ether_header);
21517c478bd9Sstevel@tonic-gate
21527c478bd9Sstevel@tonic-gate /*
21537c478bd9Sstevel@tonic-gate * Allocate an M_PROTO mblk for the DL_UNITDATA_IND.
21547c478bd9Sstevel@tonic-gate */
21557c478bd9Sstevel@tonic-gate size = sizeof (dl_unitdata_ind_t) + IDNADDRL + IDNADDRL;
21567c478bd9Sstevel@tonic-gate nmp = allocb(IDNROUNDUP(IDNHEADROOM + size, sizeof (double)), BPRI_LO);
21577c478bd9Sstevel@tonic-gate if (nmp == NULL) {
21587c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_allocbfail);
21597c478bd9Sstevel@tonic-gate IDN_KSTAT_INC(sip, si_ierrors);
21607c478bd9Sstevel@tonic-gate if (idn_debug)
21617c478bd9Sstevel@tonic-gate serror(sip->si_dip, 451, "allocb failed");
21627c478bd9Sstevel@tonic-gate freemsg(mp);
21637c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_END, "idndl_addudind end");
21647c478bd9Sstevel@tonic-gate return (NULL);
21657c478bd9Sstevel@tonic-gate }
21667c478bd9Sstevel@tonic-gate DB_TYPE(nmp) = M_PROTO;
21677c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_datap->db_lim;
21687c478bd9Sstevel@tonic-gate nmp->b_rptr = nmp->b_wptr - size;
21697c478bd9Sstevel@tonic-gate
21707c478bd9Sstevel@tonic-gate /*
21717c478bd9Sstevel@tonic-gate * Construct a DL_UNITDATA_IND primitive.
21727c478bd9Sstevel@tonic-gate */
21737c478bd9Sstevel@tonic-gate dludindp = (dl_unitdata_ind_t *)nmp->b_rptr;
21747c478bd9Sstevel@tonic-gate dludindp->dl_primitive = DL_UNITDATA_IND;
21757c478bd9Sstevel@tonic-gate dludindp->dl_dest_addr_length = IDNADDRL;
21767c478bd9Sstevel@tonic-gate dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
21777c478bd9Sstevel@tonic-gate dludindp->dl_src_addr_length = IDNADDRL;
21787c478bd9Sstevel@tonic-gate dludindp->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + IDNADDRL;
21797c478bd9Sstevel@tonic-gate dludindp->dl_group_address = isgroupaddr;
21807c478bd9Sstevel@tonic-gate
21817c478bd9Sstevel@tonic-gate dlap = (struct idndladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t));
21827c478bd9Sstevel@tonic-gate ether_copy(dhostp, &dlap->dl_phys);
21837c478bd9Sstevel@tonic-gate dlap->dl_sap = (ushort_t)type;
21847c478bd9Sstevel@tonic-gate
21857c478bd9Sstevel@tonic-gate dlap = (struct idndladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t)
21867c478bd9Sstevel@tonic-gate + IDNADDRL);
21877c478bd9Sstevel@tonic-gate ether_copy(shostp, &dlap->dl_phys);
21887c478bd9Sstevel@tonic-gate dlap->dl_sap = (ushort_t)type;
21897c478bd9Sstevel@tonic-gate
21907c478bd9Sstevel@tonic-gate /*
21917c478bd9Sstevel@tonic-gate * Link the M_PROTO and M_DATA together.
21927c478bd9Sstevel@tonic-gate */
21937c478bd9Sstevel@tonic-gate nmp->b_cont = mp;
21947c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_END, "idndl_addudind end");
21957c478bd9Sstevel@tonic-gate return (nmp);
21967c478bd9Sstevel@tonic-gate }
21977c478bd9Sstevel@tonic-gate
21987c478bd9Sstevel@tonic-gate /*
21997c478bd9Sstevel@tonic-gate * Return TRUE if the given multicast address is one
22007c478bd9Sstevel@tonic-gate * of those that this particular Stream is interested in.
22017c478bd9Sstevel@tonic-gate */
22027c478bd9Sstevel@tonic-gate static int
22037c478bd9Sstevel@tonic-gate idndl_mcmatch(register struct idnstr *stp, register struct ether_addr *addrp)
22047c478bd9Sstevel@tonic-gate {
22057c478bd9Sstevel@tonic-gate register struct ether_addr *mctab;
22067c478bd9Sstevel@tonic-gate register int mccount;
22077c478bd9Sstevel@tonic-gate register int i;
22087c478bd9Sstevel@tonic-gate
22097c478bd9Sstevel@tonic-gate /*
22107c478bd9Sstevel@tonic-gate * Return FALSE if not a multicast address.
22117c478bd9Sstevel@tonic-gate */
22127c478bd9Sstevel@tonic-gate if (!IDNDL_ADDR_IS_MULTICAST(addrp))
22137c478bd9Sstevel@tonic-gate return (0);
22147c478bd9Sstevel@tonic-gate
22157c478bd9Sstevel@tonic-gate /*
22167c478bd9Sstevel@tonic-gate * Check if all multicasts have been enabled for this Stream
22177c478bd9Sstevel@tonic-gate */
22187c478bd9Sstevel@tonic-gate if (stp->ss_flags & IDNSALLMULTI)
22197c478bd9Sstevel@tonic-gate return (1);
22207c478bd9Sstevel@tonic-gate
22217c478bd9Sstevel@tonic-gate /*
22227c478bd9Sstevel@tonic-gate * Return FALSE if no multicast addresses enabled for this Stream.
22237c478bd9Sstevel@tonic-gate */
22247c478bd9Sstevel@tonic-gate if (stp->ss_mccount == 0)
22257c478bd9Sstevel@tonic-gate return (0);
22267c478bd9Sstevel@tonic-gate
22277c478bd9Sstevel@tonic-gate /*
22287c478bd9Sstevel@tonic-gate * Otherwise, find it in the table.
22297c478bd9Sstevel@tonic-gate */
22307c478bd9Sstevel@tonic-gate
22317c478bd9Sstevel@tonic-gate mccount = stp->ss_mccount;
22327c478bd9Sstevel@tonic-gate mctab = stp->ss_mctab;
22337c478bd9Sstevel@tonic-gate
22347c478bd9Sstevel@tonic-gate for (i = 0; i < mccount; i++)
22357c478bd9Sstevel@tonic-gate if (!ether_cmp(addrp, &mctab[i]))
22367c478bd9Sstevel@tonic-gate return (1);
22377c478bd9Sstevel@tonic-gate
22387c478bd9Sstevel@tonic-gate return (0);
22397c478bd9Sstevel@tonic-gate }
22407c478bd9Sstevel@tonic-gate
22417c478bd9Sstevel@tonic-gate /*
22427c478bd9Sstevel@tonic-gate * Start xmit on any msgs previously enqueued on any write queues.
22437c478bd9Sstevel@tonic-gate * If the caller passes NULL, then we need to check all
22447c478bd9Sstevel@tonic-gate * our interfaces.
22457c478bd9Sstevel@tonic-gate */
22467c478bd9Sstevel@tonic-gate void
22477c478bd9Sstevel@tonic-gate idndl_wenable(struct idn *sip)
22487c478bd9Sstevel@tonic-gate {
22497c478bd9Sstevel@tonic-gate struct idnstr *stp;
22507c478bd9Sstevel@tonic-gate queue_t *wq;
22517c478bd9Sstevel@tonic-gate
22527c478bd9Sstevel@tonic-gate /*
22537c478bd9Sstevel@tonic-gate * Order of wantw accesses is important.
22547c478bd9Sstevel@tonic-gate */
22557c478bd9Sstevel@tonic-gate ASSERT((sip == NULL) ? RW_LOCK_HELD(&idn.struprwlock) : 1);
22567c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&idn.sipwenlock));
22577c478bd9Sstevel@tonic-gate
22587c478bd9Sstevel@tonic-gate do {
22597c478bd9Sstevel@tonic-gate if (sip)
22607c478bd9Sstevel@tonic-gate sip->si_wantw = 0;
22617c478bd9Sstevel@tonic-gate for (stp = idn.strup; stp; stp = stp->ss_nextp) {
22627c478bd9Sstevel@tonic-gate if ((!sip || (stp->ss_sip == sip)) &&
22637c478bd9Sstevel@tonic-gate stp->ss_rq && ((wq = WR(stp->ss_rq))->q_first))
22647c478bd9Sstevel@tonic-gate qenable(wq);
22657c478bd9Sstevel@tonic-gate }
22667c478bd9Sstevel@tonic-gate } while (sip && sip->si_wantw);
22677c478bd9Sstevel@tonic-gate }
22687c478bd9Sstevel@tonic-gate
22697c478bd9Sstevel@tonic-gate /*VARARGS*/
22707c478bd9Sstevel@tonic-gate static void
22717c478bd9Sstevel@tonic-gate serror(dev_info_t *dip, int idnerr, char *fmt, ...)
22727c478bd9Sstevel@tonic-gate {
22737c478bd9Sstevel@tonic-gate static long last;
22747c478bd9Sstevel@tonic-gate static char *lastfmt;
22757c478bd9Sstevel@tonic-gate char msg_buffer[255];
22767c478bd9Sstevel@tonic-gate va_list ap;
22777c478bd9Sstevel@tonic-gate time_t now;
22787c478bd9Sstevel@tonic-gate
22797c478bd9Sstevel@tonic-gate /*
22807c478bd9Sstevel@tonic-gate * Don't print same error message too often.
22817c478bd9Sstevel@tonic-gate */
22827c478bd9Sstevel@tonic-gate now = gethrestime_sec();
22837c478bd9Sstevel@tonic-gate if ((last == (now & ~1)) && (lastfmt == fmt))
22847c478bd9Sstevel@tonic-gate return;
22857c478bd9Sstevel@tonic-gate
22867c478bd9Sstevel@tonic-gate last = now & ~1;
22877c478bd9Sstevel@tonic-gate lastfmt = fmt;
22887c478bd9Sstevel@tonic-gate
22897c478bd9Sstevel@tonic-gate va_start(ap, fmt);
22907c478bd9Sstevel@tonic-gate (void) vsprintf(msg_buffer, fmt, ap);
22917c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "IDN: %d: %s%d: %s\n",
22927c478bd9Sstevel@tonic-gate idnerr, ddi_get_name(dip),
22937c478bd9Sstevel@tonic-gate ddi_get_instance(dip), msg_buffer);
22947c478bd9Sstevel@tonic-gate va_end(ap);
22957c478bd9Sstevel@tonic-gate }
2296