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 * 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 * 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 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 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 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 * 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 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 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 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