1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * llc1 - an LLC Class 1 MUX compatible with SunConnect LLC2 uses DLPI 31*7c478bd9Sstevel@tonic-gate * interface. Its primary use is to support RPL for network boot but can be 32*7c478bd9Sstevel@tonic-gate * used by other protocols. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/devops.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/ksynch.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/ethernet.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 53*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> /* for byteorder macros on machines that define them */ 54*7c478bd9Sstevel@tonic-gate #include <sys/llc1.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * function prototypes, etc. 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate static int llc1_open(queue_t *q, dev_t *dev, int flag, int sflag, 62*7c478bd9Sstevel@tonic-gate cred_t *cred); 63*7c478bd9Sstevel@tonic-gate static int llc1_close(queue_t *q, int flag, cred_t *cred); 64*7c478bd9Sstevel@tonic-gate static int llc1_uwput(queue_t *q, mblk_t *mp); 65*7c478bd9Sstevel@tonic-gate static int llc1_uwsrv(queue_t *q); 66*7c478bd9Sstevel@tonic-gate static int llc1_lrsrv(queue_t *q); 67*7c478bd9Sstevel@tonic-gate static int llc1_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 68*7c478bd9Sstevel@tonic-gate static int llc1_detach(dev_info_t *dev, ddi_detach_cmd_t cmd); 69*7c478bd9Sstevel@tonic-gate static int llc1_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd); 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate static mblk_t *llc1_form_udata(llc1_t *lld, llc_mac_info_t *macinfo, 72*7c478bd9Sstevel@tonic-gate mblk_t *mp); 73*7c478bd9Sstevel@tonic-gate static mblk_t *llc1_xid_reply(llc_mac_info_t *macinfo, mblk_t *mp, int sap); 74*7c478bd9Sstevel@tonic-gate static mblk_t *llc1_xid_ind_con(llc1_t *lld, llc_mac_info_t *macinfo, 75*7c478bd9Sstevel@tonic-gate mblk_t *mp); 76*7c478bd9Sstevel@tonic-gate static mblk_t *llc1_test_reply(llc_mac_info_t *macinfo, mblk_t *mp, int sap); 77*7c478bd9Sstevel@tonic-gate static mblk_t *llc1_test_ind_con(llc1_t *lld, llc_mac_info_t *macinfo, 78*7c478bd9Sstevel@tonic-gate mblk_t *mp); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate static void llc1_ioctl(queue_t *q, mblk_t *mp); 81*7c478bd9Sstevel@tonic-gate static void llc1_recv(llc_mac_info_t *macinfo, mblk_t *mp); 82*7c478bd9Sstevel@tonic-gate static void llc1_req_raw(llc_mac_info_t *macinfo); 83*7c478bd9Sstevel@tonic-gate static void llc1_find_waiting(llc_mac_info_t *macinfo, mblk_t *mp, long prim); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate static minor_t llc1_findminor(llc1dev_t *device); 86*7c478bd9Sstevel@tonic-gate static void llc1_send_disable_multi(llc_mac_info_t *, llc_mcast_t *); 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static void llc1insque(void *elem, void *pred); 89*7c478bd9Sstevel@tonic-gate static void llc1remque(void *arg); 90*7c478bd9Sstevel@tonic-gate static void llc1error(); 91*7c478bd9Sstevel@tonic-gate static int llc1_subs_unbind(void); 92*7c478bd9Sstevel@tonic-gate static void llc1_init_kstat(llc_mac_info_t *macinfo); 93*7c478bd9Sstevel@tonic-gate static void llc1_uninit_kstat(llc_mac_info_t *macinfo); 94*7c478bd9Sstevel@tonic-gate static int llc1_update_kstat(kstat_t *ksp, int rw); 95*7c478bd9Sstevel@tonic-gate static int llc1_broadcast(struct ether_addr *addr, llc_mac_info_t *macinfo); 96*7c478bd9Sstevel@tonic-gate static int llc1_unbind(queue_t *q, mblk_t *mp); 97*7c478bd9Sstevel@tonic-gate static int llc1_subs_bind(queue_t *q, mblk_t *mp); 98*7c478bd9Sstevel@tonic-gate static int llc1_unitdata(queue_t *q, mblk_t *mp); 99*7c478bd9Sstevel@tonic-gate static int llc1_inforeq(queue_t *q, mblk_t *mp); 100*7c478bd9Sstevel@tonic-gate static int llc1attach(queue_t *q, mblk_t *mp); 101*7c478bd9Sstevel@tonic-gate static void llc1_send_bindreq(llc_mac_info_t *macinfo); 102*7c478bd9Sstevel@tonic-gate static int llc1_req_info(queue_t *q); 103*7c478bd9Sstevel@tonic-gate static int llc1_cmds(queue_t *q, mblk_t *mp); 104*7c478bd9Sstevel@tonic-gate static int llc1_setppa(struct ll_snioc *snioc); 105*7c478bd9Sstevel@tonic-gate static int llc1_getppa(llc_mac_info_t *macinfo, struct ll_snioc *snioc); 106*7c478bd9Sstevel@tonic-gate static int llc1_bind(queue_t *q, mblk_t *mp); 107*7c478bd9Sstevel@tonic-gate static int llc1unattach(queue_t *q, mblk_t *mp); 108*7c478bd9Sstevel@tonic-gate static int llc1_enable_multi(queue_t *q, mblk_t *mp); 109*7c478bd9Sstevel@tonic-gate static int llc1_disable_multi(queue_t *q, mblk_t *mp); 110*7c478bd9Sstevel@tonic-gate static int llc1_xid_req_res(queue_t *q, mblk_t *mp, int req_or_res); 111*7c478bd9Sstevel@tonic-gate static int llc1_test_req_res(queue_t *q, mblk_t *mp, int req_or_res); 112*7c478bd9Sstevel@tonic-gate static int llc1_local(struct ether_addr *addr, llc_mac_info_t *macinfo); 113*7c478bd9Sstevel@tonic-gate static int llc1_snap_match(llc1_t *lld, struct snaphdr *snap); 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate /* 116*7c478bd9Sstevel@tonic-gate * the standard streams glue for defining the type of streams entity and the 117*7c478bd9Sstevel@tonic-gate * operational parameters. 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate static struct module_info llc1_minfo = { 121*7c478bd9Sstevel@tonic-gate LLC1IDNUM, 122*7c478bd9Sstevel@tonic-gate "llc1", 123*7c478bd9Sstevel@tonic-gate 0, 124*7c478bd9Sstevel@tonic-gate LLC1_DEFMAX, 125*7c478bd9Sstevel@tonic-gate LLC1_HIWATER, /* high water mark */ 126*7c478bd9Sstevel@tonic-gate LLC1_LOWATER, /* low water mark */ 127*7c478bd9Sstevel@tonic-gate }; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate static struct qinit llc1_rint = { 130*7c478bd9Sstevel@tonic-gate NULL, 131*7c478bd9Sstevel@tonic-gate NULL, 132*7c478bd9Sstevel@tonic-gate llc1_open, 133*7c478bd9Sstevel@tonic-gate llc1_close, 134*7c478bd9Sstevel@tonic-gate NULL, 135*7c478bd9Sstevel@tonic-gate &llc1_minfo, 136*7c478bd9Sstevel@tonic-gate NULL 137*7c478bd9Sstevel@tonic-gate }; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate static struct qinit llc1_wint = { 140*7c478bd9Sstevel@tonic-gate llc1_uwput, 141*7c478bd9Sstevel@tonic-gate llc1_uwsrv, 142*7c478bd9Sstevel@tonic-gate NULL, 143*7c478bd9Sstevel@tonic-gate NULL, 144*7c478bd9Sstevel@tonic-gate NULL, 145*7c478bd9Sstevel@tonic-gate &llc1_minfo, 146*7c478bd9Sstevel@tonic-gate NULL 147*7c478bd9Sstevel@tonic-gate }; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate static struct qinit llc1_muxrint = { 150*7c478bd9Sstevel@tonic-gate putq, 151*7c478bd9Sstevel@tonic-gate llc1_lrsrv, 152*7c478bd9Sstevel@tonic-gate NULL, 153*7c478bd9Sstevel@tonic-gate NULL, 154*7c478bd9Sstevel@tonic-gate NULL, 155*7c478bd9Sstevel@tonic-gate &llc1_minfo, 156*7c478bd9Sstevel@tonic-gate NULL 157*7c478bd9Sstevel@tonic-gate }; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate static struct qinit llc1_muxwint = { 160*7c478bd9Sstevel@tonic-gate NULL, 161*7c478bd9Sstevel@tonic-gate NULL, 162*7c478bd9Sstevel@tonic-gate NULL, 163*7c478bd9Sstevel@tonic-gate NULL, 164*7c478bd9Sstevel@tonic-gate NULL, 165*7c478bd9Sstevel@tonic-gate &llc1_minfo, 166*7c478bd9Sstevel@tonic-gate NULL 167*7c478bd9Sstevel@tonic-gate }; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate struct streamtab llc1_info = { 170*7c478bd9Sstevel@tonic-gate &llc1_rint, 171*7c478bd9Sstevel@tonic-gate &llc1_wint, 172*7c478bd9Sstevel@tonic-gate &llc1_muxrint, 173*7c478bd9Sstevel@tonic-gate &llc1_muxwint 174*7c478bd9Sstevel@tonic-gate }; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * loadable module/driver wrapper this allows llc1 to be unloaded later 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate #if !defined(BUILD_STATIC) 181*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* define the "ops" structure for a STREAMS driver */ 184*7c478bd9Sstevel@tonic-gate DDI_DEFINE_STREAM_OPS(llc1_ops, nulldev, nulldev, llc1_attach, 185*7c478bd9Sstevel@tonic-gate llc1_detach, nodev, llc1_getinfo, D_MP | D_MTPERMOD, &llc1_info); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 191*7c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a driver */ 192*7c478bd9Sstevel@tonic-gate "LLC Class 1 Driver %I%", 193*7c478bd9Sstevel@tonic-gate &llc1_ops, /* driver ops */ 194*7c478bd9Sstevel@tonic-gate }; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 197*7c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 198*7c478bd9Sstevel@tonic-gate }; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate int 201*7c478bd9Sstevel@tonic-gate _init(void) 202*7c478bd9Sstevel@tonic-gate { 203*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate int 207*7c478bd9Sstevel@tonic-gate _fini(void) 208*7c478bd9Sstevel@tonic-gate { 209*7c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate int 213*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate #endif 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 221*7c478bd9Sstevel@tonic-gate extern int llc1_debug = 0x0; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate #endif 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * Allocate and zero-out "number" structures each of type "structure" in 227*7c478bd9Sstevel@tonic-gate * kernel memory. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate #define GETSTRUCT(structure, number) \ 230*7c478bd9Sstevel@tonic-gate (kmem_zalloc(sizeof (structure) * (number), KM_NOSLEEP)) 231*7c478bd9Sstevel@tonic-gate #define GETBUF(structure, size) \ 232*7c478bd9Sstevel@tonic-gate (kmem_zalloc(size, KM_NOSLEEP)) 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate static struct llc1device llc1_device_list; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * llc1_attach - init time attach support When the hardware specific attach 238*7c478bd9Sstevel@tonic-gate * is called, it must call this procedure with the device class structure 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate static int 242*7c478bd9Sstevel@tonic-gate llc1_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate if (cmd != DDI_ATTACH) 245*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* 248*7c478bd9Sstevel@tonic-gate * there isn't any hardware but we do need to initialize things 249*7c478bd9Sstevel@tonic-gate */ 250*7c478bd9Sstevel@tonic-gate if (!(llc1_device_list.llc1_status & LLC1_ATTACHED)) { 251*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_status |= LLC1_ATTACHED; 252*7c478bd9Sstevel@tonic-gate rw_init(&llc1_device_list.llc1_rwlock, NULL, RW_DRIVER, NULL); 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate /* make sure minor device lists are initialized */ 255*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_str_next = 256*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_str_prev = 257*7c478bd9Sstevel@tonic-gate (llc1_t *)&llc1_device_list.llc1_str_next; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* make sure device list is initialized */ 260*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_mac_next = 261*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_mac_prev = 262*7c478bd9Sstevel@tonic-gate (llc_mac_info_t *)&llc1_device_list.llc1_mac_next; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate /* 266*7c478bd9Sstevel@tonic-gate * now do all the DDI stuff necessary 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate ddi_set_driver_private(devinfo, &llc1_device_list); 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * create the file system device node 273*7c478bd9Sstevel@tonic-gate */ 274*7c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(devinfo, "llc1", S_IFCHR, 275*7c478bd9Sstevel@tonic-gate 0, DDI_PSEUDO, CLONE_DEV) == DDI_FAILURE) { 276*7c478bd9Sstevel@tonic-gate llc1error(devinfo, "ddi_create_minor_node failed"); 277*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(devinfo, NULL); 278*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_multisize = ddi_getprop(DDI_DEV_T_NONE, 281*7c478bd9Sstevel@tonic-gate devinfo, 0, "multisize", 0); 282*7c478bd9Sstevel@tonic-gate if (llc1_device_list.llc1_multisize == 0) 283*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_multisize = LLC1_MAX_MULTICAST; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate ddi_report_dev(devinfo); 286*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * llc1_detach standard kernel interface routine 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate static int 294*7c478bd9Sstevel@tonic-gate llc1_detach(dev_info_t *dev, ddi_detach_cmd_t cmd) 295*7c478bd9Sstevel@tonic-gate { 296*7c478bd9Sstevel@tonic-gate if (cmd != DDI_DETACH) { 297*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate if (llc1_device_list.llc1_ndevice > 0) 300*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 301*7c478bd9Sstevel@tonic-gate /* remove all mutex and locks */ 302*7c478bd9Sstevel@tonic-gate rw_destroy(&llc1_device_list.llc1_rwlock); 303*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_status = 0; /* no longer attached */ 304*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dev, NULL); 305*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * llc1_devinfo(dev, cmd, arg, result) standard kernel devinfo lookup 310*7c478bd9Sstevel@tonic-gate * function 311*7c478bd9Sstevel@tonic-gate */ 312*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 313*7c478bd9Sstevel@tonic-gate static int 314*7c478bd9Sstevel@tonic-gate llc1_getinfo(dev_info_t *dev, ddi_info_cmd_t cmd, void *arg, void **result) 315*7c478bd9Sstevel@tonic-gate { 316*7c478bd9Sstevel@tonic-gate int error; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate switch (cmd) { 319*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 320*7c478bd9Sstevel@tonic-gate if (dev == NULL) { 321*7c478bd9Sstevel@tonic-gate error = DDI_FAILURE; 322*7c478bd9Sstevel@tonic-gate } else { 323*7c478bd9Sstevel@tonic-gate *result = (void *)dev; 324*7c478bd9Sstevel@tonic-gate error = DDI_SUCCESS; 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate break; 327*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 328*7c478bd9Sstevel@tonic-gate *result = (void *)0; 329*7c478bd9Sstevel@tonic-gate error = DDI_SUCCESS; 330*7c478bd9Sstevel@tonic-gate break; 331*7c478bd9Sstevel@tonic-gate default: 332*7c478bd9Sstevel@tonic-gate error = DDI_FAILURE; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate return (error); 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* 338*7c478bd9Sstevel@tonic-gate * llc1_open() 339*7c478bd9Sstevel@tonic-gate * LLC1 open routine, called when device is opened by the user 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 343*7c478bd9Sstevel@tonic-gate static int 344*7c478bd9Sstevel@tonic-gate llc1_open(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred) 345*7c478bd9Sstevel@tonic-gate { 346*7c478bd9Sstevel@tonic-gate llc1_t *llc1; 347*7c478bd9Sstevel@tonic-gate minor_t minordev; 348*7c478bd9Sstevel@tonic-gate int status = 0; 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate ASSERT(q); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Stream already open, sucess. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate if (q->q_ptr) 356*7c478bd9Sstevel@tonic-gate return (0); 357*7c478bd9Sstevel@tonic-gate /* 358*7c478bd9Sstevel@tonic-gate * Serialize access through open/close this will serialize across all 359*7c478bd9Sstevel@tonic-gate * llc1 devices, but open and close are not frequent so should not 360*7c478bd9Sstevel@tonic-gate * induce much, if any delay. 361*7c478bd9Sstevel@tonic-gate */ 362*7c478bd9Sstevel@tonic-gate rw_enter(&llc1_device_list.llc1_rwlock, RW_WRITER); 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate if (sflag == CLONEOPEN) { 365*7c478bd9Sstevel@tonic-gate /* need to find a minor dev */ 366*7c478bd9Sstevel@tonic-gate minordev = llc1_findminor(&llc1_device_list); 367*7c478bd9Sstevel@tonic-gate if (minordev == 0) { 368*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 369*7c478bd9Sstevel@tonic-gate return (ENXIO); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate *dev = makedevice(getmajor(*dev), minordev); 372*7c478bd9Sstevel@tonic-gate } else { 373*7c478bd9Sstevel@tonic-gate minordev = getminor (*dev); 374*7c478bd9Sstevel@tonic-gate if ((minordev > MAXMIN32) || (minordev == 0)) { 375*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 376*7c478bd9Sstevel@tonic-gate return (ENXIO); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * get a per-stream structure and link things together so we 382*7c478bd9Sstevel@tonic-gate * can easily find them later. 383*7c478bd9Sstevel@tonic-gate */ 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate llc1 = kmem_zalloc(sizeof (llc1_t), KM_SLEEP); 386*7c478bd9Sstevel@tonic-gate llc1->llc_qptr = q; 387*7c478bd9Sstevel@tonic-gate WR(q)->q_ptr = q->q_ptr = (caddr_t)llc1; 388*7c478bd9Sstevel@tonic-gate /* 389*7c478bd9Sstevel@tonic-gate * fill in the structure and state info 390*7c478bd9Sstevel@tonic-gate */ 391*7c478bd9Sstevel@tonic-gate llc1->llc_state = DL_UNATTACHED; 392*7c478bd9Sstevel@tonic-gate llc1->llc_style = DL_STYLE2; 393*7c478bd9Sstevel@tonic-gate llc1->llc_minor = minordev; 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate mutex_init(&llc1->llc_lock, NULL, MUTEX_DRIVER, NULL); 396*7c478bd9Sstevel@tonic-gate llc1insque(llc1, llc1_device_list.llc1_str_prev); 397*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 398*7c478bd9Sstevel@tonic-gate qprocson(q); /* start the queues running */ 399*7c478bd9Sstevel@tonic-gate return (status); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate /* 403*7c478bd9Sstevel@tonic-gate * llc1_close(q) 404*7c478bd9Sstevel@tonic-gate * normal stream close call checks current status and cleans up 405*7c478bd9Sstevel@tonic-gate * data structures that were dynamically allocated 406*7c478bd9Sstevel@tonic-gate */ 407*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 408*7c478bd9Sstevel@tonic-gate static int 409*7c478bd9Sstevel@tonic-gate llc1_close(queue_t *q, int flag, cred_t *cred) 410*7c478bd9Sstevel@tonic-gate { 411*7c478bd9Sstevel@tonic-gate llc1_t *llc1; 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate ASSERT(q); 414*7c478bd9Sstevel@tonic-gate ASSERT(q->q_ptr); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate qprocsoff(q); 417*7c478bd9Sstevel@tonic-gate llc1 = (llc1_t *)q->q_ptr; 418*7c478bd9Sstevel@tonic-gate rw_enter(&llc1_device_list.llc1_rwlock, RW_WRITER); 419*7c478bd9Sstevel@tonic-gate /* completely disassociate the stream from the device */ 420*7c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate (void) llc1remque(llc1); /* remove from active list */ 423*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate mutex_enter(&llc1->llc_lock); 426*7c478bd9Sstevel@tonic-gate if (llc1->llc_state == DL_IDLE || llc1->llc_state == DL_UNBOUND) { 427*7c478bd9Sstevel@tonic-gate llc1->llc_state = DL_UNBOUND; /* force the issue */ 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate if (llc1->llc_mcast != NULL) { 431*7c478bd9Sstevel@tonic-gate int i; 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate for (i = 0; i < llc1_device_list.llc1_multisize; i++) { 434*7c478bd9Sstevel@tonic-gate llc_mcast_t *mcast; 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate if ((mcast = llc1->llc_mcast[i]) != NULL) { 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * disable from stream and possibly 439*7c478bd9Sstevel@tonic-gate * lower stream 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate if (llc1->llc_mac_info && 442*7c478bd9Sstevel@tonic-gate llc1->llc_mac_info->llcp_flags & 443*7c478bd9Sstevel@tonic-gate LLC1_AVAILABLE) 444*7c478bd9Sstevel@tonic-gate llc1_send_disable_multi( 445*7c478bd9Sstevel@tonic-gate llc1->llc_mac_info, 446*7c478bd9Sstevel@tonic-gate mcast); 447*7c478bd9Sstevel@tonic-gate llc1->llc_mcast[i] = NULL; 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate kmem_free(llc1->llc_mcast, 451*7c478bd9Sstevel@tonic-gate sizeof (llc_mcast_t *) * llc1->llc_multicnt); 452*7c478bd9Sstevel@tonic-gate llc1->llc_mcast = NULL; 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate llc1->llc_state = DL_UNATTACHED; 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate mutex_exit(&llc1->llc_lock); 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate mutex_destroy(&llc1->llc_lock); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate kmem_free(llc1, sizeof (llc1_t)); 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate return (0); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate /* 466*7c478bd9Sstevel@tonic-gate * llc1_uwput() 467*7c478bd9Sstevel@tonic-gate * general llc stream write put routine. Receives ioctl's from 468*7c478bd9Sstevel@tonic-gate * user level and data from upper modules and processes them immediately. 469*7c478bd9Sstevel@tonic-gate * M_PROTO/M_PCPROTO are queued for later processing by the service 470*7c478bd9Sstevel@tonic-gate * procedure. 471*7c478bd9Sstevel@tonic-gate */ 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate static int 474*7c478bd9Sstevel@tonic-gate llc1_uwput(queue_t *q, mblk_t *mp) 475*7c478bd9Sstevel@tonic-gate { 476*7c478bd9Sstevel@tonic-gate llc1_t *ld = (llc1_t *)(q->q_ptr); 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 479*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 480*7c478bd9Sstevel@tonic-gate printf("llc1_wput(%x %x): type %d\n", q, mp, DB_TYPE(mp)); 481*7c478bd9Sstevel@tonic-gate #endif 482*7c478bd9Sstevel@tonic-gate switch (DB_TYPE(mp)) { 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate case M_IOCTL: /* no waiting in ioctl's */ 485*7c478bd9Sstevel@tonic-gate (void) llc1_ioctl(q, mp); 486*7c478bd9Sstevel@tonic-gate break; 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate case M_FLUSH: /* canonical flush handling */ 489*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 490*7c478bd9Sstevel@tonic-gate flushq(q, 0); 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) { 493*7c478bd9Sstevel@tonic-gate flushq(RD(q), 0); 494*7c478bd9Sstevel@tonic-gate *mp->b_rptr &= ~FLUSHW; 495*7c478bd9Sstevel@tonic-gate qreply(q, mp); 496*7c478bd9Sstevel@tonic-gate } else 497*7c478bd9Sstevel@tonic-gate freemsg(mp); 498*7c478bd9Sstevel@tonic-gate break; 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate /* for now, we will always queue */ 501*7c478bd9Sstevel@tonic-gate case M_PROTO: 502*7c478bd9Sstevel@tonic-gate case M_PCPROTO: 503*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 504*7c478bd9Sstevel@tonic-gate break; 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate case M_DATA: 507*7c478bd9Sstevel@tonic-gate /* fast data / raw support */ 508*7c478bd9Sstevel@tonic-gate if ((ld->llc_flags & (LLC_RAW | LLC_FAST)) == 0 || 509*7c478bd9Sstevel@tonic-gate ld->llc_state != DL_IDLE) { 510*7c478bd9Sstevel@tonic-gate (void) merror(q, mp, EPROTO); 511*7c478bd9Sstevel@tonic-gate break; 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate /* need to do further checking */ 514*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 515*7c478bd9Sstevel@tonic-gate break; 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate default: 518*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 519*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCERRS) 520*7c478bd9Sstevel@tonic-gate printf("llc1: Unexpected packet type from queue: %d\n", 521*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type); 522*7c478bd9Sstevel@tonic-gate #endif 523*7c478bd9Sstevel@tonic-gate freemsg(mp); 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate return (0); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * llc1_lrsrv() 530*7c478bd9Sstevel@tonic-gate * called when data is put into the service queue from below. 531*7c478bd9Sstevel@tonic-gate * Determines additional processing that might be needed and sends the data 532*7c478bd9Sstevel@tonic-gate * upstream in the form of a Data Indication packet. 533*7c478bd9Sstevel@tonic-gate */ 534*7c478bd9Sstevel@tonic-gate static int 535*7c478bd9Sstevel@tonic-gate llc1_lrsrv(queue_t *q) 536*7c478bd9Sstevel@tonic-gate { 537*7c478bd9Sstevel@tonic-gate mblk_t *mp; 538*7c478bd9Sstevel@tonic-gate union DL_primitives *prim; 539*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo = (llc_mac_info_t *)q->q_ptr; 540*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 543*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 544*7c478bd9Sstevel@tonic-gate printf("llc1_rsrv(%x)\n", q); 545*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCRECV) { 546*7c478bd9Sstevel@tonic-gate printf("llc1_lrsrv: q=%x macinfo=%x", q, macinfo); 547*7c478bd9Sstevel@tonic-gate if (macinfo == NULL) { 548*7c478bd9Sstevel@tonic-gate printf("NULL macinfo"); 549*7c478bd9Sstevel@tonic-gate panic("null macinfo in lrsrv"); 550*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate printf("\n"); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate #endif 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate /* 557*7c478bd9Sstevel@tonic-gate * determine where message goes, then call the proper handler 558*7c478bd9Sstevel@tonic-gate */ 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 561*7c478bd9Sstevel@tonic-gate switch (DB_TYPE(mp)) { 562*7c478bd9Sstevel@tonic-gate case M_PROTO: 563*7c478bd9Sstevel@tonic-gate case M_PCPROTO: 564*7c478bd9Sstevel@tonic-gate prim = (union DL_primitives *)mp->b_rptr; 565*7c478bd9Sstevel@tonic-gate /* only some primitives ever get passed through */ 566*7c478bd9Sstevel@tonic-gate switch (prim->dl_primitive) { 567*7c478bd9Sstevel@tonic-gate case DL_INFO_ACK: 568*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_flags & LLC1_LINKED) { 569*7c478bd9Sstevel@tonic-gate /* 570*7c478bd9Sstevel@tonic-gate * we are in the midst of completing 571*7c478bd9Sstevel@tonic-gate * the I_LINK/I_PLINK and needed this 572*7c478bd9Sstevel@tonic-gate * info 573*7c478bd9Sstevel@tonic-gate */ 574*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags &= ~LLC1_LINKED; 575*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags |= LLC1_AVAILABLE; 576*7c478bd9Sstevel@tonic-gate macinfo->llcp_maxpkt = 577*7c478bd9Sstevel@tonic-gate prim->info_ack.dl_max_sdu; 578*7c478bd9Sstevel@tonic-gate macinfo->llcp_minpkt = 579*7c478bd9Sstevel@tonic-gate prim->info_ack.dl_min_sdu; 580*7c478bd9Sstevel@tonic-gate macinfo->llcp_type = 581*7c478bd9Sstevel@tonic-gate prim->info_ack.dl_mac_type; 582*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_type == DL_ETHER) { 583*7c478bd9Sstevel@tonic-gate macinfo->llcp_type = DL_CSMACD; 584*7c478bd9Sstevel@tonic-gate /* 585*7c478bd9Sstevel@tonic-gate * size of max header 586*7c478bd9Sstevel@tonic-gate * (including SNAP) 587*7c478bd9Sstevel@tonic-gate */ 588*7c478bd9Sstevel@tonic-gate macinfo->llcp_maxpkt -= 8; 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen = 591*7c478bd9Sstevel@tonic-gate prim->info_ack.dl_addr_length - 592*7c478bd9Sstevel@tonic-gate ABS(prim->info_ack.dl_sap_length); 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr + 595*7c478bd9Sstevel@tonic-gate prim->info_ack.dl_addr_offset, 596*7c478bd9Sstevel@tonic-gate macinfo->llcp_macaddr, 597*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 598*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr + 599*7c478bd9Sstevel@tonic-gate prim->info_ack.dl_brdcst_addr_offset, 600*7c478bd9Sstevel@tonic-gate macinfo->llcp_broadcast, 601*7c478bd9Sstevel@tonic-gate prim->info_ack.dl_brdcst_addr_length); 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate if (prim->info_ack.dl_current_state == 604*7c478bd9Sstevel@tonic-gate DL_UNBOUND) 605*7c478bd9Sstevel@tonic-gate llc1_send_bindreq(macinfo); 606*7c478bd9Sstevel@tonic-gate freemsg(mp); 607*7c478bd9Sstevel@tonic-gate /* 608*7c478bd9Sstevel@tonic-gate * need to put the lower stream into 609*7c478bd9Sstevel@tonic-gate * DLRAW mode. Currently only DL_ETHER 610*7c478bd9Sstevel@tonic-gate * or DL_CSMACD 611*7c478bd9Sstevel@tonic-gate */ 612*7c478bd9Sstevel@tonic-gate switch (macinfo->llcp_type) { 613*7c478bd9Sstevel@tonic-gate case DL_ETHER: 614*7c478bd9Sstevel@tonic-gate case DL_CSMACD: 615*7c478bd9Sstevel@tonic-gate /* 616*7c478bd9Sstevel@tonic-gate * raw mode is optimal so ask 617*7c478bd9Sstevel@tonic-gate * for it * we might not get 618*7c478bd9Sstevel@tonic-gate * it but that's OK 619*7c478bd9Sstevel@tonic-gate */ 620*7c478bd9Sstevel@tonic-gate llc1_req_raw(macinfo); 621*7c478bd9Sstevel@tonic-gate break; 622*7c478bd9Sstevel@tonic-gate default: 623*7c478bd9Sstevel@tonic-gate /* 624*7c478bd9Sstevel@tonic-gate * don't want raw mode so don't 625*7c478bd9Sstevel@tonic-gate * ask for it 626*7c478bd9Sstevel@tonic-gate */ 627*7c478bd9Sstevel@tonic-gate break; 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate } else { 630*7c478bd9Sstevel@tonic-gate if (prim->info_ack.dl_current_state == 631*7c478bd9Sstevel@tonic-gate DL_IDLE) 632*7c478bd9Sstevel@tonic-gate /* address was wrong before */ 633*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr + 634*7c478bd9Sstevel@tonic-gate prim->info_ack.dl_addr_offset, 635*7c478bd9Sstevel@tonic-gate macinfo->llcp_macaddr, 636*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 637*7c478bd9Sstevel@tonic-gate freemsg(mp); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate break; 640*7c478bd9Sstevel@tonic-gate case DL_BIND_ACK: 641*7c478bd9Sstevel@tonic-gate /* 642*7c478bd9Sstevel@tonic-gate * if we had to bind, the macaddr is wrong 643*7c478bd9Sstevel@tonic-gate * so get it again 644*7c478bd9Sstevel@tonic-gate */ 645*7c478bd9Sstevel@tonic-gate freemsg(mp); 646*7c478bd9Sstevel@tonic-gate (void) llc1_req_info(q); 647*7c478bd9Sstevel@tonic-gate break; 648*7c478bd9Sstevel@tonic-gate case DL_UNITDATA_IND: 649*7c478bd9Sstevel@tonic-gate /* when not using raw mode we get these */ 650*7c478bd9Sstevel@tonic-gate (void) llc1_recv(macinfo, mp); 651*7c478bd9Sstevel@tonic-gate break; 652*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 653*7c478bd9Sstevel@tonic-gate /* binding is a special case */ 654*7c478bd9Sstevel@tonic-gate if (prim->error_ack.dl_error_primitive == 655*7c478bd9Sstevel@tonic-gate DL_BIND_REQ) { 656*7c478bd9Sstevel@tonic-gate freemsg(mp); 657*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_flags & LLC1_BINDING) 658*7c478bd9Sstevel@tonic-gate llc1_send_bindreq(macinfo); 659*7c478bd9Sstevel@tonic-gate } else 660*7c478bd9Sstevel@tonic-gate llc1_find_waiting(macinfo, mp, 661*7c478bd9Sstevel@tonic-gate prim->error_ack.dl_error_primitive); 662*7c478bd9Sstevel@tonic-gate break; 663*7c478bd9Sstevel@tonic-gate case DL_PHYS_ADDR_ACK: 664*7c478bd9Sstevel@tonic-gate llc1_find_waiting(macinfo, mp, 665*7c478bd9Sstevel@tonic-gate DL_PHYS_ADDR_REQ); 666*7c478bd9Sstevel@tonic-gate break; 667*7c478bd9Sstevel@tonic-gate case DL_OK_ACK: 668*7c478bd9Sstevel@tonic-gate if (prim->ok_ack.dl_correct_primitive == 669*7c478bd9Sstevel@tonic-gate DL_BIND_REQ) 670*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags &= ~LLC1_BINDING; 671*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 672*7c478bd9Sstevel@tonic-gate default: 673*7c478bd9Sstevel@tonic-gate freemsg(mp); 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate break; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate case M_IOCACK: 678*7c478bd9Sstevel@tonic-gate /* probably our DLIOCRAW completing */ 679*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 680*7c478bd9Sstevel@tonic-gate if ((macinfo->llcp_flags & LLC1_RAW_WAIT) && 681*7c478bd9Sstevel@tonic-gate macinfo->llcp_iocid == iocp->ioc_id) { 682*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags &= ~LLC1_RAW_WAIT; 683*7c478bd9Sstevel@tonic-gate /* we can use this form */ 684*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags |= LLC1_USING_RAW; 685*7c478bd9Sstevel@tonic-gate freemsg(mp); 686*7c478bd9Sstevel@tonic-gate break; 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate /* need to find the correct queue */ 689*7c478bd9Sstevel@tonic-gate freemsg(mp); 690*7c478bd9Sstevel@tonic-gate break; 691*7c478bd9Sstevel@tonic-gate case M_IOCNAK: 692*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 693*7c478bd9Sstevel@tonic-gate if ((macinfo->llcp_flags & LLC1_RAW_WAIT) && 694*7c478bd9Sstevel@tonic-gate macinfo->llcp_iocid == iocp->ioc_id) { 695*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags &= ~LLC1_RAW_WAIT; 696*7c478bd9Sstevel@tonic-gate freemsg(mp); 697*7c478bd9Sstevel@tonic-gate break; 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate /* need to find the correct queue */ 700*7c478bd9Sstevel@tonic-gate freemsg(mp); 701*7c478bd9Sstevel@tonic-gate break; 702*7c478bd9Sstevel@tonic-gate case M_DATA: 703*7c478bd9Sstevel@tonic-gate llc1_recv(macinfo, mp); 704*7c478bd9Sstevel@tonic-gate break; 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate return (0); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate /* 711*7c478bd9Sstevel@tonic-gate * llc1_uwsrv - Incoming messages are processed according to the DLPI 712*7c478bd9Sstevel@tonic-gate * protocol specification 713*7c478bd9Sstevel@tonic-gate */ 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate static int 716*7c478bd9Sstevel@tonic-gate llc1_uwsrv(queue_t *q) 717*7c478bd9Sstevel@tonic-gate { 718*7c478bd9Sstevel@tonic-gate mblk_t *mp; 719*7c478bd9Sstevel@tonic-gate llc1_t *lld = (llc1_t *)q->q_ptr; 720*7c478bd9Sstevel@tonic-gate union DL_primitives *prim; 721*7c478bd9Sstevel@tonic-gate int err; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 724*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 725*7c478bd9Sstevel@tonic-gate printf("llc1_wsrv(%x)\n", q); 726*7c478bd9Sstevel@tonic-gate #endif 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate 729*7c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 730*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 731*7c478bd9Sstevel@tonic-gate case M_PROTO: /* Will be an DLPI message of some type */ 732*7c478bd9Sstevel@tonic-gate case M_PCPROTO: 733*7c478bd9Sstevel@tonic-gate if ((err = llc1_cmds(q, mp)) != LLCE_OK) { 734*7c478bd9Sstevel@tonic-gate prim = (union DL_primitives *)mp->b_rptr; 735*7c478bd9Sstevel@tonic-gate if (err == LLCE_NOBUFFER || err == DL_SYSERR) { 736*7c478bd9Sstevel@tonic-gate /* quit while we're ahead */ 737*7c478bd9Sstevel@tonic-gate lld->llc_stats->llcs_nobuffer++; 738*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 739*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCERRS) 740*7c478bd9Sstevel@tonic-gate printf( 741*7c478bd9Sstevel@tonic-gate "llc1_cmds: nonfatal err=%d\n", 742*7c478bd9Sstevel@tonic-gate err); 743*7c478bd9Sstevel@tonic-gate #endif 744*7c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 745*7c478bd9Sstevel@tonic-gate return (0); 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate } else { 748*7c478bd9Sstevel@tonic-gate dlerrorack(q, mp, 749*7c478bd9Sstevel@tonic-gate prim->dl_primitive, 750*7c478bd9Sstevel@tonic-gate err, 0); 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate break; 754*7c478bd9Sstevel@tonic-gate case M_DATA: 755*7c478bd9Sstevel@tonic-gate /* 756*7c478bd9Sstevel@tonic-gate * retry of a previously processed 757*7c478bd9Sstevel@tonic-gate * UNITDATA_REQ or is a RAW message from 758*7c478bd9Sstevel@tonic-gate * above 759*7c478bd9Sstevel@tonic-gate */ 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate mutex_enter(&lld->llc_lock); 762*7c478bd9Sstevel@tonic-gate putnext(lld->llc_mac_info->llcp_queue, mp); 763*7c478bd9Sstevel@tonic-gate mutex_exit(&lld->llc_lock); 764*7c478bd9Sstevel@tonic-gate freemsg(mp); /* free on success */ 765*7c478bd9Sstevel@tonic-gate break; 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate /* This should never happen */ 768*7c478bd9Sstevel@tonic-gate default: 769*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 770*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCERRS) 771*7c478bd9Sstevel@tonic-gate printf("llc1_wsrv: type(%x) not supported\n", 772*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type); 773*7c478bd9Sstevel@tonic-gate #endif 774*7c478bd9Sstevel@tonic-gate freemsg(mp); /* unknown types are discarded */ 775*7c478bd9Sstevel@tonic-gate break; 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate } 778*7c478bd9Sstevel@tonic-gate return (0); 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate /* 782*7c478bd9Sstevel@tonic-gate * llc1_multicast used to determine if the address is a multicast address for 783*7c478bd9Sstevel@tonic-gate * this user. 784*7c478bd9Sstevel@tonic-gate */ 785*7c478bd9Sstevel@tonic-gate int 786*7c478bd9Sstevel@tonic-gate llc1_multicast(struct ether_addr *addr, llc1_t *lld) 787*7c478bd9Sstevel@tonic-gate { 788*7c478bd9Sstevel@tonic-gate int i; 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate if (lld->llc_mcast) 791*7c478bd9Sstevel@tonic-gate for (i = 0; i < lld->llc_multicnt; i++) 792*7c478bd9Sstevel@tonic-gate if (lld->llc_mcast[i] && 793*7c478bd9Sstevel@tonic-gate lld->llc_mcast[i]->llcm_refcnt && 794*7c478bd9Sstevel@tonic-gate bcmp(lld->llc_mcast[i]->llcm_addr, 795*7c478bd9Sstevel@tonic-gate addr->ether_addr_octet, ETHERADDRL) == 0) 796*7c478bd9Sstevel@tonic-gate return (1); 797*7c478bd9Sstevel@tonic-gate return (0); 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* 801*7c478bd9Sstevel@tonic-gate * llc1_ioctl handles all ioctl requests passed downstream. This routine is 802*7c478bd9Sstevel@tonic-gate * passed a pointer to the message block with the ioctl request in it, and a 803*7c478bd9Sstevel@tonic-gate * pointer to the queue so it can respond to the ioctl request with an ack. 804*7c478bd9Sstevel@tonic-gate */ 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate int llc1_doreqinfo; 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate static void 809*7c478bd9Sstevel@tonic-gate llc1_ioctl(queue_t *q, mblk_t *mp) 810*7c478bd9Sstevel@tonic-gate { 811*7c478bd9Sstevel@tonic-gate struct iocblk *iocp; 812*7c478bd9Sstevel@tonic-gate llc1_t *lld; 813*7c478bd9Sstevel@tonic-gate struct linkblk *link; 814*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo; 815*7c478bd9Sstevel@tonic-gate mblk_t *tmp; 816*7c478bd9Sstevel@tonic-gate int error; 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 819*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 820*7c478bd9Sstevel@tonic-gate printf("llc1_ioctl(%x %x)\n", q, mp); 821*7c478bd9Sstevel@tonic-gate #endif 822*7c478bd9Sstevel@tonic-gate lld = (llc1_t *)q->q_ptr; 823*7c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 824*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 825*7c478bd9Sstevel@tonic-gate /* XXX need to lock the data structures */ 826*7c478bd9Sstevel@tonic-gate case I_PLINK: 827*7c478bd9Sstevel@tonic-gate case I_LINK: 828*7c478bd9Sstevel@tonic-gate link = (struct linkblk *)mp->b_cont->b_rptr; 829*7c478bd9Sstevel@tonic-gate tmp = allocb(sizeof (llc_mac_info_t), BPRI_MED); 830*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 831*7c478bd9Sstevel@tonic-gate (void) miocnak(q, mp, 0, ENOSR); 832*7c478bd9Sstevel@tonic-gate return; 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate bzero(tmp->b_rptr, sizeof (llc_mac_info_t)); 835*7c478bd9Sstevel@tonic-gate macinfo = (llc_mac_info_t *)tmp->b_rptr; 836*7c478bd9Sstevel@tonic-gate macinfo->llcp_mb = tmp; 837*7c478bd9Sstevel@tonic-gate macinfo->llcp_next = macinfo->llcp_prev = macinfo; 838*7c478bd9Sstevel@tonic-gate macinfo->llcp_queue = link->l_qbot; 839*7c478bd9Sstevel@tonic-gate macinfo->llcp_lindex = link->l_index; 840*7c478bd9Sstevel@tonic-gate /* tentative */ 841*7c478bd9Sstevel@tonic-gate macinfo->llcp_ppa = --llc1_device_list.llc1_nextppa; 842*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_ndevice++; 843*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags |= LLC1_LINKED | LLC1_DEF_PPA; 844*7c478bd9Sstevel@tonic-gate macinfo->llcp_lqtop = q; 845*7c478bd9Sstevel@tonic-gate macinfo->llcp_data = NULL; 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate /* need to do an info_req before an info_req or attach */ 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate rw_enter(&llc1_device_list.llc1_rwlock, RW_WRITER); 850*7c478bd9Sstevel@tonic-gate llc1insque(macinfo, llc1_device_list.llc1_mac_prev); 851*7c478bd9Sstevel@tonic-gate macinfo->llcp_queue->q_ptr = RD(macinfo->llcp_queue)->q_ptr = 852*7c478bd9Sstevel@tonic-gate (caddr_t)macinfo; 853*7c478bd9Sstevel@tonic-gate llc1_init_kstat(macinfo); 854*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate /* initiate getting the info */ 857*7c478bd9Sstevel@tonic-gate (void) llc1_req_info(macinfo->llcp_queue); 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate miocack(q, mp, 0, 0); 860*7c478bd9Sstevel@tonic-gate return; 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate case I_PUNLINK: 863*7c478bd9Sstevel@tonic-gate case I_UNLINK: 864*7c478bd9Sstevel@tonic-gate link = (struct linkblk *)mp->b_cont->b_rptr; 865*7c478bd9Sstevel@tonic-gate rw_enter(&llc1_device_list.llc1_rwlock, RW_WRITER); 866*7c478bd9Sstevel@tonic-gate for (macinfo = llc1_device_list.llc1_mac_next; 867*7c478bd9Sstevel@tonic-gate macinfo != NULL && 868*7c478bd9Sstevel@tonic-gate macinfo != 869*7c478bd9Sstevel@tonic-gate (llc_mac_info_t *)&llc1_device_list.llc1_mac_next; 870*7c478bd9Sstevel@tonic-gate macinfo = macinfo->llcp_next) { 871*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_lindex == link->l_index && 872*7c478bd9Sstevel@tonic-gate macinfo->llcp_queue == link->l_qbot) { 873*7c478bd9Sstevel@tonic-gate /* found it */ 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate ASSERT(macinfo->llcp_next); 876*7c478bd9Sstevel@tonic-gate 877*7c478bd9Sstevel@tonic-gate /* remove from device list */ 878*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_ndevice--; 879*7c478bd9Sstevel@tonic-gate llc1remque(macinfo); 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate /* remove any mcast structs */ 882*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_mcast != NULL) { 883*7c478bd9Sstevel@tonic-gate kmem_free(macinfo->llcp_mcast, 884*7c478bd9Sstevel@tonic-gate sizeof (llc_mcast_t) * 885*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_multisize); 886*7c478bd9Sstevel@tonic-gate macinfo->llcp_mcast = NULL; 887*7c478bd9Sstevel@tonic-gate } 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate /* remove any kstat counters */ 890*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_kstatp != NULL) 891*7c478bd9Sstevel@tonic-gate llc1_uninit_kstat(macinfo); 892*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_mb != NULL) 893*7c478bd9Sstevel@tonic-gate freeb(macinfo->llcp_mb); 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate lld->llc_mac_info = NULL; 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate miocack(q, mp, 0, 0); 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate /* finish any necessary setup */ 900*7c478bd9Sstevel@tonic-gate if (llc1_device_list.llc1_ndevice == 0) 901*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_nextppa = 0; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 904*7c478bd9Sstevel@tonic-gate return; 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 908*7c478bd9Sstevel@tonic-gate /* 909*7c478bd9Sstevel@tonic-gate * what should really be done here -- force errors on all 910*7c478bd9Sstevel@tonic-gate * streams? 911*7c478bd9Sstevel@tonic-gate */ 912*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 913*7c478bd9Sstevel@tonic-gate return; 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate case L_SETPPA: 916*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct ll_snioc)); 917*7c478bd9Sstevel@tonic-gate if (error != 0) { 918*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 919*7c478bd9Sstevel@tonic-gate return; 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if (llc1_setppa((struct ll_snioc *)mp->b_cont->b_rptr) >= 0) { 923*7c478bd9Sstevel@tonic-gate miocack(q, mp, 0, 0); 924*7c478bd9Sstevel@tonic-gate return; 925*7c478bd9Sstevel@tonic-gate } 926*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 927*7c478bd9Sstevel@tonic-gate return; 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate case L_GETPPA: 930*7c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) { 931*7c478bd9Sstevel@tonic-gate mp->b_cont = allocb(sizeof (struct ll_snioc), BPRI_MED); 932*7c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) { 933*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENOSR); 934*7c478bd9Sstevel@tonic-gate return; 935*7c478bd9Sstevel@tonic-gate } 936*7c478bd9Sstevel@tonic-gate mp->b_cont->b_wptr = 937*7c478bd9Sstevel@tonic-gate mp->b_cont->b_rptr + sizeof (struct ll_snioc); 938*7c478bd9Sstevel@tonic-gate } else { 939*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct ll_snioc)); 940*7c478bd9Sstevel@tonic-gate if (error != 0) { 941*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 942*7c478bd9Sstevel@tonic-gate return; 943*7c478bd9Sstevel@tonic-gate } 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate lld = (llc1_t *)q->q_ptr; 947*7c478bd9Sstevel@tonic-gate if (llc1_getppa(lld->llc_mac_info, 948*7c478bd9Sstevel@tonic-gate (struct ll_snioc *)mp->b_cont->b_rptr) >= 0) 949*7c478bd9Sstevel@tonic-gate miocack(q, mp, 0, 0); 950*7c478bd9Sstevel@tonic-gate else 951*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 952*7c478bd9Sstevel@tonic-gate return; 953*7c478bd9Sstevel@tonic-gate default: 954*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate /* 959*7c478bd9Sstevel@tonic-gate * llc1_setppa(snioc) this function sets the real PPA number for a previously 960*7c478bd9Sstevel@tonic-gate * I_LINKED stream. Be careful to select the macinfo struct associated 961*7c478bd9Sstevel@tonic-gate * with our llc struct, to avoid erroneous references. 962*7c478bd9Sstevel@tonic-gate */ 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate static int 965*7c478bd9Sstevel@tonic-gate llc1_setppa(struct ll_snioc *snioc) 966*7c478bd9Sstevel@tonic-gate { 967*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo; 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate for (macinfo = llc1_device_list.llc1_mac_next; 970*7c478bd9Sstevel@tonic-gate macinfo != (llc_mac_info_t *)&llc1_device_list.llc1_mac_next; 971*7c478bd9Sstevel@tonic-gate macinfo = macinfo->llcp_next) 972*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_lindex == snioc->lli_index && 973*7c478bd9Sstevel@tonic-gate (macinfo->llcp_flags & LLC1_DEF_PPA)) { 974*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags &= ~LLC1_DEF_PPA; 975*7c478bd9Sstevel@tonic-gate macinfo->llcp_ppa = snioc->lli_ppa; 976*7c478bd9Sstevel@tonic-gate return (0); 977*7c478bd9Sstevel@tonic-gate } 978*7c478bd9Sstevel@tonic-gate return (-1); 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate /* 982*7c478bd9Sstevel@tonic-gate * llc1_getppa(macinfo, snioc) returns the PPA for this stream 983*7c478bd9Sstevel@tonic-gate */ 984*7c478bd9Sstevel@tonic-gate static int 985*7c478bd9Sstevel@tonic-gate llc1_getppa(llc_mac_info_t *macinfo, struct ll_snioc *snioc) 986*7c478bd9Sstevel@tonic-gate { 987*7c478bd9Sstevel@tonic-gate if (macinfo == NULL) 988*7c478bd9Sstevel@tonic-gate return (-1); 989*7c478bd9Sstevel@tonic-gate snioc->lli_ppa = macinfo->llcp_ppa; 990*7c478bd9Sstevel@tonic-gate snioc->lli_index = macinfo->llcp_lindex; 991*7c478bd9Sstevel@tonic-gate return (0); 992*7c478bd9Sstevel@tonic-gate } 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate /* 995*7c478bd9Sstevel@tonic-gate * llc1_cmds - process the DL commands as defined in dlpi.h 996*7c478bd9Sstevel@tonic-gate */ 997*7c478bd9Sstevel@tonic-gate static int 998*7c478bd9Sstevel@tonic-gate llc1_cmds(queue_t *q, mblk_t *mp) 999*7c478bd9Sstevel@tonic-gate { 1000*7c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 1001*7c478bd9Sstevel@tonic-gate llc1_t *llc = (llc1_t *)q->q_ptr; 1002*7c478bd9Sstevel@tonic-gate int result = 0; 1003*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo = llc->llc_mac_info; 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)mp->b_rptr; 1006*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1007*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 1008*7c478bd9Sstevel@tonic-gate printf("llc1_cmds(%x, %x):dlp=%x, dlp->dl_primitive=%d\n", 1009*7c478bd9Sstevel@tonic-gate q, mp, dlp, dlp->dl_primitive); 1010*7c478bd9Sstevel@tonic-gate #endif 1011*7c478bd9Sstevel@tonic-gate mutex_enter(&llc->llc_lock); 1012*7c478bd9Sstevel@tonic-gate rw_enter(&llc1_device_list.llc1_rwlock, RW_READER); 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate switch (dlp->dl_primitive) { 1015*7c478bd9Sstevel@tonic-gate case DL_BIND_REQ: 1016*7c478bd9Sstevel@tonic-gate result = llc1_bind(q, mp); 1017*7c478bd9Sstevel@tonic-gate break; 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate case DL_UNBIND_REQ: 1020*7c478bd9Sstevel@tonic-gate result = llc1_unbind(q, mp); 1021*7c478bd9Sstevel@tonic-gate break; 1022*7c478bd9Sstevel@tonic-gate 1023*7c478bd9Sstevel@tonic-gate case DL_SUBS_BIND_REQ: 1024*7c478bd9Sstevel@tonic-gate result = llc1_subs_bind(q, mp); 1025*7c478bd9Sstevel@tonic-gate break; 1026*7c478bd9Sstevel@tonic-gate 1027*7c478bd9Sstevel@tonic-gate case DL_SUBS_UNBIND_REQ: 1028*7c478bd9Sstevel@tonic-gate result = llc1_subs_unbind(); 1029*7c478bd9Sstevel@tonic-gate break; 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate case DL_UNITDATA_REQ: 1032*7c478bd9Sstevel@tonic-gate result = llc1_unitdata(q, mp); 1033*7c478bd9Sstevel@tonic-gate break; 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate case DL_INFO_REQ: 1036*7c478bd9Sstevel@tonic-gate result = llc1_inforeq(q, mp); 1037*7c478bd9Sstevel@tonic-gate break; 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate case DL_ATTACH_REQ: 1040*7c478bd9Sstevel@tonic-gate result = llc1attach(q, mp); 1041*7c478bd9Sstevel@tonic-gate break; 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate case DL_DETACH_REQ: 1044*7c478bd9Sstevel@tonic-gate result = llc1unattach(q, mp); 1045*7c478bd9Sstevel@tonic-gate break; 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate case DL_ENABMULTI_REQ: 1048*7c478bd9Sstevel@tonic-gate result = llc1_enable_multi(q, mp); 1049*7c478bd9Sstevel@tonic-gate break; 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate case DL_DISABMULTI_REQ: 1052*7c478bd9Sstevel@tonic-gate result = llc1_disable_multi(q, mp); 1053*7c478bd9Sstevel@tonic-gate break; 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate case DL_XID_REQ: 1056*7c478bd9Sstevel@tonic-gate result = llc1_xid_req_res(q, mp, 0); 1057*7c478bd9Sstevel@tonic-gate break; 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate case DL_XID_RES: 1060*7c478bd9Sstevel@tonic-gate result = llc1_xid_req_res(q, mp, 1); 1061*7c478bd9Sstevel@tonic-gate break; 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate case DL_TEST_REQ: 1064*7c478bd9Sstevel@tonic-gate result = llc1_test_req_res(q, mp, 0); 1065*7c478bd9Sstevel@tonic-gate break; 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate case DL_TEST_RES: 1068*7c478bd9Sstevel@tonic-gate result = llc1_test_req_res(q, mp, 1); 1069*7c478bd9Sstevel@tonic-gate break; 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate case DL_SET_PHYS_ADDR_REQ: 1072*7c478bd9Sstevel@tonic-gate result = DL_NOTSUPPORTED; 1073*7c478bd9Sstevel@tonic-gate break; 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate case DL_PHYS_ADDR_REQ: 1076*7c478bd9Sstevel@tonic-gate if (llc->llc_state != DL_UNATTACHED && macinfo) { 1077*7c478bd9Sstevel@tonic-gate llc->llc_waiting_for = dlp->dl_primitive; 1078*7c478bd9Sstevel@tonic-gate putnext(WR(macinfo->llcp_queue), mp); 1079*7c478bd9Sstevel@tonic-gate result = LLCE_OK; 1080*7c478bd9Sstevel@tonic-gate } else { 1081*7c478bd9Sstevel@tonic-gate result = DL_OUTSTATE; 1082*7c478bd9Sstevel@tonic-gate } 1083*7c478bd9Sstevel@tonic-gate break; 1084*7c478bd9Sstevel@tonic-gate 1085*7c478bd9Sstevel@tonic-gate case DL_PROMISCON_REQ: 1086*7c478bd9Sstevel@tonic-gate case DL_PROMISCOFF_REQ: 1087*7c478bd9Sstevel@tonic-gate result = DL_NOTSUPPORTED; 1088*7c478bd9Sstevel@tonic-gate break; 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate default: 1091*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1092*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCERRS) 1093*7c478bd9Sstevel@tonic-gate printf("llc1_cmds: Received unknown primitive: %d\n", 1094*7c478bd9Sstevel@tonic-gate dlp->dl_primitive); 1095*7c478bd9Sstevel@tonic-gate #endif 1096*7c478bd9Sstevel@tonic-gate result = DL_BADPRIM; 1097*7c478bd9Sstevel@tonic-gate break; 1098*7c478bd9Sstevel@tonic-gate } 1099*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 1100*7c478bd9Sstevel@tonic-gate mutex_exit(&llc->llc_lock); 1101*7c478bd9Sstevel@tonic-gate return (result); 1102*7c478bd9Sstevel@tonic-gate } 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate /* 1105*7c478bd9Sstevel@tonic-gate * llc1_bind - determine if a SAP is already allocated and whether it is 1106*7c478bd9Sstevel@tonic-gate * legal to do the bind at this time 1107*7c478bd9Sstevel@tonic-gate */ 1108*7c478bd9Sstevel@tonic-gate static int 1109*7c478bd9Sstevel@tonic-gate llc1_bind(queue_t *q, mblk_t *mp) 1110*7c478bd9Sstevel@tonic-gate { 1111*7c478bd9Sstevel@tonic-gate int sap; 1112*7c478bd9Sstevel@tonic-gate dl_bind_req_t *dlp; 1113*7c478bd9Sstevel@tonic-gate llc1_t *lld = (llc1_t *)q->q_ptr; 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate ASSERT(lld); 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1118*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 1119*7c478bd9Sstevel@tonic-gate printf("llc1_bind(%x %x)\n", q, mp); 1120*7c478bd9Sstevel@tonic-gate #endif 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate dlp = (dl_bind_req_t *)mp->b_rptr; 1123*7c478bd9Sstevel@tonic-gate sap = dlp->dl_sap; 1124*7c478bd9Sstevel@tonic-gate 1125*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1126*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCPROT) 1127*7c478bd9Sstevel@tonic-gate printf("llc1_bind: lsap=%x\n", sap); 1128*7c478bd9Sstevel@tonic-gate #endif 1129*7c478bd9Sstevel@tonic-gate 1130*7c478bd9Sstevel@tonic-gate if (lld->llc_mac_info == NULL) 1131*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1132*7c478bd9Sstevel@tonic-gate 1133*7c478bd9Sstevel@tonic-gate if (lld->llc_qptr && lld->llc_state != DL_UNBOUND) { 1134*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1135*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCERRS) 1136*7c478bd9Sstevel@tonic-gate printf("llc1_bind: stream bound/not attached (%d)\n", 1137*7c478bd9Sstevel@tonic-gate lld->llc_state); 1138*7c478bd9Sstevel@tonic-gate #endif 1139*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate if (dlp->dl_service_mode != DL_CLDLS || dlp->dl_max_conind != 0) { 1143*7c478bd9Sstevel@tonic-gate return (DL_UNSUPPORTED); 1144*7c478bd9Sstevel@tonic-gate } 1145*7c478bd9Sstevel@tonic-gate /* 1146*7c478bd9Sstevel@tonic-gate * prohibit group saps. An exception is the broadcast sap which is, 1147*7c478bd9Sstevel@tonic-gate * unfortunately, used by SUNSelect to indicate Novell Netware in 1148*7c478bd9Sstevel@tonic-gate * 802.3 mode. Really should use a very non-802.2 SAP like 0xFFFF 1149*7c478bd9Sstevel@tonic-gate * or -2. 1150*7c478bd9Sstevel@tonic-gate */ 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate if (sap == 0 || (sap <= 0xFF && (sap & 1 && sap != 0xFF)) || 1153*7c478bd9Sstevel@tonic-gate sap > 0xFFFF) { 1154*7c478bd9Sstevel@tonic-gate return (DL_BADSAP); 1155*7c478bd9Sstevel@tonic-gate } 1156*7c478bd9Sstevel@tonic-gate lld->llc_state = DL_BIND_PENDING; 1157*7c478bd9Sstevel@tonic-gate 1158*7c478bd9Sstevel@tonic-gate /* if we fall through, then the SAP is legal */ 1159*7c478bd9Sstevel@tonic-gate if (sap == 0xFF) { 1160*7c478bd9Sstevel@tonic-gate if (lld->llc_mac_info->llcp_type == DL_CSMACD) 1161*7c478bd9Sstevel@tonic-gate sap = LLC_NOVELL_SAP; 1162*7c478bd9Sstevel@tonic-gate else 1163*7c478bd9Sstevel@tonic-gate return (DL_BADSAP); 1164*7c478bd9Sstevel@tonic-gate } 1165*7c478bd9Sstevel@tonic-gate lld->llc_sap = sap; 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate if (sap > 0xFF) { 1168*7c478bd9Sstevel@tonic-gate ushort_t snapsap = htons(sap); 1169*7c478bd9Sstevel@tonic-gate /* this is SNAP, so set things up */ 1170*7c478bd9Sstevel@tonic-gate lld->llc_snap[3] = ((uchar_t *)&snapsap)[0]; 1171*7c478bd9Sstevel@tonic-gate lld->llc_snap[4] = ((uchar_t *)&snapsap)[1]; 1172*7c478bd9Sstevel@tonic-gate /* mark as SNAP but allow OID to be added later */ 1173*7c478bd9Sstevel@tonic-gate lld->llc_flags |= LLC_SNAP; 1174*7c478bd9Sstevel@tonic-gate lld->llc_sap = LLC_SNAP_SAP; 1175*7c478bd9Sstevel@tonic-gate } 1176*7c478bd9Sstevel@tonic-gate 1177*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1178*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCPROT) 1179*7c478bd9Sstevel@tonic-gate printf("llc1_bind: ok - type = %d\n", lld->llc_type); 1180*7c478bd9Sstevel@tonic-gate #endif 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate if (dlp->dl_xidtest_flg & DL_AUTO_XID) 1183*7c478bd9Sstevel@tonic-gate lld->llc_flags |= LLC1_AUTO_XID; 1184*7c478bd9Sstevel@tonic-gate if (dlp->dl_xidtest_flg & DL_AUTO_TEST) 1185*7c478bd9Sstevel@tonic-gate lld->llc_flags |= LLC1_AUTO_TEST; 1186*7c478bd9Sstevel@tonic-gate 1187*7c478bd9Sstevel@tonic-gate /* ACK the BIND, if possible */ 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate dlbindack(q, mp, sap, lld->llc_mac_info->llcp_macaddr, 6, 0, 0); 1190*7c478bd9Sstevel@tonic-gate 1191*7c478bd9Sstevel@tonic-gate lld->llc_state = DL_IDLE; /* bound and ready */ 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1194*7c478bd9Sstevel@tonic-gate } 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate /* 1197*7c478bd9Sstevel@tonic-gate * llc1_unbind - perform an unbind of an LSAP or ether type on the stream. 1198*7c478bd9Sstevel@tonic-gate * The stream is still open and can be re-bound. 1199*7c478bd9Sstevel@tonic-gate */ 1200*7c478bd9Sstevel@tonic-gate static int 1201*7c478bd9Sstevel@tonic-gate llc1_unbind(queue_t *q, mblk_t *mp) 1202*7c478bd9Sstevel@tonic-gate { 1203*7c478bd9Sstevel@tonic-gate llc1_t *lld; 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1206*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 1207*7c478bd9Sstevel@tonic-gate printf("llc1_unbind(%x %x)\n", q, mp); 1208*7c478bd9Sstevel@tonic-gate #endif 1209*7c478bd9Sstevel@tonic-gate lld = (llc1_t *)q->q_ptr; 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate if (lld->llc_mac_info == NULL) 1212*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1213*7c478bd9Sstevel@tonic-gate 1214*7c478bd9Sstevel@tonic-gate if (lld->llc_state != DL_IDLE) { 1215*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1216*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCERRS) 1217*7c478bd9Sstevel@tonic-gate printf("llc1_unbind: wrong state (%d)\n", 1218*7c478bd9Sstevel@tonic-gate lld->llc_state); 1219*7c478bd9Sstevel@tonic-gate #endif 1220*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1221*7c478bd9Sstevel@tonic-gate } 1222*7c478bd9Sstevel@tonic-gate lld->llc_state = DL_UNBIND_PENDING; 1223*7c478bd9Sstevel@tonic-gate lld->llc_flags &= ~(LLC_SNAP|LLC_SNAP_OID); /* just in case */ 1224*7c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_UNBIND_REQ); 1225*7c478bd9Sstevel@tonic-gate lld->llc_state = DL_UNBOUND; 1226*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1227*7c478bd9Sstevel@tonic-gate } 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate /* 1230*7c478bd9Sstevel@tonic-gate * llc1_inforeq - generate the response to an info request 1231*7c478bd9Sstevel@tonic-gate */ 1232*7c478bd9Sstevel@tonic-gate static int 1233*7c478bd9Sstevel@tonic-gate llc1_inforeq(queue_t *q, mblk_t *mp) 1234*7c478bd9Sstevel@tonic-gate { 1235*7c478bd9Sstevel@tonic-gate llc1_t *lld; 1236*7c478bd9Sstevel@tonic-gate mblk_t *nmp; 1237*7c478bd9Sstevel@tonic-gate dl_info_ack_t *dlp; 1238*7c478bd9Sstevel@tonic-gate int bufsize; 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1241*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 1242*7c478bd9Sstevel@tonic-gate printf("llc1_inforeq(%x %x)\n", q, mp); 1243*7c478bd9Sstevel@tonic-gate #endif 1244*7c478bd9Sstevel@tonic-gate lld = (llc1_t *)q->q_ptr; 1245*7c478bd9Sstevel@tonic-gate ASSERT(lld); 1246*7c478bd9Sstevel@tonic-gate if (lld->llc_mac_info == NULL) 1247*7c478bd9Sstevel@tonic-gate bufsize = sizeof (dl_info_ack_t) + ETHERADDRL; 1248*7c478bd9Sstevel@tonic-gate else 1249*7c478bd9Sstevel@tonic-gate bufsize = sizeof (dl_info_ack_t) + 1250*7c478bd9Sstevel@tonic-gate 2 * lld->llc_mac_info->llcp_addrlen + 2; 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate nmp = mexchange(q, mp, bufsize, M_PCPROTO, DL_INFO_ACK); 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate if (nmp) { 1255*7c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + sizeof (dl_info_ack_t); 1256*7c478bd9Sstevel@tonic-gate dlp = (dl_info_ack_t *)nmp->b_rptr; 1257*7c478bd9Sstevel@tonic-gate bzero(dlp, DL_INFO_ACK_SIZE); 1258*7c478bd9Sstevel@tonic-gate dlp->dl_primitive = DL_INFO_ACK; 1259*7c478bd9Sstevel@tonic-gate if (lld->llc_mac_info) 1260*7c478bd9Sstevel@tonic-gate dlp->dl_max_sdu = lld->llc_mac_info->llcp_maxpkt; 1261*7c478bd9Sstevel@tonic-gate dlp->dl_min_sdu = 0; 1262*7c478bd9Sstevel@tonic-gate dlp->dl_mac_type = lld->llc_type; 1263*7c478bd9Sstevel@tonic-gate dlp->dl_service_mode = DL_CLDLS; 1264*7c478bd9Sstevel@tonic-gate dlp->dl_current_state = lld->llc_state; 1265*7c478bd9Sstevel@tonic-gate dlp->dl_provider_style = 1266*7c478bd9Sstevel@tonic-gate (lld->llc_style == 0) ? lld->llc_style : DL_STYLE2; 1267*7c478bd9Sstevel@tonic-gate 1268*7c478bd9Sstevel@tonic-gate /* now append physical address */ 1269*7c478bd9Sstevel@tonic-gate if (lld->llc_mac_info) { 1270*7c478bd9Sstevel@tonic-gate dlp->dl_addr_length = lld->llc_mac_info->llcp_addrlen; 1271*7c478bd9Sstevel@tonic-gate dlp->dl_addr_offset = DL_INFO_ACK_SIZE; 1272*7c478bd9Sstevel@tonic-gate nmp->b_wptr += dlp->dl_addr_length + 1; 1273*7c478bd9Sstevel@tonic-gate bcopy(lld->llc_mac_info->llcp_macaddr, 1274*7c478bd9Sstevel@tonic-gate ((caddr_t)dlp) + dlp->dl_addr_offset, 1275*7c478bd9Sstevel@tonic-gate lld->llc_mac_info->llcp_addrlen); 1276*7c478bd9Sstevel@tonic-gate if (lld->llc_state == DL_IDLE) { 1277*7c478bd9Sstevel@tonic-gate dlp->dl_sap_length = -1; /* 1 byte on end */ 1278*7c478bd9Sstevel@tonic-gate *(((caddr_t)dlp) + dlp->dl_addr_offset + 1279*7c478bd9Sstevel@tonic-gate dlp->dl_addr_length) = lld->llc_sap; 1280*7c478bd9Sstevel@tonic-gate dlp->dl_addr_length += 1; 1281*7c478bd9Sstevel@tonic-gate } 1282*7c478bd9Sstevel@tonic-gate /* and the broadcast address */ 1283*7c478bd9Sstevel@tonic-gate dlp->dl_brdcst_addr_length = 1284*7c478bd9Sstevel@tonic-gate lld->llc_mac_info->llcp_addrlen; 1285*7c478bd9Sstevel@tonic-gate dlp->dl_brdcst_addr_offset = 1286*7c478bd9Sstevel@tonic-gate dlp->dl_addr_offset + dlp->dl_addr_length; 1287*7c478bd9Sstevel@tonic-gate nmp->b_wptr += dlp->dl_brdcst_addr_length; 1288*7c478bd9Sstevel@tonic-gate bcopy(lld->llc_mac_info->llcp_broadcast, 1289*7c478bd9Sstevel@tonic-gate ((caddr_t)dlp) + dlp->dl_brdcst_addr_offset, 1290*7c478bd9Sstevel@tonic-gate lld->llc_mac_info->llcp_addrlen); 1291*7c478bd9Sstevel@tonic-gate } else { 1292*7c478bd9Sstevel@tonic-gate dlp->dl_addr_length = 0; /* not attached yet */ 1293*7c478bd9Sstevel@tonic-gate dlp->dl_addr_offset = NULL; 1294*7c478bd9Sstevel@tonic-gate dlp->dl_sap_length = 0; /* 1 bytes on end */ 1295*7c478bd9Sstevel@tonic-gate } 1296*7c478bd9Sstevel@tonic-gate dlp->dl_version = DL_VERSION_2; 1297*7c478bd9Sstevel@tonic-gate qreply(q, nmp); 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1300*7c478bd9Sstevel@tonic-gate } 1301*7c478bd9Sstevel@tonic-gate 1302*7c478bd9Sstevel@tonic-gate /* 1303*7c478bd9Sstevel@tonic-gate * llc1_unitdata 1304*7c478bd9Sstevel@tonic-gate * send a datagram. Destination address/lsap is in M_PROTO 1305*7c478bd9Sstevel@tonic-gate * message (first mblock), data is in remainder of message. 1306*7c478bd9Sstevel@tonic-gate * 1307*7c478bd9Sstevel@tonic-gate * NOTE: We are reusing the DL_unitdata_req mblock; if llc header gets any 1308*7c478bd9Sstevel@tonic-gate * bigger, recheck to make sure it still fits! We assume that we have a 1309*7c478bd9Sstevel@tonic-gate * 64-byte dblock for this, since a DL_unitdata_req is 20 bytes and the next 1310*7c478bd9Sstevel@tonic-gate * larger dblock size is 64. 1311*7c478bd9Sstevel@tonic-gate */ 1312*7c478bd9Sstevel@tonic-gate static int 1313*7c478bd9Sstevel@tonic-gate llc1_unitdata(queue_t *q, mblk_t *mp) 1314*7c478bd9Sstevel@tonic-gate { 1315*7c478bd9Sstevel@tonic-gate llc1_t *lld = (llc1_t *)q->q_ptr; 1316*7c478bd9Sstevel@tonic-gate dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)mp->b_rptr; 1317*7c478bd9Sstevel@tonic-gate struct ether_header *hdr; 1318*7c478bd9Sstevel@tonic-gate struct llcaddr *llcp; 1319*7c478bd9Sstevel@tonic-gate mblk_t *nmp; 1320*7c478bd9Sstevel@tonic-gate long msglen; 1321*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 1322*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo; 1323*7c478bd9Sstevel@tonic-gate int xmt_type = 0; 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1326*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 1327*7c478bd9Sstevel@tonic-gate printf("llc1_unitdata(%x %x)\n", q, mp); 1328*7c478bd9Sstevel@tonic-gate #endif 1329*7c478bd9Sstevel@tonic-gate 1330*7c478bd9Sstevel@tonic-gate if ((macinfo = lld->llc_mac_info) == NULL) 1331*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1332*7c478bd9Sstevel@tonic-gate 1333*7c478bd9Sstevel@tonic-gate if (lld->llc_state != DL_IDLE) { 1334*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1335*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCERRS) 1336*7c478bd9Sstevel@tonic-gate printf("llc1_unitdata: wrong state (%d)\n", 1337*7c478bd9Sstevel@tonic-gate lld->llc_state); 1338*7c478bd9Sstevel@tonic-gate #endif 1339*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate /* need the destination address in all cases */ 1343*7c478bd9Sstevel@tonic-gate llcp = (struct llcaddr *)((caddr_t)dlp + dlp->dl_dest_addr_offset); 1344*7c478bd9Sstevel@tonic-gate 1345*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_flags & LLC1_USING_RAW) { 1346*7c478bd9Sstevel@tonic-gate /* 1347*7c478bd9Sstevel@tonic-gate * make a valid header for transmission 1348*7c478bd9Sstevel@tonic-gate */ 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate /* need a buffer big enough for the headers */ 1351*7c478bd9Sstevel@tonic-gate nmp = allocb(macinfo->llcp_addrlen * 2 + 2 + 8, BPRI_MED); 1352*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)nmp->b_rptr; 1353*7c478bd9Sstevel@tonic-gate msglen = msgdsize(mp); 1354*7c478bd9Sstevel@tonic-gate 1355*7c478bd9Sstevel@tonic-gate /* fill in type dependent fields */ 1356*7c478bd9Sstevel@tonic-gate switch (lld->llc_type) { 1357*7c478bd9Sstevel@tonic-gate case DL_CSMACD: /* 802.3 CSMA/CD */ 1358*7c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + LLC1_CSMACD_HDR_SIZE; 1359*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)nmp->b_wptr; 1360*7c478bd9Sstevel@tonic-gate bcopy(llcp->llca_addr, 1361*7c478bd9Sstevel@tonic-gate hdr->ether_dhost.ether_addr_octet, 1362*7c478bd9Sstevel@tonic-gate ETHERADDRL); 1363*7c478bd9Sstevel@tonic-gate bcopy(macinfo->llcp_macaddr, 1364*7c478bd9Sstevel@tonic-gate hdr->ether_shost.ether_addr_octet, 1365*7c478bd9Sstevel@tonic-gate ETHERADDRL); 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate if (lld->llc_sap != LLC_NOVELL_SAP) { 1368*7c478bd9Sstevel@tonic-gate /* set length with llc header size */ 1369*7c478bd9Sstevel@tonic-gate hdr->ether_type = ntohs(msglen + 1370*7c478bd9Sstevel@tonic-gate sizeof (struct llchdr)); 1371*7c478bd9Sstevel@tonic-gate 1372*7c478bd9Sstevel@tonic-gate /* need an LLC header, otherwise is Novell */ 1373*7c478bd9Sstevel@tonic-gate /* bound sap is always source */ 1374*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap = lld->llc_sap; 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate /* destination sap */ 1377*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap = llcp->llca_sap; 1378*7c478bd9Sstevel@tonic-gate 1379*7c478bd9Sstevel@tonic-gate /* always Unnumbered Information */ 1380*7c478bd9Sstevel@tonic-gate llchdr->llc_ctl = LLC_UI; 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate nmp->b_wptr += sizeof (struct llchdr); 1383*7c478bd9Sstevel@tonic-gate 1384*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & LLC_SNAP) { 1385*7c478bd9Sstevel@tonic-gate bcopy(lld->llc_snap, nmp->b_wptr, 5); 1386*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap = LLC_SNAP_SAP; 1387*7c478bd9Sstevel@tonic-gate nmp->b_wptr += 5; 1388*7c478bd9Sstevel@tonic-gate } 1389*7c478bd9Sstevel@tonic-gate } else { 1390*7c478bd9Sstevel@tonic-gate /* set length without llc header size */ 1391*7c478bd9Sstevel@tonic-gate hdr->ether_type = ntohs(msglen); 1392*7c478bd9Sstevel@tonic-gate 1393*7c478bd9Sstevel@tonic-gate /* we don't do anything else for Netware */ 1394*7c478bd9Sstevel@tonic-gate } 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate if (ismulticast(hdr->ether_dhost.ether_addr_octet)) { 1397*7c478bd9Sstevel@tonic-gate if (bcmp(hdr->ether_dhost.ether_addr_octet, 1398*7c478bd9Sstevel@tonic-gate macinfo->llcp_broadcast, ETHERADDRL) == 0) 1399*7c478bd9Sstevel@tonic-gate xmt_type = 2; 1400*7c478bd9Sstevel@tonic-gate else 1401*7c478bd9Sstevel@tonic-gate xmt_type = 1; 1402*7c478bd9Sstevel@tonic-gate } 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate break; 1405*7c478bd9Sstevel@tonic-gate 1406*7c478bd9Sstevel@tonic-gate default: /* either RAW or unknown, send as is */ 1407*7c478bd9Sstevel@tonic-gate break; 1408*7c478bd9Sstevel@tonic-gate } 1409*7c478bd9Sstevel@tonic-gate DB_TYPE(nmp) = M_DATA; /* ether/llc header is data */ 1410*7c478bd9Sstevel@tonic-gate nmp->b_cont = mp->b_cont; /* use the data given */ 1411*7c478bd9Sstevel@tonic-gate freeb(mp); 1412*7c478bd9Sstevel@tonic-gate mp = nmp; 1413*7c478bd9Sstevel@tonic-gate } else { 1414*7c478bd9Sstevel@tonic-gate /* need to format a DL_UNITDATA_REQ with LLC1 header inserted */ 1415*7c478bd9Sstevel@tonic-gate nmp = allocb(sizeof (struct llchdr)+sizeof (struct snaphdr), 1416*7c478bd9Sstevel@tonic-gate BPRI_MED); 1417*7c478bd9Sstevel@tonic-gate if (nmp == NULL) 1418*7c478bd9Sstevel@tonic-gate return (DL_UNDELIVERABLE); 1419*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(nmp->b_rptr); 1420*7c478bd9Sstevel@tonic-gate nmp->b_wptr += sizeof (struct llchdr); 1421*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap = llcp->llca_sap; 1422*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap = lld->llc_sap; 1423*7c478bd9Sstevel@tonic-gate llchdr->llc_ctl = LLC_UI; 1424*7c478bd9Sstevel@tonic-gate 1425*7c478bd9Sstevel@tonic-gate /* 1426*7c478bd9Sstevel@tonic-gate * if we are using SNAP, insert the header here 1427*7c478bd9Sstevel@tonic-gate */ 1428*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & LLC_SNAP) { 1429*7c478bd9Sstevel@tonic-gate bcopy(lld->llc_snap, nmp->b_wptr, 5); 1430*7c478bd9Sstevel@tonic-gate nmp->b_wptr += 5; 1431*7c478bd9Sstevel@tonic-gate } 1432*7c478bd9Sstevel@tonic-gate nmp->b_cont = mp->b_cont; 1433*7c478bd9Sstevel@tonic-gate mp->b_cont = nmp; 1434*7c478bd9Sstevel@tonic-gate nmp = mp; 1435*7c478bd9Sstevel@tonic-gate if (ismulticast(llcp->llca_addr)) { 1436*7c478bd9Sstevel@tonic-gate if (bcmp(llcp->llca_addr, 1437*7c478bd9Sstevel@tonic-gate macinfo->llcp_broadcast, ETHERADDRL) == 0) 1438*7c478bd9Sstevel@tonic-gate xmt_type = 2; 1439*7c478bd9Sstevel@tonic-gate else 1440*7c478bd9Sstevel@tonic-gate xmt_type = 1; 1441*7c478bd9Sstevel@tonic-gate } 1442*7c478bd9Sstevel@tonic-gate } 1443*7c478bd9Sstevel@tonic-gate if (canput(macinfo->llcp_queue)) { 1444*7c478bd9Sstevel@tonic-gate lld->llc_stats->llcs_bytexmt += msgdsize(mp); 1445*7c478bd9Sstevel@tonic-gate lld->llc_stats->llcs_pktxmt++; 1446*7c478bd9Sstevel@tonic-gate switch (xmt_type) { 1447*7c478bd9Sstevel@tonic-gate case 1: 1448*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_multixmt++; 1449*7c478bd9Sstevel@tonic-gate break; 1450*7c478bd9Sstevel@tonic-gate case 2: 1451*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_brdcstxmt++; 1452*7c478bd9Sstevel@tonic-gate break; 1453*7c478bd9Sstevel@tonic-gate } 1454*7c478bd9Sstevel@tonic-gate 1455*7c478bd9Sstevel@tonic-gate putnext(macinfo->llcp_queue, mp); 1456*7c478bd9Sstevel@tonic-gate return (LLCE_OK); /* this is almost correct, the result */ 1457*7c478bd9Sstevel@tonic-gate } else { 1458*7c478bd9Sstevel@tonic-gate lld->llc_stats->llcs_nobuffer++; 1459*7c478bd9Sstevel@tonic-gate } 1460*7c478bd9Sstevel@tonic-gate if (nmp != NULL) 1461*7c478bd9Sstevel@tonic-gate freemsg(nmp); /* free on failure */ 1462*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1463*7c478bd9Sstevel@tonic-gate } 1464*7c478bd9Sstevel@tonic-gate 1465*7c478bd9Sstevel@tonic-gate /* 1466*7c478bd9Sstevel@tonic-gate * llc1_recv(macinfo, mp) 1467*7c478bd9Sstevel@tonic-gate * called with an ethernet packet in a mblock; must decide 1468*7c478bd9Sstevel@tonic-gate * whether packet is for us and which streams to queue it to. This routine is 1469*7c478bd9Sstevel@tonic-gate * called with locally originated packets for loopback. 1470*7c478bd9Sstevel@tonic-gate */ 1471*7c478bd9Sstevel@tonic-gate static void 1472*7c478bd9Sstevel@tonic-gate llc1_recv(llc_mac_info_t *macinfo, mblk_t *mp) 1473*7c478bd9Sstevel@tonic-gate { 1474*7c478bd9Sstevel@tonic-gate struct ether_addr *addr; 1475*7c478bd9Sstevel@tonic-gate llc1_t *lld; 1476*7c478bd9Sstevel@tonic-gate mblk_t *nmp, *udmp; 1477*7c478bd9Sstevel@tonic-gate int i, nmcast = 0, statcnt_normal = 0, statcnt_brdcst = 0; 1478*7c478bd9Sstevel@tonic-gate int valid, msgsap; 1479*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 1480*7c478bd9Sstevel@tonic-gate 1481*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1482*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCTRACE) 1483*7c478bd9Sstevel@tonic-gate printf("llc1_recv(%x, %x)\n", mp, macinfo); 1484*7c478bd9Sstevel@tonic-gate #endif 1485*7c478bd9Sstevel@tonic-gate 1486*7c478bd9Sstevel@tonic-gate if (DB_TYPE(mp) == M_PROTO) { 1487*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *udata; 1488*7c478bd9Sstevel@tonic-gate 1489*7c478bd9Sstevel@tonic-gate /* check to see if really LLC1 XXX */ 1490*7c478bd9Sstevel@tonic-gate /* also need to make sure to keep address info */ 1491*7c478bd9Sstevel@tonic-gate nmp = mp; 1492*7c478bd9Sstevel@tonic-gate udata = (dl_unitdata_ind_t *)(nmp->b_rptr); 1493*7c478bd9Sstevel@tonic-gate addr = (struct ether_addr *)(nmp->b_rptr + 1494*7c478bd9Sstevel@tonic-gate udata->dl_dest_addr_offset); 1495*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(nmp->b_cont->b_rptr); 1496*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_type == DL_CSMACD) { 1497*7c478bd9Sstevel@tonic-gate i = ((struct llcsaddr *)addr)->llca_ssap; 1498*7c478bd9Sstevel@tonic-gate if (i < 60) { 1499*7c478bd9Sstevel@tonic-gate valid = adjmsg(mp->b_cont, i - msgdsize(mp)); 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate } 1502*7c478bd9Sstevel@tonic-gate } else { 1503*7c478bd9Sstevel@tonic-gate struct ether_header *hdr; 1504*7c478bd9Sstevel@tonic-gate 1505*7c478bd9Sstevel@tonic-gate /* Note that raw mode currently assumes Ethernet */ 1506*7c478bd9Sstevel@tonic-gate nmp = NULL; 1507*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)mp->b_rptr; 1508*7c478bd9Sstevel@tonic-gate addr = &hdr->ether_dhost; 1509*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(mp->b_rptr + 1510*7c478bd9Sstevel@tonic-gate sizeof (struct ether_header)); 1511*7c478bd9Sstevel@tonic-gate i = (ushort_t)ntohs(hdr->ether_type); 1512*7c478bd9Sstevel@tonic-gate if (i < 60) { 1513*7c478bd9Sstevel@tonic-gate (void) adjmsg(mp, i + sizeof (struct ether_header) - 1514*7c478bd9Sstevel@tonic-gate msgdsize(mp)); 1515*7c478bd9Sstevel@tonic-gate } 1516*7c478bd9Sstevel@tonic-gate } 1517*7c478bd9Sstevel@tonic-gate udmp = NULL; 1518*7c478bd9Sstevel@tonic-gate 1519*7c478bd9Sstevel@tonic-gate msgsap = llchdr->llc_dsap; 1520*7c478bd9Sstevel@tonic-gate 1521*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1522*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCRECV) { 1523*7c478bd9Sstevel@tonic-gate printf("llc1_recv: machdr=<%s>\n", ether_sprintf(addr)); 1524*7c478bd9Sstevel@tonic-gate } 1525*7c478bd9Sstevel@tonic-gate #endif 1526*7c478bd9Sstevel@tonic-gate 1527*7c478bd9Sstevel@tonic-gate if (llc1_broadcast(addr, macinfo)) { 1528*7c478bd9Sstevel@tonic-gate valid = 2; /* 2 means valid but multicast */ 1529*7c478bd9Sstevel@tonic-gate statcnt_brdcst = 1; 1530*7c478bd9Sstevel@tonic-gate } else { 1531*7c478bd9Sstevel@tonic-gate valid = llc1_local(addr, macinfo); 1532*7c478bd9Sstevel@tonic-gate statcnt_normal = msgdsize(mp); 1533*7c478bd9Sstevel@tonic-gate } 1534*7c478bd9Sstevel@tonic-gate 1535*7c478bd9Sstevel@tonic-gate /* 1536*7c478bd9Sstevel@tonic-gate * Note that the NULL SAP is a special case. It is associated with 1537*7c478bd9Sstevel@tonic-gate * the MAC layer and not the LLC layer so should be handled 1538*7c478bd9Sstevel@tonic-gate * independently of any STREAM. 1539*7c478bd9Sstevel@tonic-gate */ 1540*7c478bd9Sstevel@tonic-gate if (msgsap == LLC_NULL_SAP) { 1541*7c478bd9Sstevel@tonic-gate /* only XID and TEST ever processed, UI is dropped */ 1542*7c478bd9Sstevel@tonic-gate if ((llchdr->llc_ctl & ~LLC_P) == LLC_XID) 1543*7c478bd9Sstevel@tonic-gate mp = llc1_xid_reply(macinfo, mp, 0); 1544*7c478bd9Sstevel@tonic-gate else if ((llchdr->llc_ctl & ~LLC_P) == LLC_TEST) 1545*7c478bd9Sstevel@tonic-gate mp = llc1_test_reply(macinfo, mp, 0); 1546*7c478bd9Sstevel@tonic-gate } else 1547*7c478bd9Sstevel@tonic-gate for (lld = llc1_device_list.llc1_str_next; 1548*7c478bd9Sstevel@tonic-gate lld != (llc1_t *)&llc1_device_list.llc1_str_next; 1549*7c478bd9Sstevel@tonic-gate lld = lld->llc_next) { 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate /* 1552*7c478bd9Sstevel@tonic-gate * is this a potentially usable SAP on the 1553*7c478bd9Sstevel@tonic-gate * right MAC layer? 1554*7c478bd9Sstevel@tonic-gate */ 1555*7c478bd9Sstevel@tonic-gate if (lld->llc_qptr == NULL || 1556*7c478bd9Sstevel@tonic-gate lld->llc_state != DL_IDLE || 1557*7c478bd9Sstevel@tonic-gate lld->llc_mac_info != macinfo) { 1558*7c478bd9Sstevel@tonic-gate continue; 1559*7c478bd9Sstevel@tonic-gate } 1560*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1561*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCRECV) 1562*7c478bd9Sstevel@tonic-gate printf( 1563*7c478bd9Sstevel@tonic-gate "llc1_recv: type=%d, sap=%x, pkt-dsap=%x\n", 1564*7c478bd9Sstevel@tonic-gate lld->llc_type, lld->llc_sap, 1565*7c478bd9Sstevel@tonic-gate msgsap); 1566*7c478bd9Sstevel@tonic-gate #endif 1567*7c478bd9Sstevel@tonic-gate if (!valid && ismulticast(addr->ether_addr_octet) && 1568*7c478bd9Sstevel@tonic-gate lld->llc_multicnt > 0 && 1569*7c478bd9Sstevel@tonic-gate llc1_multicast(addr, lld)) { 1570*7c478bd9Sstevel@tonic-gate valid |= 4; 1571*7c478bd9Sstevel@tonic-gate } else if (lld->llc_flags & LLC_PROM) 1572*7c478bd9Sstevel@tonic-gate /* promiscuous mode */ 1573*7c478bd9Sstevel@tonic-gate valid = 1; 1574*7c478bd9Sstevel@tonic-gate 1575*7c478bd9Sstevel@tonic-gate if ((lld->llc_flags & LLC_PROM) || 1576*7c478bd9Sstevel@tonic-gate /* promiscuous streams */ 1577*7c478bd9Sstevel@tonic-gate (valid && 1578*7c478bd9Sstevel@tonic-gate (lld->llc_sap == msgsap || 1579*7c478bd9Sstevel@tonic-gate msgsap == LLC_GLOBAL_SAP))) { 1580*7c478bd9Sstevel@tonic-gate /* sap matches */ 1581*7c478bd9Sstevel@tonic-gate if (msgsap == LLC_SNAP_SAP && 1582*7c478bd9Sstevel@tonic-gate (lld->llc_flags & (LLC_SNAP|LLC_PROM)) == 1583*7c478bd9Sstevel@tonic-gate LLC_SNAP) { 1584*7c478bd9Sstevel@tonic-gate if (!llc1_snap_match(lld, 1585*7c478bd9Sstevel@tonic-gate (struct snaphdr *)(llchdr+1))) 1586*7c478bd9Sstevel@tonic-gate continue; 1587*7c478bd9Sstevel@tonic-gate } 1588*7c478bd9Sstevel@tonic-gate if (!canputnext(RD(lld->llc_qptr))) { 1589*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 1590*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCRECV) 1591*7c478bd9Sstevel@tonic-gate printf( 1592*7c478bd9Sstevel@tonic-gate "llc1_recv: canput failed\n"); 1593*7c478bd9Sstevel@tonic-gate #endif 1594*7c478bd9Sstevel@tonic-gate lld->llc_stats->llcs_blocked++; 1595*7c478bd9Sstevel@tonic-gate continue; 1596*7c478bd9Sstevel@tonic-gate } 1597*7c478bd9Sstevel@tonic-gate /* check for Novell special handling */ 1598*7c478bd9Sstevel@tonic-gate if (msgsap == LLC_GLOBAL_SAP && 1599*7c478bd9Sstevel@tonic-gate lld->llc_sap == LLC_NOVELL_SAP && 1600*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap == LLC_GLOBAL_SAP) { 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate /* A Novell packet */ 1603*7c478bd9Sstevel@tonic-gate nmp = llc1_form_udata(lld, macinfo, mp); 1604*7c478bd9Sstevel@tonic-gate continue; 1605*7c478bd9Sstevel@tonic-gate } 1606*7c478bd9Sstevel@tonic-gate switch (llchdr->llc_ctl) { 1607*7c478bd9Sstevel@tonic-gate case LLC_UI: 1608*7c478bd9Sstevel@tonic-gate /* 1609*7c478bd9Sstevel@tonic-gate * this is an Unnumbered Information 1610*7c478bd9Sstevel@tonic-gate * packet so form a DL_UNITDATA_IND and 1611*7c478bd9Sstevel@tonic-gate * send to user 1612*7c478bd9Sstevel@tonic-gate */ 1613*7c478bd9Sstevel@tonic-gate nmp = llc1_form_udata(lld, macinfo, mp); 1614*7c478bd9Sstevel@tonic-gate break; 1615*7c478bd9Sstevel@tonic-gate 1616*7c478bd9Sstevel@tonic-gate case LLC_XID: 1617*7c478bd9Sstevel@tonic-gate case LLC_XID | LLC_P: 1618*7c478bd9Sstevel@tonic-gate /* 1619*7c478bd9Sstevel@tonic-gate * this is either an XID request or 1620*7c478bd9Sstevel@tonic-gate * response. We either handle directly 1621*7c478bd9Sstevel@tonic-gate * (if user hasn't requested to handle 1622*7c478bd9Sstevel@tonic-gate * itself) or send to user. We also 1623*7c478bd9Sstevel@tonic-gate * must check if a response if user 1624*7c478bd9Sstevel@tonic-gate * handled so that we can send correct 1625*7c478bd9Sstevel@tonic-gate * message form 1626*7c478bd9Sstevel@tonic-gate */ 1627*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & LLC1_AUTO_XID) { 1628*7c478bd9Sstevel@tonic-gate nmp = llc1_xid_reply(macinfo, 1629*7c478bd9Sstevel@tonic-gate mp, lld->llc_sap); 1630*7c478bd9Sstevel@tonic-gate } else { 1631*7c478bd9Sstevel@tonic-gate /* 1632*7c478bd9Sstevel@tonic-gate * hand to the user for 1633*7c478bd9Sstevel@tonic-gate * handling. if this is a 1634*7c478bd9Sstevel@tonic-gate * "request", generate a 1635*7c478bd9Sstevel@tonic-gate * DL_XID_IND. If it is a 1636*7c478bd9Sstevel@tonic-gate * "response" to one of our 1637*7c478bd9Sstevel@tonic-gate * requests, generate a 1638*7c478bd9Sstevel@tonic-gate * DL_XID_CON. 1639*7c478bd9Sstevel@tonic-gate */ 1640*7c478bd9Sstevel@tonic-gate nmp = llc1_xid_ind_con(lld, 1641*7c478bd9Sstevel@tonic-gate macinfo, mp); 1642*7c478bd9Sstevel@tonic-gate } 1643*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_xidrcv++; 1644*7c478bd9Sstevel@tonic-gate break; 1645*7c478bd9Sstevel@tonic-gate 1646*7c478bd9Sstevel@tonic-gate case LLC_TEST: 1647*7c478bd9Sstevel@tonic-gate case LLC_TEST | LLC_P: 1648*7c478bd9Sstevel@tonic-gate /* 1649*7c478bd9Sstevel@tonic-gate * this is either a TEST request or 1650*7c478bd9Sstevel@tonic-gate * response. We either handle 1651*7c478bd9Sstevel@tonic-gate * directly (if user hasn't 1652*7c478bd9Sstevel@tonic-gate * requested to handle itself) 1653*7c478bd9Sstevel@tonic-gate * or send to user. We also 1654*7c478bd9Sstevel@tonic-gate * must check if a response if 1655*7c478bd9Sstevel@tonic-gate * user handled so that we can 1656*7c478bd9Sstevel@tonic-gate * send correct message form 1657*7c478bd9Sstevel@tonic-gate */ 1658*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & LLC1_AUTO_TEST) { 1659*7c478bd9Sstevel@tonic-gate nmp = llc1_test_reply(macinfo, 1660*7c478bd9Sstevel@tonic-gate mp, lld->llc_sap); 1661*7c478bd9Sstevel@tonic-gate } else { 1662*7c478bd9Sstevel@tonic-gate /* 1663*7c478bd9Sstevel@tonic-gate * hand to the user for 1664*7c478bd9Sstevel@tonic-gate * handling. if this is 1665*7c478bd9Sstevel@tonic-gate * a "request", 1666*7c478bd9Sstevel@tonic-gate * generate a 1667*7c478bd9Sstevel@tonic-gate * DL_TEST_IND. If it 1668*7c478bd9Sstevel@tonic-gate * is a "response" to 1669*7c478bd9Sstevel@tonic-gate * one of our requests, 1670*7c478bd9Sstevel@tonic-gate * generate a 1671*7c478bd9Sstevel@tonic-gate * DL_TEST_CON. 1672*7c478bd9Sstevel@tonic-gate */ 1673*7c478bd9Sstevel@tonic-gate nmp = llc1_test_ind_con(lld, 1674*7c478bd9Sstevel@tonic-gate macinfo, mp); 1675*7c478bd9Sstevel@tonic-gate } 1676*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_testrcv++; 1677*7c478bd9Sstevel@tonic-gate break; 1678*7c478bd9Sstevel@tonic-gate default: 1679*7c478bd9Sstevel@tonic-gate nmp = mp; 1680*7c478bd9Sstevel@tonic-gate break; 1681*7c478bd9Sstevel@tonic-gate } 1682*7c478bd9Sstevel@tonic-gate mp = nmp; 1683*7c478bd9Sstevel@tonic-gate } 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate if (mp != NULL) 1686*7c478bd9Sstevel@tonic-gate freemsg(mp); 1687*7c478bd9Sstevel@tonic-gate if (udmp != NULL) 1688*7c478bd9Sstevel@tonic-gate freeb(udmp); 1689*7c478bd9Sstevel@tonic-gate if (nmcast > 0) 1690*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_multircv++; 1691*7c478bd9Sstevel@tonic-gate if (statcnt_brdcst) { 1692*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_brdcstrcv++; 1693*7c478bd9Sstevel@tonic-gate } 1694*7c478bd9Sstevel@tonic-gate if (statcnt_normal) { 1695*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_bytercv += statcnt_normal; 1696*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_pktrcv++; 1697*7c478bd9Sstevel@tonic-gate } 1698*7c478bd9Sstevel@tonic-gate } 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate /* 1701*7c478bd9Sstevel@tonic-gate * llc1_local - check to see if the message is addressed to this system by 1702*7c478bd9Sstevel@tonic-gate * comparing with the board's address. 1703*7c478bd9Sstevel@tonic-gate */ 1704*7c478bd9Sstevel@tonic-gate static int 1705*7c478bd9Sstevel@tonic-gate llc1_local(struct ether_addr *addr, llc_mac_info_t *macinfo) 1706*7c478bd9Sstevel@tonic-gate { 1707*7c478bd9Sstevel@tonic-gate return (bcmp(addr->ether_addr_octet, macinfo->llcp_macaddr, 1708*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen) == 0); 1709*7c478bd9Sstevel@tonic-gate } 1710*7c478bd9Sstevel@tonic-gate 1711*7c478bd9Sstevel@tonic-gate /* 1712*7c478bd9Sstevel@tonic-gate * llc1_broadcast - check to see if a broadcast address is the destination of 1713*7c478bd9Sstevel@tonic-gate * this received packet 1714*7c478bd9Sstevel@tonic-gate */ 1715*7c478bd9Sstevel@tonic-gate static int 1716*7c478bd9Sstevel@tonic-gate llc1_broadcast(struct ether_addr *addr, llc_mac_info_t *macinfo) 1717*7c478bd9Sstevel@tonic-gate { 1718*7c478bd9Sstevel@tonic-gate return (bcmp(addr->ether_addr_octet, macinfo->llcp_broadcast, 1719*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen) == 0); 1720*7c478bd9Sstevel@tonic-gate } 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate /* 1723*7c478bd9Sstevel@tonic-gate * llc1attach(q, mp) DLPI DL_ATTACH_REQ this attaches the stream to a PPA 1724*7c478bd9Sstevel@tonic-gate */ 1725*7c478bd9Sstevel@tonic-gate static int 1726*7c478bd9Sstevel@tonic-gate llc1attach(queue_t *q, mblk_t *mp) 1727*7c478bd9Sstevel@tonic-gate { 1728*7c478bd9Sstevel@tonic-gate dl_attach_req_t *at; 1729*7c478bd9Sstevel@tonic-gate llc_mac_info_t *mac; 1730*7c478bd9Sstevel@tonic-gate llc1_t *llc = (llc1_t *)q->q_ptr; 1731*7c478bd9Sstevel@tonic-gate 1732*7c478bd9Sstevel@tonic-gate at = (dl_attach_req_t *)mp->b_rptr; 1733*7c478bd9Sstevel@tonic-gate 1734*7c478bd9Sstevel@tonic-gate if (llc->llc_state != DL_UNATTACHED) { 1735*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1736*7c478bd9Sstevel@tonic-gate } 1737*7c478bd9Sstevel@tonic-gate llc->llc_state = DL_ATTACH_PENDING; 1738*7c478bd9Sstevel@tonic-gate 1739*7c478bd9Sstevel@tonic-gate if (rw_tryupgrade(&llc1_device_list.llc1_rwlock) == 0) { 1740*7c478bd9Sstevel@tonic-gate /* 1741*7c478bd9Sstevel@tonic-gate * someone else has a lock held. To avoid deadlock, 1742*7c478bd9Sstevel@tonic-gate * release the READER lock and block on a WRITER 1743*7c478bd9Sstevel@tonic-gate * lock. This will let things continue safely. 1744*7c478bd9Sstevel@tonic-gate */ 1745*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 1746*7c478bd9Sstevel@tonic-gate rw_enter(&llc1_device_list.llc1_rwlock, RW_WRITER); 1747*7c478bd9Sstevel@tonic-gate } 1748*7c478bd9Sstevel@tonic-gate 1749*7c478bd9Sstevel@tonic-gate for (mac = llc1_device_list.llc1_mac_next; 1750*7c478bd9Sstevel@tonic-gate mac != (llc_mac_info_t *)(&llc1_device_list.llc1_mac_next); 1751*7c478bd9Sstevel@tonic-gate mac = mac->llcp_next) { 1752*7c478bd9Sstevel@tonic-gate ASSERT(mac); 1753*7c478bd9Sstevel@tonic-gate if (mac->llcp_ppa == at->dl_ppa && mac->llcp_lqtop == q) { 1754*7c478bd9Sstevel@tonic-gate /* 1755*7c478bd9Sstevel@tonic-gate * We may have found the correct PPA 1756*7c478bd9Sstevel@tonic-gate * check to see if linking has finished. 1757*7c478bd9Sstevel@tonic-gate * Use explicit flag checks for incorrect 1758*7c478bd9Sstevel@tonic-gate * state, and use negative values for "tenative" 1759*7c478bd9Sstevel@tonic-gate * llcp_ppas, to avoid erroneous attaches. 1760*7c478bd9Sstevel@tonic-gate */ 1761*7c478bd9Sstevel@tonic-gate if (mac->llcp_flags & 1762*7c478bd9Sstevel@tonic-gate (LLC1_LINKED|LLC1_DEF_PPA)) { 1763*7c478bd9Sstevel@tonic-gate return (DL_INITFAILED); 1764*7c478bd9Sstevel@tonic-gate } else if (!(mac->llcp_flags & LLC1_AVAILABLE)) { 1765*7c478bd9Sstevel@tonic-gate return (DL_BADPPA); 1766*7c478bd9Sstevel@tonic-gate } 1767*7c478bd9Sstevel@tonic-gate 1768*7c478bd9Sstevel@tonic-gate /* this links us to the PPA */ 1769*7c478bd9Sstevel@tonic-gate mac->llcp_nstreams++; 1770*7c478bd9Sstevel@tonic-gate llc->llc_mac_info = mac; 1771*7c478bd9Sstevel@tonic-gate 1772*7c478bd9Sstevel@tonic-gate llc->llc_state = DL_UNBOUND; /* now ready for action */ 1773*7c478bd9Sstevel@tonic-gate llc->llc_stats = &mac->llcp_stats; 1774*7c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_ATTACH_REQ); 1775*7c478bd9Sstevel@tonic-gate 1776*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1777*7c478bd9Sstevel@tonic-gate } 1778*7c478bd9Sstevel@tonic-gate } 1779*7c478bd9Sstevel@tonic-gate llc->llc_state = DL_UNATTACHED; 1780*7c478bd9Sstevel@tonic-gate return (DL_BADPPA); 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate /* 1784*7c478bd9Sstevel@tonic-gate * llc1unattach(q, mp) DLPI DL_DETACH_REQ detaches the mac layer from the 1785*7c478bd9Sstevel@tonic-gate * stream 1786*7c478bd9Sstevel@tonic-gate */ 1787*7c478bd9Sstevel@tonic-gate static int 1788*7c478bd9Sstevel@tonic-gate llc1unattach(queue_t *q, mblk_t *mp) 1789*7c478bd9Sstevel@tonic-gate { 1790*7c478bd9Sstevel@tonic-gate llc1_t *llc = (llc1_t *)q->q_ptr; 1791*7c478bd9Sstevel@tonic-gate int state; 1792*7c478bd9Sstevel@tonic-gate int i; 1793*7c478bd9Sstevel@tonic-gate 1794*7c478bd9Sstevel@tonic-gate state = llc->llc_state; 1795*7c478bd9Sstevel@tonic-gate if (state != DL_UNBOUND) 1796*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1797*7c478bd9Sstevel@tonic-gate 1798*7c478bd9Sstevel@tonic-gate /* can now detach from the PPA */ 1799*7c478bd9Sstevel@tonic-gate llc->llc_state = DL_DETACH_PENDING; 1800*7c478bd9Sstevel@tonic-gate 1801*7c478bd9Sstevel@tonic-gate if (rw_tryupgrade(&llc1_device_list.llc1_rwlock) == 0) { 1802*7c478bd9Sstevel@tonic-gate /* 1803*7c478bd9Sstevel@tonic-gate * someone else has a lock held. To avoid deadlock, 1804*7c478bd9Sstevel@tonic-gate * release the READER lock and block on a WRITER 1805*7c478bd9Sstevel@tonic-gate * lock. This will let things continue safely. 1806*7c478bd9Sstevel@tonic-gate */ 1807*7c478bd9Sstevel@tonic-gate rw_exit(&llc1_device_list.llc1_rwlock); 1808*7c478bd9Sstevel@tonic-gate rw_enter(&llc1_device_list.llc1_rwlock, RW_WRITER); 1809*7c478bd9Sstevel@tonic-gate } 1810*7c478bd9Sstevel@tonic-gate 1811*7c478bd9Sstevel@tonic-gate if (llc->llc_mcast) { 1812*7c478bd9Sstevel@tonic-gate for (i = 0; i < llc1_device_list.llc1_multisize; i++) { 1813*7c478bd9Sstevel@tonic-gate llc_mcast_t *mcast; 1814*7c478bd9Sstevel@tonic-gate 1815*7c478bd9Sstevel@tonic-gate if ((mcast = llc->llc_mcast[i]) != NULL) { 1816*7c478bd9Sstevel@tonic-gate /* disable from stream and possibly lower */ 1817*7c478bd9Sstevel@tonic-gate llc1_send_disable_multi(llc->llc_mac_info, 1818*7c478bd9Sstevel@tonic-gate mcast); 1819*7c478bd9Sstevel@tonic-gate llc->llc_mcast[i] = NULL; 1820*7c478bd9Sstevel@tonic-gate } 1821*7c478bd9Sstevel@tonic-gate } 1822*7c478bd9Sstevel@tonic-gate kmem_free(llc->llc_mcast, 1823*7c478bd9Sstevel@tonic-gate sizeof (llc_mcast_t *) * llc->llc_multicnt); 1824*7c478bd9Sstevel@tonic-gate llc->llc_mcast = NULL; 1825*7c478bd9Sstevel@tonic-gate } 1826*7c478bd9Sstevel@tonic-gate if (llc->llc_mac_info) 1827*7c478bd9Sstevel@tonic-gate llc->llc_mac_info->llcp_nstreams--; 1828*7c478bd9Sstevel@tonic-gate llc->llc_sap = 0; 1829*7c478bd9Sstevel@tonic-gate llc->llc_state = DL_UNATTACHED; 1830*7c478bd9Sstevel@tonic-gate if (mp) { 1831*7c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_DETACH_REQ); 1832*7c478bd9Sstevel@tonic-gate } 1833*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1834*7c478bd9Sstevel@tonic-gate } 1835*7c478bd9Sstevel@tonic-gate 1836*7c478bd9Sstevel@tonic-gate /* 1837*7c478bd9Sstevel@tonic-gate * llc1_enable_multi enables multicast address on the stream if the mac layer 1838*7c478bd9Sstevel@tonic-gate * isn't enabled for this address, enable at that level as well. 1839*7c478bd9Sstevel@tonic-gate */ 1840*7c478bd9Sstevel@tonic-gate static int 1841*7c478bd9Sstevel@tonic-gate llc1_enable_multi(queue_t *q, mblk_t *mp) 1842*7c478bd9Sstevel@tonic-gate { 1843*7c478bd9Sstevel@tonic-gate llc1_t *llc; 1844*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo; 1845*7c478bd9Sstevel@tonic-gate struct ether_addr *maddr; 1846*7c478bd9Sstevel@tonic-gate dl_enabmulti_req_t *multi; 1847*7c478bd9Sstevel@tonic-gate llc_mcast_t *mcast; 1848*7c478bd9Sstevel@tonic-gate int status = DL_BADADDR; 1849*7c478bd9Sstevel@tonic-gate int i; 1850*7c478bd9Sstevel@tonic-gate 1851*7c478bd9Sstevel@tonic-gate #if defined(LLC1_DEBUG) 1852*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCPROT) { 1853*7c478bd9Sstevel@tonic-gate printf("llc1_enable_multi(%x, %x)\n", q, mp); 1854*7c478bd9Sstevel@tonic-gate } 1855*7c478bd9Sstevel@tonic-gate #endif 1856*7c478bd9Sstevel@tonic-gate 1857*7c478bd9Sstevel@tonic-gate llc = (llc1_t *)q->q_ptr; 1858*7c478bd9Sstevel@tonic-gate 1859*7c478bd9Sstevel@tonic-gate if (llc->llc_state == DL_UNATTACHED) 1860*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1861*7c478bd9Sstevel@tonic-gate 1862*7c478bd9Sstevel@tonic-gate macinfo = llc->llc_mac_info; 1863*7c478bd9Sstevel@tonic-gate multi = (dl_enabmulti_req_t *)mp->b_rptr; 1864*7c478bd9Sstevel@tonic-gate maddr = (struct ether_addr *)(mp->b_rptr + multi->dl_addr_offset); 1865*7c478bd9Sstevel@tonic-gate 1866*7c478bd9Sstevel@tonic-gate /* 1867*7c478bd9Sstevel@tonic-gate * check to see if this multicast address is valid if it is, then 1868*7c478bd9Sstevel@tonic-gate * check to see if it is already in the per stream table and the per 1869*7c478bd9Sstevel@tonic-gate * device table if it is already in the per stream table, if it isn't 1870*7c478bd9Sstevel@tonic-gate * in the per device, add it. If it is, just set a pointer. If it 1871*7c478bd9Sstevel@tonic-gate * isn't, allocate what's necessary. 1872*7c478bd9Sstevel@tonic-gate */ 1873*7c478bd9Sstevel@tonic-gate 1874*7c478bd9Sstevel@tonic-gate if (MBLKL(mp) >= sizeof (dl_enabmulti_req_t) && 1875*7c478bd9Sstevel@tonic-gate MBLKIN(mp, multi->dl_addr_offset, multi->dl_addr_length) && 1876*7c478bd9Sstevel@tonic-gate multi->dl_addr_length == macinfo->llcp_addrlen && 1877*7c478bd9Sstevel@tonic-gate ismulticast(maddr->ether_addr_octet)) { 1878*7c478bd9Sstevel@tonic-gate /* request appears to be valid */ 1879*7c478bd9Sstevel@tonic-gate /* does this address appear in current table? */ 1880*7c478bd9Sstevel@tonic-gate if (llc->llc_mcast == NULL) { 1881*7c478bd9Sstevel@tonic-gate /* no mcast addresses -- allocate table */ 1882*7c478bd9Sstevel@tonic-gate llc->llc_mcast = 1883*7c478bd9Sstevel@tonic-gate GETSTRUCT(llc_mcast_t *, 1884*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_multisize); 1885*7c478bd9Sstevel@tonic-gate if (llc->llc_mcast == NULL) 1886*7c478bd9Sstevel@tonic-gate return (DL_SYSERR); 1887*7c478bd9Sstevel@tonic-gate llc->llc_multicnt = llc1_device_list.llc1_multisize; 1888*7c478bd9Sstevel@tonic-gate } else { 1889*7c478bd9Sstevel@tonic-gate for (i = 0; i < llc1_device_list.llc1_multisize; i++) { 1890*7c478bd9Sstevel@tonic-gate if (llc->llc_mcast[i] && 1891*7c478bd9Sstevel@tonic-gate bcmp(llc->llc_mcast[i]->llcm_addr, 1892*7c478bd9Sstevel@tonic-gate maddr->ether_addr_octet, ETHERADDRL)) { 1893*7c478bd9Sstevel@tonic-gate /* this is a match -- just succeed */ 1894*7c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_ENABMULTI_REQ); 1895*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1896*7c478bd9Sstevel@tonic-gate } 1897*7c478bd9Sstevel@tonic-gate } 1898*7c478bd9Sstevel@tonic-gate } 1899*7c478bd9Sstevel@tonic-gate /* 1900*7c478bd9Sstevel@tonic-gate * there wasn't one so check to see if the mac layer has one 1901*7c478bd9Sstevel@tonic-gate */ 1902*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_mcast == NULL) { 1903*7c478bd9Sstevel@tonic-gate macinfo->llcp_mcast = 1904*7c478bd9Sstevel@tonic-gate GETSTRUCT(llc_mcast_t, 1905*7c478bd9Sstevel@tonic-gate llc1_device_list.llc1_multisize); 1906*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_mcast == NULL) 1907*7c478bd9Sstevel@tonic-gate return (DL_SYSERR); 1908*7c478bd9Sstevel@tonic-gate } 1909*7c478bd9Sstevel@tonic-gate for (mcast = NULL, i = 0; 1910*7c478bd9Sstevel@tonic-gate i < llc1_device_list.llc1_multisize; i++) { 1911*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_mcast[i].llcm_refcnt && 1912*7c478bd9Sstevel@tonic-gate bcmp(macinfo->llcp_mcast[i].llcm_addr, 1913*7c478bd9Sstevel@tonic-gate maddr->ether_addr_octet, ETHERADDRL) == 0) { 1914*7c478bd9Sstevel@tonic-gate mcast = &macinfo->llcp_mcast[i]; 1915*7c478bd9Sstevel@tonic-gate break; 1916*7c478bd9Sstevel@tonic-gate } 1917*7c478bd9Sstevel@tonic-gate } 1918*7c478bd9Sstevel@tonic-gate if (mcast == NULL) { 1919*7c478bd9Sstevel@tonic-gate mblk_t *nmp; 1920*7c478bd9Sstevel@tonic-gate 1921*7c478bd9Sstevel@tonic-gate nmp = dupmsg(mp); 1922*7c478bd9Sstevel@tonic-gate if (nmp) { 1923*7c478bd9Sstevel@tonic-gate nmp->b_cont = NULL; 1924*7c478bd9Sstevel@tonic-gate DB_TYPE(nmp) = M_PROTO; 1925*7c478bd9Sstevel@tonic-gate putnext(WR(macinfo->llcp_queue), nmp); 1926*7c478bd9Sstevel@tonic-gate } 1927*7c478bd9Sstevel@tonic-gate /* find an empty slot to fill in */ 1928*7c478bd9Sstevel@tonic-gate for (mcast = macinfo->llcp_mcast, i = 0; 1929*7c478bd9Sstevel@tonic-gate i < llc1_device_list.llc1_multisize; i++, mcast++) { 1930*7c478bd9Sstevel@tonic-gate if (mcast->llcm_refcnt == 0) { 1931*7c478bd9Sstevel@tonic-gate bcopy(maddr->ether_addr_octet, 1932*7c478bd9Sstevel@tonic-gate mcast->llcm_addr, ETHERADDRL); 1933*7c478bd9Sstevel@tonic-gate break; 1934*7c478bd9Sstevel@tonic-gate } 1935*7c478bd9Sstevel@tonic-gate } 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate if (mcast != NULL) { 1938*7c478bd9Sstevel@tonic-gate for (i = 0; i < llc1_device_list.llc1_multisize; i++) { 1939*7c478bd9Sstevel@tonic-gate if (llc->llc_mcast[i] == NULL) { 1940*7c478bd9Sstevel@tonic-gate llc->llc_mcast[i] = mcast; 1941*7c478bd9Sstevel@tonic-gate mcast->llcm_refcnt++; 1942*7c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_ENABMULTI_REQ); 1943*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1944*7c478bd9Sstevel@tonic-gate } 1945*7c478bd9Sstevel@tonic-gate } 1946*7c478bd9Sstevel@tonic-gate } 1947*7c478bd9Sstevel@tonic-gate status = DL_TOOMANY; 1948*7c478bd9Sstevel@tonic-gate } 1949*7c478bd9Sstevel@tonic-gate return (status); 1950*7c478bd9Sstevel@tonic-gate } 1951*7c478bd9Sstevel@tonic-gate 1952*7c478bd9Sstevel@tonic-gate /* 1953*7c478bd9Sstevel@tonic-gate * llc1_disable_multi disable the multicast address on the stream if last 1954*7c478bd9Sstevel@tonic-gate * reference for the mac layer, disable there as well 1955*7c478bd9Sstevel@tonic-gate */ 1956*7c478bd9Sstevel@tonic-gate static int 1957*7c478bd9Sstevel@tonic-gate llc1_disable_multi(queue_t *q, mblk_t *mp) 1958*7c478bd9Sstevel@tonic-gate { 1959*7c478bd9Sstevel@tonic-gate llc1_t *llc; 1960*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo; 1961*7c478bd9Sstevel@tonic-gate struct ether_addr *maddr; 1962*7c478bd9Sstevel@tonic-gate dl_enabmulti_req_t *multi; 1963*7c478bd9Sstevel@tonic-gate int status = DL_BADADDR, i; 1964*7c478bd9Sstevel@tonic-gate llc_mcast_t *mcast; 1965*7c478bd9Sstevel@tonic-gate 1966*7c478bd9Sstevel@tonic-gate #if defined(LLC1_DEBUG) 1967*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCPROT) { 1968*7c478bd9Sstevel@tonic-gate printf("llc1_enable_multi(%x, %x)\n", q, mp); 1969*7c478bd9Sstevel@tonic-gate } 1970*7c478bd9Sstevel@tonic-gate #endif 1971*7c478bd9Sstevel@tonic-gate 1972*7c478bd9Sstevel@tonic-gate llc = (llc1_t *)q->q_ptr; 1973*7c478bd9Sstevel@tonic-gate 1974*7c478bd9Sstevel@tonic-gate if (llc->llc_state == DL_UNATTACHED) 1975*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 1976*7c478bd9Sstevel@tonic-gate 1977*7c478bd9Sstevel@tonic-gate macinfo = llc->llc_mac_info; 1978*7c478bd9Sstevel@tonic-gate multi = (dl_enabmulti_req_t *)mp->b_rptr; 1979*7c478bd9Sstevel@tonic-gate maddr = (struct ether_addr *)(multi + 1); 1980*7c478bd9Sstevel@tonic-gate 1981*7c478bd9Sstevel@tonic-gate if (MBLKL(mp) >= sizeof (dl_enabmulti_req_t) && 1982*7c478bd9Sstevel@tonic-gate MBLKIN(mp, multi->dl_addr_offset, multi->dl_addr_length)) { 1983*7c478bd9Sstevel@tonic-gate /* request appears to be valid */ 1984*7c478bd9Sstevel@tonic-gate /* does this address appear in current table? */ 1985*7c478bd9Sstevel@tonic-gate if (llc->llc_mcast != NULL) { 1986*7c478bd9Sstevel@tonic-gate for (i = 0; i < llc->llc_multicnt; i++) 1987*7c478bd9Sstevel@tonic-gate if (((mcast = llc->llc_mcast[i]) != NULL) && 1988*7c478bd9Sstevel@tonic-gate mcast->llcm_refcnt && 1989*7c478bd9Sstevel@tonic-gate bcmp(mcast->llcm_addr, 1990*7c478bd9Sstevel@tonic-gate maddr->ether_addr_octet, ETHERADDRL) == 0) { 1991*7c478bd9Sstevel@tonic-gate llc1_send_disable_multi(macinfo, 1992*7c478bd9Sstevel@tonic-gate mcast); 1993*7c478bd9Sstevel@tonic-gate llc->llc_mcast[i] = NULL; 1994*7c478bd9Sstevel@tonic-gate dlokack(q, mp, DL_DISABMULTI_REQ); 1995*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 1996*7c478bd9Sstevel@tonic-gate } 1997*7c478bd9Sstevel@tonic-gate status = DL_NOTENAB; 1998*7c478bd9Sstevel@tonic-gate } 1999*7c478bd9Sstevel@tonic-gate } 2000*7c478bd9Sstevel@tonic-gate return (status); 2001*7c478bd9Sstevel@tonic-gate } 2002*7c478bd9Sstevel@tonic-gate 2003*7c478bd9Sstevel@tonic-gate /* 2004*7c478bd9Sstevel@tonic-gate * llc1_send_disable_multi(llc, macinfo, mcast) this function is used to 2005*7c478bd9Sstevel@tonic-gate * disable a multicast address if the reference count goes to zero. The 2006*7c478bd9Sstevel@tonic-gate * disable request will then be forwarded to the lower stream. 2007*7c478bd9Sstevel@tonic-gate */ 2008*7c478bd9Sstevel@tonic-gate static void 2009*7c478bd9Sstevel@tonic-gate llc1_send_disable_multi(llc_mac_info_t *macinfo, llc_mcast_t *mcast) 2010*7c478bd9Sstevel@tonic-gate { 2011*7c478bd9Sstevel@tonic-gate mblk_t *mp; 2012*7c478bd9Sstevel@tonic-gate dl_disabmulti_req_t *dis; 2013*7c478bd9Sstevel@tonic-gate 2014*7c478bd9Sstevel@tonic-gate if (mcast == NULL) { 2015*7c478bd9Sstevel@tonic-gate return; 2016*7c478bd9Sstevel@tonic-gate } 2017*7c478bd9Sstevel@tonic-gate if (macinfo == NULL || macinfo->llcp_queue == NULL) { 2018*7c478bd9Sstevel@tonic-gate return; 2019*7c478bd9Sstevel@tonic-gate } 2020*7c478bd9Sstevel@tonic-gate if (--mcast->llcm_refcnt > 0) 2021*7c478bd9Sstevel@tonic-gate return; 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate mp = allocb(sizeof (dl_disabmulti_req_t) + ETHERADDRL, BPRI_MED); 2024*7c478bd9Sstevel@tonic-gate if (mp) { 2025*7c478bd9Sstevel@tonic-gate dis = (dl_disabmulti_req_t *)mp->b_rptr; 2026*7c478bd9Sstevel@tonic-gate mp->b_wptr = 2027*7c478bd9Sstevel@tonic-gate mp->b_rptr + sizeof (dl_disabmulti_req_t) + ETHERADDRL; 2028*7c478bd9Sstevel@tonic-gate dis->dl_primitive = DL_DISABMULTI_REQ; 2029*7c478bd9Sstevel@tonic-gate dis->dl_addr_offset = sizeof (dl_disabmulti_req_t); 2030*7c478bd9Sstevel@tonic-gate dis->dl_addr_length = ETHERADDRL; 2031*7c478bd9Sstevel@tonic-gate bcopy(mcast->llcm_addr, 2032*7c478bd9Sstevel@tonic-gate (mp->b_rptr + sizeof (dl_disabmulti_req_t)), ETHERADDRL); 2033*7c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_PROTO; 2034*7c478bd9Sstevel@tonic-gate putnext(WR(macinfo->llcp_queue), mp); 2035*7c478bd9Sstevel@tonic-gate } 2036*7c478bd9Sstevel@tonic-gate } 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate /* 2039*7c478bd9Sstevel@tonic-gate * llc1_findminor(device) searches the per device class list of STREAMS for 2040*7c478bd9Sstevel@tonic-gate * the first minor number not used. Note that we currently don't allocate 2041*7c478bd9Sstevel@tonic-gate * minor 0. 2042*7c478bd9Sstevel@tonic-gate */ 2043*7c478bd9Sstevel@tonic-gate 2044*7c478bd9Sstevel@tonic-gate static minor_t 2045*7c478bd9Sstevel@tonic-gate llc1_findminor(llc1dev_t *device) 2046*7c478bd9Sstevel@tonic-gate { 2047*7c478bd9Sstevel@tonic-gate llc1_t *next; 2048*7c478bd9Sstevel@tonic-gate minor_t minor; 2049*7c478bd9Sstevel@tonic-gate 2050*7c478bd9Sstevel@tonic-gate ASSERT(device != NULL); 2051*7c478bd9Sstevel@tonic-gate for (minor = 1; minor <= MAXMIN32; minor++) { 2052*7c478bd9Sstevel@tonic-gate for (next = device->llc1_str_next; 2053*7c478bd9Sstevel@tonic-gate next != NULL && next != (llc1_t *)&device->llc1_str_next; 2054*7c478bd9Sstevel@tonic-gate next = next->llc_next) { 2055*7c478bd9Sstevel@tonic-gate if (minor == next->llc_minor) 2056*7c478bd9Sstevel@tonic-gate goto nextminor; 2057*7c478bd9Sstevel@tonic-gate } 2058*7c478bd9Sstevel@tonic-gate return (minor); 2059*7c478bd9Sstevel@tonic-gate nextminor: 2060*7c478bd9Sstevel@tonic-gate /* don't need to do anything */ 2061*7c478bd9Sstevel@tonic-gate ; 2062*7c478bd9Sstevel@tonic-gate } 2063*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2064*7c478bd9Sstevel@tonic-gate return (0); 2065*7c478bd9Sstevel@tonic-gate } 2066*7c478bd9Sstevel@tonic-gate 2067*7c478bd9Sstevel@tonic-gate /* 2068*7c478bd9Sstevel@tonic-gate * llc1_req_info(q) simply construct a DL_INFO_REQ to be sent to the lower 2069*7c478bd9Sstevel@tonic-gate * stream this is used to populate the macinfo structure. 2070*7c478bd9Sstevel@tonic-gate */ 2071*7c478bd9Sstevel@tonic-gate static int 2072*7c478bd9Sstevel@tonic-gate llc1_req_info(queue_t *q) 2073*7c478bd9Sstevel@tonic-gate { 2074*7c478bd9Sstevel@tonic-gate dl_info_req_t *info; 2075*7c478bd9Sstevel@tonic-gate mblk_t *mp; 2076*7c478bd9Sstevel@tonic-gate 2077*7c478bd9Sstevel@tonic-gate mp = allocb(DL_INFO_REQ_SIZE, BPRI_MED); 2078*7c478bd9Sstevel@tonic-gate if (mp == NULL) 2079*7c478bd9Sstevel@tonic-gate return (-1); 2080*7c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_PCPROTO; 2081*7c478bd9Sstevel@tonic-gate info = (dl_info_req_t *)mp->b_rptr; 2082*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + DL_INFO_REQ_SIZE; 2083*7c478bd9Sstevel@tonic-gate info->dl_primitive = DL_INFO_REQ; 2084*7c478bd9Sstevel@tonic-gate putnext(q, mp); 2085*7c478bd9Sstevel@tonic-gate return (0); 2086*7c478bd9Sstevel@tonic-gate } 2087*7c478bd9Sstevel@tonic-gate 2088*7c478bd9Sstevel@tonic-gate /* 2089*7c478bd9Sstevel@tonic-gate * llc1_req_raw(macinfo) request that the lower stream enter DLIOCRAW mode 2090*7c478bd9Sstevel@tonic-gate */ 2091*7c478bd9Sstevel@tonic-gate static void 2092*7c478bd9Sstevel@tonic-gate llc1_req_raw(llc_mac_info_t *macinfo) 2093*7c478bd9Sstevel@tonic-gate { 2094*7c478bd9Sstevel@tonic-gate mblk_t *mp; 2095*7c478bd9Sstevel@tonic-gate 2096*7c478bd9Sstevel@tonic-gate mp = mkiocb(DLIOCRAW); 2097*7c478bd9Sstevel@tonic-gate if (mp == NULL) 2098*7c478bd9Sstevel@tonic-gate return; 2099*7c478bd9Sstevel@tonic-gate 2100*7c478bd9Sstevel@tonic-gate macinfo->llcp_iocid = ((struct iocblk *)mp->b_rptr)->ioc_id; 2101*7c478bd9Sstevel@tonic-gate 2102*7c478bd9Sstevel@tonic-gate putnext(macinfo->llcp_queue, mp); 2103*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags |= LLC1_RAW_WAIT; 2104*7c478bd9Sstevel@tonic-gate } 2105*7c478bd9Sstevel@tonic-gate 2106*7c478bd9Sstevel@tonic-gate /* 2107*7c478bd9Sstevel@tonic-gate * llc1_send_bindreq 2108*7c478bd9Sstevel@tonic-gate * if lower stream isn't bound, bind it to something appropriate 2109*7c478bd9Sstevel@tonic-gate */ 2110*7c478bd9Sstevel@tonic-gate static void 2111*7c478bd9Sstevel@tonic-gate llc1_send_bindreq(llc_mac_info_t *macinfo) 2112*7c478bd9Sstevel@tonic-gate { 2113*7c478bd9Sstevel@tonic-gate mblk_t *mp; 2114*7c478bd9Sstevel@tonic-gate dl_bind_req_t *bind; 2115*7c478bd9Sstevel@tonic-gate 2116*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_sap >= 0xFF) { 2117*7c478bd9Sstevel@tonic-gate /* have to quite sometime if the world is failing */ 2118*7c478bd9Sstevel@tonic-gate macinfo->llcp_sap &= ~(LLC1_BINDING|LLC1_AVAILABLE); 2119*7c478bd9Sstevel@tonic-gate return; 2120*7c478bd9Sstevel@tonic-gate } 2121*7c478bd9Sstevel@tonic-gate 2122*7c478bd9Sstevel@tonic-gate mp = allocb(sizeof (dl_bind_req_t), BPRI_MED); 2123*7c478bd9Sstevel@tonic-gate if (mp == NULL) 2124*7c478bd9Sstevel@tonic-gate return; 2125*7c478bd9Sstevel@tonic-gate 2126*7c478bd9Sstevel@tonic-gate bind = (dl_bind_req_t *)mp->b_rptr; 2127*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (dl_bind_req_t); 2128*7c478bd9Sstevel@tonic-gate 2129*7c478bd9Sstevel@tonic-gate bind->dl_primitive = DL_BIND_REQ; 2130*7c478bd9Sstevel@tonic-gate bind->dl_sap = macinfo->llcp_sap += 2; /* starts at 2, inc by 2 */ 2131*7c478bd9Sstevel@tonic-gate macinfo->llcp_flags |= LLC1_BINDING; 2132*7c478bd9Sstevel@tonic-gate bind->dl_max_conind = 0; 2133*7c478bd9Sstevel@tonic-gate bind->dl_service_mode = DL_CLDLS; 2134*7c478bd9Sstevel@tonic-gate bind->dl_conn_mgmt = 0; 2135*7c478bd9Sstevel@tonic-gate bind->dl_xidtest_flg = 0; 2136*7c478bd9Sstevel@tonic-gate putnext(macinfo->llcp_queue, mp); 2137*7c478bd9Sstevel@tonic-gate } 2138*7c478bd9Sstevel@tonic-gate 2139*7c478bd9Sstevel@tonic-gate /* 2140*7c478bd9Sstevel@tonic-gate * llc1_form_udata(lld, macinfo, mp) format a DL_UNITDATA_IND message to be 2141*7c478bd9Sstevel@tonic-gate * sent to the user 2142*7c478bd9Sstevel@tonic-gate */ 2143*7c478bd9Sstevel@tonic-gate static mblk_t * 2144*7c478bd9Sstevel@tonic-gate llc1_form_udata(llc1_t *lld, llc_mac_info_t *macinfo, mblk_t *mp) 2145*7c478bd9Sstevel@tonic-gate { 2146*7c478bd9Sstevel@tonic-gate mblk_t *udmp, *nmp; 2147*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *udata; 2148*7c478bd9Sstevel@tonic-gate struct ether_header *hdr; 2149*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 2150*7c478bd9Sstevel@tonic-gate struct snaphdr *snap; 2151*7c478bd9Sstevel@tonic-gate 2152*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_flags & LLC1_USING_RAW) { 2153*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)mp->b_rptr; 2154*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(hdr + 1); 2155*7c478bd9Sstevel@tonic-gate 2156*7c478bd9Sstevel@tonic-gate /* allocate the DL_UNITDATA_IND M_PROTO header */ 2157*7c478bd9Sstevel@tonic-gate udmp = allocb(sizeof (dl_unitdata_ind_t) + 2158*7c478bd9Sstevel@tonic-gate 2 * (macinfo->llcp_addrlen + 5), BPRI_MED); 2159*7c478bd9Sstevel@tonic-gate if (udmp == NULL) { 2160*7c478bd9Sstevel@tonic-gate /* might as well discard since we can't go further */ 2161*7c478bd9Sstevel@tonic-gate freemsg(mp); 2162*7c478bd9Sstevel@tonic-gate return (NULL); 2163*7c478bd9Sstevel@tonic-gate } 2164*7c478bd9Sstevel@tonic-gate udata = (dl_unitdata_ind_t *)udmp->b_rptr; 2165*7c478bd9Sstevel@tonic-gate udmp->b_wptr += sizeof (dl_unitdata_ind_t); 2166*7c478bd9Sstevel@tonic-gate 2167*7c478bd9Sstevel@tonic-gate nmp = dupmsg(mp); /* make a copy for future streams */ 2168*7c478bd9Sstevel@tonic-gate if (lld->llc_sap != LLC_NOVELL_SAP) 2169*7c478bd9Sstevel@tonic-gate mp->b_rptr += sizeof (struct ether_header) + 2170*7c478bd9Sstevel@tonic-gate sizeof (struct llchdr); 2171*7c478bd9Sstevel@tonic-gate else 2172*7c478bd9Sstevel@tonic-gate mp->b_rptr += sizeof (struct ether_header); 2173*7c478bd9Sstevel@tonic-gate 2174*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & LLC_SNAP) { 2175*7c478bd9Sstevel@tonic-gate mp->b_rptr += sizeof (struct snaphdr); 2176*7c478bd9Sstevel@tonic-gate snap = (struct snaphdr *)(llchdr + 1); 2177*7c478bd9Sstevel@tonic-gate } 2178*7c478bd9Sstevel@tonic-gate 2179*7c478bd9Sstevel@tonic-gate /* 2180*7c478bd9Sstevel@tonic-gate * now setup the DL_UNITDATA_IND header 2181*7c478bd9Sstevel@tonic-gate */ 2182*7c478bd9Sstevel@tonic-gate DB_TYPE(udmp) = M_PROTO; 2183*7c478bd9Sstevel@tonic-gate udata->dl_primitive = DL_UNITDATA_IND; 2184*7c478bd9Sstevel@tonic-gate udata->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t); 2185*7c478bd9Sstevel@tonic-gate bcopy(hdr->ether_dhost.ether_addr_octet, 2186*7c478bd9Sstevel@tonic-gate LLCADDR(udata, udata->dl_dest_addr_offset)->llca_addr, 2187*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 2188*7c478bd9Sstevel@tonic-gate 2189*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & LLC_SNAP) { 2190*7c478bd9Sstevel@tonic-gate udata->dl_dest_addr_length = macinfo->llcp_addrlen + 2; 2191*7c478bd9Sstevel@tonic-gate LLCSADDR(udata, udata->dl_dest_addr_offset)->llca_ssap = 2192*7c478bd9Sstevel@tonic-gate ntohs(*(ushort_t *)snap->snap_type); 2193*7c478bd9Sstevel@tonic-gate } else { 2194*7c478bd9Sstevel@tonic-gate udata->dl_dest_addr_length = macinfo->llcp_addrlen + 1; 2195*7c478bd9Sstevel@tonic-gate LLCADDR(udata, udata->dl_dest_addr_offset)->llca_sap = 2196*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap; 2197*7c478bd9Sstevel@tonic-gate } 2198*7c478bd9Sstevel@tonic-gate udmp->b_wptr += udata->dl_dest_addr_length; 2199*7c478bd9Sstevel@tonic-gate udata->dl_src_addr_offset = udata->dl_dest_addr_length + 2200*7c478bd9Sstevel@tonic-gate udata->dl_dest_addr_offset; 2201*7c478bd9Sstevel@tonic-gate bcopy(hdr->ether_shost.ether_addr_octet, 2202*7c478bd9Sstevel@tonic-gate LLCADDR(udata, udata->dl_src_addr_offset)->llca_addr, 2203*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 2204*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & LLC_SNAP) { 2205*7c478bd9Sstevel@tonic-gate udata->dl_src_addr_length = macinfo->llcp_addrlen + 2; 2206*7c478bd9Sstevel@tonic-gate LLCSADDR(udata, udata->dl_src_addr_offset)->llca_ssap = 2207*7c478bd9Sstevel@tonic-gate ntohs(*(ushort_t *)snap->snap_type); 2208*7c478bd9Sstevel@tonic-gate } else { 2209*7c478bd9Sstevel@tonic-gate udata->dl_src_addr_length = macinfo->llcp_addrlen + 1; 2210*7c478bd9Sstevel@tonic-gate LLCADDR(udata, udata->dl_src_addr_offset)->llca_sap = 2211*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap; 2212*7c478bd9Sstevel@tonic-gate } 2213*7c478bd9Sstevel@tonic-gate udata->dl_group_address = hdr->ether_dhost.ether_addr_octet[0] & 2214*7c478bd9Sstevel@tonic-gate 0x1; 2215*7c478bd9Sstevel@tonic-gate udmp->b_wptr += udata->dl_src_addr_length; 2216*7c478bd9Sstevel@tonic-gate udmp->b_cont = mp; 2217*7c478bd9Sstevel@tonic-gate } else { 2218*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *ud2; 2219*7c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) { 2220*7c478bd9Sstevel@tonic-gate return (mp); /* we can't do anything */ 2221*7c478bd9Sstevel@tonic-gate } 2222*7c478bd9Sstevel@tonic-gate /* if we end up here, we only want to patch the existing M_PROTO */ 2223*7c478bd9Sstevel@tonic-gate nmp = dupmsg(mp); /* make a copy for future streams */ 2224*7c478bd9Sstevel@tonic-gate udata = (dl_unitdata_ind_t *)(mp->b_rptr); 2225*7c478bd9Sstevel@tonic-gate udmp = allocb(MBLKL(mp) + 4, BPRI_MED); 2226*7c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr, udmp->b_rptr, sizeof (dl_unitdata_ind_t)); 2227*7c478bd9Sstevel@tonic-gate ud2 = (dl_unitdata_ind_t *)(udmp->b_rptr); 2228*7c478bd9Sstevel@tonic-gate udmp->b_wptr += sizeof (dl_unitdata_ind_t); 2229*7c478bd9Sstevel@tonic-gate bcopy((caddr_t)mp->b_rptr + udata->dl_dest_addr_offset, 2230*7c478bd9Sstevel@tonic-gate udmp->b_wptr, macinfo->llcp_addrlen); 2231*7c478bd9Sstevel@tonic-gate ud2->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t); 2232*7c478bd9Sstevel@tonic-gate ud2->dl_dest_addr_length = macinfo->llcp_addrlen + 1; 2233*7c478bd9Sstevel@tonic-gate udmp->b_wptr += ud2->dl_dest_addr_length; 2234*7c478bd9Sstevel@tonic-gate bcopy((caddr_t)udmp->b_rptr + udata->dl_src_addr_offset, 2235*7c478bd9Sstevel@tonic-gate udmp->b_wptr, macinfo->llcp_addrlen); 2236*7c478bd9Sstevel@tonic-gate ud2->dl_src_addr_length = ud2->dl_dest_addr_length; 2237*7c478bd9Sstevel@tonic-gate udmp->b_wptr += ud2->dl_src_addr_length; 2238*7c478bd9Sstevel@tonic-gate udmp->b_cont = mp->b_cont; 2239*7c478bd9Sstevel@tonic-gate if (lld->llc_sap != LLC_NOVELL_SAP) 2240*7c478bd9Sstevel@tonic-gate mp->b_cont->b_rptr += sizeof (struct llchdr); 2241*7c478bd9Sstevel@tonic-gate freeb(mp); 2242*7c478bd9Sstevel@tonic-gate 2243*7c478bd9Sstevel@tonic-gate DB_TYPE(udmp) = M_PROTO; 2244*7c478bd9Sstevel@tonic-gate udata = (dl_unitdata_ind_t *)(mp->b_rptr); 2245*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(mp->b_cont->b_rptr); 2246*7c478bd9Sstevel@tonic-gate LLCADDR(udata, udata->dl_dest_addr_offset)->llca_sap = 2247*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap; 2248*7c478bd9Sstevel@tonic-gate LLCADDR(udata, udata->dl_src_addr_offset)->llca_sap = 2249*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap; 2250*7c478bd9Sstevel@tonic-gate } 2251*7c478bd9Sstevel@tonic-gate #ifdef LLC1_DEBUG 2252*7c478bd9Sstevel@tonic-gate if (llc1_debug & LLCRECV) 2253*7c478bd9Sstevel@tonic-gate printf("llc1_recv: queued message to %x (%d)\n", 2254*7c478bd9Sstevel@tonic-gate lld->llc_qptr, lld->llc_minor); 2255*7c478bd9Sstevel@tonic-gate #endif 2256*7c478bd9Sstevel@tonic-gate /* enqueue for the service routine to process */ 2257*7c478bd9Sstevel@tonic-gate putnext(RD(lld->llc_qptr), udmp); 2258*7c478bd9Sstevel@tonic-gate mp = nmp; 2259*7c478bd9Sstevel@tonic-gate return (mp); 2260*7c478bd9Sstevel@tonic-gate } 2261*7c478bd9Sstevel@tonic-gate 2262*7c478bd9Sstevel@tonic-gate /* 2263*7c478bd9Sstevel@tonic-gate * llc1_xid_reply(macinfo, mp) automatic reply to an XID command 2264*7c478bd9Sstevel@tonic-gate */ 2265*7c478bd9Sstevel@tonic-gate static mblk_t * 2266*7c478bd9Sstevel@tonic-gate llc1_xid_reply(llc_mac_info_t *macinfo, mblk_t *mp, int sap) 2267*7c478bd9Sstevel@tonic-gate { 2268*7c478bd9Sstevel@tonic-gate mblk_t *nmp, *rmp; 2269*7c478bd9Sstevel@tonic-gate struct ether_header *hdr, *msgether; 2270*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 2271*7c478bd9Sstevel@tonic-gate struct llchdr *msgllc; 2272*7c478bd9Sstevel@tonic-gate struct llchdr_xid *xid; 2273*7c478bd9Sstevel@tonic-gate 2274*7c478bd9Sstevel@tonic-gate if (DB_TYPE(mp) == M_DATA) { 2275*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)mp->b_rptr; 2276*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(hdr + 1); 2277*7c478bd9Sstevel@tonic-gate } else { 2278*7c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) 2279*7c478bd9Sstevel@tonic-gate return (mp); 2280*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(mp->b_cont->b_rptr); 2281*7c478bd9Sstevel@tonic-gate } 2282*7c478bd9Sstevel@tonic-gate 2283*7c478bd9Sstevel@tonic-gate /* we only want to respond to commands to avoid response loops */ 2284*7c478bd9Sstevel@tonic-gate if (llchdr->llc_ssap & LLC_RESPONSE) 2285*7c478bd9Sstevel@tonic-gate return (mp); 2286*7c478bd9Sstevel@tonic-gate 2287*7c478bd9Sstevel@tonic-gate nmp = allocb(msgdsize(mp) + LLC_XID_INFO_SIZE, BPRI_MED); 2288*7c478bd9Sstevel@tonic-gate if (nmp == NULL) { 2289*7c478bd9Sstevel@tonic-gate return (mp); 2290*7c478bd9Sstevel@tonic-gate } 2291*7c478bd9Sstevel@tonic-gate 2292*7c478bd9Sstevel@tonic-gate /* 2293*7c478bd9Sstevel@tonic-gate * now construct the XID reply frame 2294*7c478bd9Sstevel@tonic-gate */ 2295*7c478bd9Sstevel@tonic-gate if (DB_TYPE(mp) == M_DATA) { 2296*7c478bd9Sstevel@tonic-gate msgether = (struct ether_header *)nmp->b_rptr; 2297*7c478bd9Sstevel@tonic-gate nmp->b_wptr += sizeof (struct ether_header); 2298*7c478bd9Sstevel@tonic-gate bcopy(hdr->ether_shost.ether_addr_octet, 2299*7c478bd9Sstevel@tonic-gate msgether->ether_dhost.ether_addr_octet, 2300*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 2301*7c478bd9Sstevel@tonic-gate bcopy(macinfo->llcp_macaddr, 2302*7c478bd9Sstevel@tonic-gate msgether->ether_shost.ether_addr_octet, 2303*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 2304*7c478bd9Sstevel@tonic-gate msgether->ether_type = htons(sizeof (struct llchdr_xid) + 2305*7c478bd9Sstevel@tonic-gate sizeof (struct llchdr)); 2306*7c478bd9Sstevel@tonic-gate rmp = nmp; 2307*7c478bd9Sstevel@tonic-gate } else { 2308*7c478bd9Sstevel@tonic-gate dl_unitdata_req_t *ud; 2309*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *rud; 2310*7c478bd9Sstevel@tonic-gate rud = (dl_unitdata_ind_t *)mp->b_rptr; 2311*7c478bd9Sstevel@tonic-gate 2312*7c478bd9Sstevel@tonic-gate rmp = allocb(sizeof (dl_unitdata_req_t) + 2313*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen + 5, BPRI_MED); 2314*7c478bd9Sstevel@tonic-gate if (rmp == NULL) 2315*7c478bd9Sstevel@tonic-gate return (mp); 2316*7c478bd9Sstevel@tonic-gate 2317*7c478bd9Sstevel@tonic-gate DB_TYPE(rmp) = M_PROTO; 2318*7c478bd9Sstevel@tonic-gate bzero(rmp->b_rptr, sizeof (dl_unitdata_req_t)); 2319*7c478bd9Sstevel@tonic-gate ud = (dl_unitdata_req_t *)rmp->b_rptr; 2320*7c478bd9Sstevel@tonic-gate ud->dl_primitive = DL_UNITDATA_REQ; 2321*7c478bd9Sstevel@tonic-gate ud->dl_dest_addr_offset = sizeof (dl_unitdata_req_t); 2322*7c478bd9Sstevel@tonic-gate ud->dl_dest_addr_length = macinfo->llcp_addrlen + 1; 2323*7c478bd9Sstevel@tonic-gate 2324*7c478bd9Sstevel@tonic-gate rmp->b_wptr += sizeof (dl_unitdata_req_t); 2325*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(mp->b_rptr, rud->dl_src_addr_offset), 2326*7c478bd9Sstevel@tonic-gate LLCADDR(rmp->b_rptr, ud->dl_dest_addr_offset), 2327*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 2328*7c478bd9Sstevel@tonic-gate LLCADDR(rmp->b_rptr, ud->dl_dest_addr_offset)->llca_sap = 2329*7c478bd9Sstevel@tonic-gate LLCADDR(mp->b_rptr, rud->dl_src_addr_offset)->llca_sap; 2330*7c478bd9Sstevel@tonic-gate rmp->b_wptr += sizeof (struct llcaddr); 2331*7c478bd9Sstevel@tonic-gate rmp->b_cont = nmp; 2332*7c478bd9Sstevel@tonic-gate } 2333*7c478bd9Sstevel@tonic-gate 2334*7c478bd9Sstevel@tonic-gate msgllc = (struct llchdr *)nmp->b_wptr; 2335*7c478bd9Sstevel@tonic-gate xid = (struct llchdr_xid *)(msgllc + 1); 2336*7c478bd9Sstevel@tonic-gate nmp->b_wptr += sizeof (struct llchdr); 2337*7c478bd9Sstevel@tonic-gate 2338*7c478bd9Sstevel@tonic-gate msgllc->llc_dsap = llchdr->llc_ssap; 2339*7c478bd9Sstevel@tonic-gate 2340*7c478bd9Sstevel@tonic-gate /* mark it a response */ 2341*7c478bd9Sstevel@tonic-gate msgllc->llc_ssap = sap | LLC_RESPONSE; 2342*7c478bd9Sstevel@tonic-gate 2343*7c478bd9Sstevel@tonic-gate msgllc->llc_ctl = llchdr->llc_ctl; 2344*7c478bd9Sstevel@tonic-gate xid->llcx_format = LLC_XID_FMTID; 2345*7c478bd9Sstevel@tonic-gate xid->llcx_class = LLC_XID_TYPE_1; 2346*7c478bd9Sstevel@tonic-gate xid->llcx_window = 0; /* we don't have connections yet */ 2347*7c478bd9Sstevel@tonic-gate 2348*7c478bd9Sstevel@tonic-gate nmp->b_wptr += sizeof (struct llchdr_xid); 2349*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_xidxmt++; 2350*7c478bd9Sstevel@tonic-gate putnext(WR(macinfo->llcp_queue), rmp); 2351*7c478bd9Sstevel@tonic-gate return (mp); 2352*7c478bd9Sstevel@tonic-gate } 2353*7c478bd9Sstevel@tonic-gate 2354*7c478bd9Sstevel@tonic-gate /* 2355*7c478bd9Sstevel@tonic-gate * llc1_xid_ind_con(lld, macinfo, mp) form a DL_XID_IND or DL_XID_CON message 2356*7c478bd9Sstevel@tonic-gate * to send to the user since it was requested that the user process these 2357*7c478bd9Sstevel@tonic-gate * messages 2358*7c478bd9Sstevel@tonic-gate */ 2359*7c478bd9Sstevel@tonic-gate static mblk_t * 2360*7c478bd9Sstevel@tonic-gate llc1_xid_ind_con(llc1_t *lld, llc_mac_info_t *macinfo, mblk_t *mp) 2361*7c478bd9Sstevel@tonic-gate { 2362*7c478bd9Sstevel@tonic-gate mblk_t *nmp; 2363*7c478bd9Sstevel@tonic-gate dl_xid_ind_t *xid; 2364*7c478bd9Sstevel@tonic-gate struct ether_header *hdr; 2365*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 2366*7c478bd9Sstevel@tonic-gate int raw; 2367*7c478bd9Sstevel@tonic-gate 2368*7c478bd9Sstevel@tonic-gate nmp = allocb(sizeof (dl_xid_ind_t) + 2 * (macinfo->llcp_addrlen + 1), 2369*7c478bd9Sstevel@tonic-gate BPRI_MED); 2370*7c478bd9Sstevel@tonic-gate if (nmp == NULL) 2371*7c478bd9Sstevel@tonic-gate return (mp); 2372*7c478bd9Sstevel@tonic-gate 2373*7c478bd9Sstevel@tonic-gate if ((raw = (DB_TYPE(mp) == M_DATA)) != 0) { 2374*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)mp->b_rptr; 2375*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(hdr + 1); 2376*7c478bd9Sstevel@tonic-gate } else { 2377*7c478bd9Sstevel@tonic-gate if (mp->b_rptr == NULL) 2378*7c478bd9Sstevel@tonic-gate return (mp); 2379*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)mp->b_cont->b_rptr; 2380*7c478bd9Sstevel@tonic-gate } 2381*7c478bd9Sstevel@tonic-gate 2382*7c478bd9Sstevel@tonic-gate xid = (dl_xid_ind_t *)nmp->b_rptr; 2383*7c478bd9Sstevel@tonic-gate xid->dl_flag = (llchdr->llc_ctl & LLC_P) ? DL_POLL_FINAL : 0; 2384*7c478bd9Sstevel@tonic-gate xid->dl_dest_addr_offset = sizeof (dl_xid_ind_t); 2385*7c478bd9Sstevel@tonic-gate xid->dl_dest_addr_length = macinfo->llcp_addrlen + 1; 2386*7c478bd9Sstevel@tonic-gate 2387*7c478bd9Sstevel@tonic-gate if (raw) { 2388*7c478bd9Sstevel@tonic-gate bcopy(hdr->ether_dhost.ether_addr_octet, 2389*7c478bd9Sstevel@tonic-gate (nmp->b_rptr + xid->dl_dest_addr_offset), 2390*7c478bd9Sstevel@tonic-gate xid->dl_dest_addr_length); 2391*7c478bd9Sstevel@tonic-gate } else { 2392*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *ind; 2393*7c478bd9Sstevel@tonic-gate ind = (dl_unitdata_ind_t *)mp->b_rptr; 2394*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(ind, ind->dl_dest_addr_offset), 2395*7c478bd9Sstevel@tonic-gate (nmp->b_rptr + xid->dl_dest_addr_offset), 2396*7c478bd9Sstevel@tonic-gate xid->dl_dest_addr_length); 2397*7c478bd9Sstevel@tonic-gate } 2398*7c478bd9Sstevel@tonic-gate 2399*7c478bd9Sstevel@tonic-gate LLCADDR(xid, xid->dl_dest_addr_offset)->llca_sap = 2400*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap; 2401*7c478bd9Sstevel@tonic-gate 2402*7c478bd9Sstevel@tonic-gate xid->dl_src_addr_offset = 2403*7c478bd9Sstevel@tonic-gate xid->dl_dest_addr_offset + xid->dl_dest_addr_length; 2404*7c478bd9Sstevel@tonic-gate xid->dl_src_addr_length = xid->dl_dest_addr_length; 2405*7c478bd9Sstevel@tonic-gate 2406*7c478bd9Sstevel@tonic-gate if (raw) { 2407*7c478bd9Sstevel@tonic-gate bcopy(hdr->ether_shost.ether_addr_octet, 2408*7c478bd9Sstevel@tonic-gate (nmp->b_rptr + xid->dl_src_addr_offset), 2409*7c478bd9Sstevel@tonic-gate xid->dl_src_addr_length); 2410*7c478bd9Sstevel@tonic-gate } else { 2411*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *ind; 2412*7c478bd9Sstevel@tonic-gate ind = (dl_unitdata_ind_t *)mp->b_rptr; 2413*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(mp->b_rptr, ind->dl_src_addr_offset), 2414*7c478bd9Sstevel@tonic-gate (nmp->b_rptr + xid->dl_src_addr_offset), 2415*7c478bd9Sstevel@tonic-gate ind->dl_src_addr_length); 2416*7c478bd9Sstevel@tonic-gate } 2417*7c478bd9Sstevel@tonic-gate LLCADDR(nmp->b_rptr, xid->dl_src_addr_offset)->llca_sap = 2418*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap & ~LLC_RESPONSE; 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + sizeof (dl_xid_ind_t) + 2421*7c478bd9Sstevel@tonic-gate 2 * xid->dl_dest_addr_length; 2422*7c478bd9Sstevel@tonic-gate 2423*7c478bd9Sstevel@tonic-gate if (!(llchdr->llc_ssap & LLC_RESPONSE)) { 2424*7c478bd9Sstevel@tonic-gate xid->dl_primitive = DL_XID_IND; 2425*7c478bd9Sstevel@tonic-gate } else { 2426*7c478bd9Sstevel@tonic-gate xid->dl_primitive = DL_XID_CON; 2427*7c478bd9Sstevel@tonic-gate } 2428*7c478bd9Sstevel@tonic-gate 2429*7c478bd9Sstevel@tonic-gate DB_TYPE(nmp) = M_PROTO; 2430*7c478bd9Sstevel@tonic-gate if (raw) { 2431*7c478bd9Sstevel@tonic-gate if (MBLKL(mp) > 2432*7c478bd9Sstevel@tonic-gate (sizeof (struct ether_header) + sizeof (struct llchdr))) { 2433*7c478bd9Sstevel@tonic-gate nmp->b_cont = dupmsg(mp); 2434*7c478bd9Sstevel@tonic-gate if (nmp->b_cont) { 2435*7c478bd9Sstevel@tonic-gate nmp->b_cont->b_rptr += 2436*7c478bd9Sstevel@tonic-gate sizeof (struct ether_header) + 2437*7c478bd9Sstevel@tonic-gate sizeof (struct llchdr); 2438*7c478bd9Sstevel@tonic-gate } 2439*7c478bd9Sstevel@tonic-gate } 2440*7c478bd9Sstevel@tonic-gate } else if (mp->b_cont != NULL && MBLKL(mp->b_cont) > 2441*7c478bd9Sstevel@tonic-gate sizeof (struct llchdr)) { 2442*7c478bd9Sstevel@tonic-gate nmp->b_cont = dupmsg(mp->b_cont); 2443*7c478bd9Sstevel@tonic-gate (void) adjmsg(nmp->b_cont, sizeof (struct llchdr)); 2444*7c478bd9Sstevel@tonic-gate } 2445*7c478bd9Sstevel@tonic-gate putnext(RD(lld->llc_qptr), nmp); 2446*7c478bd9Sstevel@tonic-gate return (mp); 2447*7c478bd9Sstevel@tonic-gate } 2448*7c478bd9Sstevel@tonic-gate 2449*7c478bd9Sstevel@tonic-gate /* 2450*7c478bd9Sstevel@tonic-gate * llc1_xid_req_res(q, mp, req_or_res) the user wants to send an XID message 2451*7c478bd9Sstevel@tonic-gate * or response construct a proper message and put on the net 2452*7c478bd9Sstevel@tonic-gate */ 2453*7c478bd9Sstevel@tonic-gate static int 2454*7c478bd9Sstevel@tonic-gate llc1_xid_req_res(queue_t *q, mblk_t *mp, int req_or_res) 2455*7c478bd9Sstevel@tonic-gate { 2456*7c478bd9Sstevel@tonic-gate dl_xid_req_t *xid = (dl_xid_req_t *)mp->b_rptr; 2457*7c478bd9Sstevel@tonic-gate llc1_t *llc = (llc1_t *)q->q_ptr; 2458*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo; 2459*7c478bd9Sstevel@tonic-gate mblk_t *nmp, *rmp; 2460*7c478bd9Sstevel@tonic-gate struct ether_header *hdr; 2461*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 2462*7c478bd9Sstevel@tonic-gate 2463*7c478bd9Sstevel@tonic-gate if (llc == NULL || llc->llc_state == DL_UNATTACHED) 2464*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 2465*7c478bd9Sstevel@tonic-gate 2466*7c478bd9Sstevel@tonic-gate if (llc->llc_sap == LLC_NOVELL_SAP) 2467*7c478bd9Sstevel@tonic-gate return (DL_NOTSUPPORTED); 2468*7c478bd9Sstevel@tonic-gate 2469*7c478bd9Sstevel@tonic-gate if (llc->llc_flags & DL_AUTO_XID) 2470*7c478bd9Sstevel@tonic-gate return (DL_XIDAUTO); 2471*7c478bd9Sstevel@tonic-gate 2472*7c478bd9Sstevel@tonic-gate macinfo = llc->llc_mac_info; 2473*7c478bd9Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_xid_req_t) || 2474*7c478bd9Sstevel@tonic-gate !MBLKIN(mp, xid->dl_dest_addr_offset, xid->dl_dest_addr_length)) { 2475*7c478bd9Sstevel@tonic-gate return (DL_BADPRIM); 2476*7c478bd9Sstevel@tonic-gate } 2477*7c478bd9Sstevel@tonic-gate 2478*7c478bd9Sstevel@tonic-gate nmp = allocb(sizeof (struct ether_header) + sizeof (struct llchdr) + 2479*7c478bd9Sstevel@tonic-gate sizeof (struct llchdr_xid), BPRI_MED); 2480*7c478bd9Sstevel@tonic-gate 2481*7c478bd9Sstevel@tonic-gate if (nmp == NULL) 2482*7c478bd9Sstevel@tonic-gate return (LLCE_NOBUFFER); 2483*7c478bd9Sstevel@tonic-gate 2484*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_flags & LLC1_USING_RAW) { 2485*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)nmp->b_rptr; 2486*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(xid, xid->dl_dest_addr_offset)->llca_addr, 2487*7c478bd9Sstevel@tonic-gate hdr->ether_dhost.ether_addr_octet, ETHERADDRL); 2488*7c478bd9Sstevel@tonic-gate bcopy(macinfo->llcp_macaddr, 2489*7c478bd9Sstevel@tonic-gate hdr->ether_shost.ether_addr_octet, ETHERADDRL); 2490*7c478bd9Sstevel@tonic-gate hdr->ether_type = htons(sizeof (struct llchdr) + msgdsize(mp)); 2491*7c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + 2492*7c478bd9Sstevel@tonic-gate sizeof (struct ether_header) + sizeof (struct llchdr); 2493*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(hdr + 1); 2494*7c478bd9Sstevel@tonic-gate rmp = nmp; 2495*7c478bd9Sstevel@tonic-gate } else { 2496*7c478bd9Sstevel@tonic-gate dl_unitdata_req_t *ud; 2497*7c478bd9Sstevel@tonic-gate rmp = allocb(sizeof (dl_unitdata_req_t) + 2498*7c478bd9Sstevel@tonic-gate (macinfo->llcp_addrlen + 2), BPRI_MED); 2499*7c478bd9Sstevel@tonic-gate if (rmp == NULL) { 2500*7c478bd9Sstevel@tonic-gate freemsg(nmp); 2501*7c478bd9Sstevel@tonic-gate return (LLCE_NOBUFFER); 2502*7c478bd9Sstevel@tonic-gate } 2503*7c478bd9Sstevel@tonic-gate ud = (dl_unitdata_req_t *)rmp->b_rptr; 2504*7c478bd9Sstevel@tonic-gate DB_TYPE(rmp) = M_PROTO; 2505*7c478bd9Sstevel@tonic-gate ud->dl_primitive = DL_UNITDATA_REQ; 2506*7c478bd9Sstevel@tonic-gate ud->dl_dest_addr_offset = sizeof (dl_unitdata_req_t); 2507*7c478bd9Sstevel@tonic-gate ud->dl_dest_addr_length = xid->dl_dest_addr_length; 2508*7c478bd9Sstevel@tonic-gate rmp->b_wptr += sizeof (dl_unitdata_req_t); 2509*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(xid, xid->dl_dest_addr_offset)->llca_addr, 2510*7c478bd9Sstevel@tonic-gate LLCADDR(ud, ud->dl_dest_addr_offset), 2511*7c478bd9Sstevel@tonic-gate xid->dl_dest_addr_length); 2512*7c478bd9Sstevel@tonic-gate LLCSADDR(ud, ud->dl_dest_addr_offset)->llca_ssap = 2513*7c478bd9Sstevel@tonic-gate msgdsize(mp); 2514*7c478bd9Sstevel@tonic-gate rmp->b_wptr += xid->dl_dest_addr_length; 2515*7c478bd9Sstevel@tonic-gate rmp->b_cont = nmp; 2516*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)nmp->b_rptr; 2517*7c478bd9Sstevel@tonic-gate nmp->b_wptr += sizeof (struct llchdr); 2518*7c478bd9Sstevel@tonic-gate } 2519*7c478bd9Sstevel@tonic-gate 2520*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap = LLCADDR(xid, xid->dl_dest_addr_offset)->llca_sap; 2521*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap = llc->llc_sap | (req_or_res ? LLC_RESPONSE : 0); 2522*7c478bd9Sstevel@tonic-gate llchdr->llc_ctl = 2523*7c478bd9Sstevel@tonic-gate LLC_XID | ((xid->dl_flag & DL_POLL_FINAL) ? LLC_P : 0); 2524*7c478bd9Sstevel@tonic-gate 2525*7c478bd9Sstevel@tonic-gate nmp->b_cont = mp->b_cont; 2526*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 2527*7c478bd9Sstevel@tonic-gate freeb(mp); 2528*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_xidxmt++; 2529*7c478bd9Sstevel@tonic-gate putnext(WR(macinfo->llcp_queue), rmp); 2530*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 2531*7c478bd9Sstevel@tonic-gate } 2532*7c478bd9Sstevel@tonic-gate 2533*7c478bd9Sstevel@tonic-gate /* 2534*7c478bd9Sstevel@tonic-gate * llc1_test_reply(macinfo, mp) 2535*7c478bd9Sstevel@tonic-gate * automatic reply to a TEST message 2536*7c478bd9Sstevel@tonic-gate */ 2537*7c478bd9Sstevel@tonic-gate static mblk_t * 2538*7c478bd9Sstevel@tonic-gate llc1_test_reply(llc_mac_info_t *macinfo, mblk_t *mp, int sap) 2539*7c478bd9Sstevel@tonic-gate { 2540*7c478bd9Sstevel@tonic-gate mblk_t *nmp; 2541*7c478bd9Sstevel@tonic-gate struct ether_header *hdr, *msgether; 2542*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 2543*7c478bd9Sstevel@tonic-gate struct llchdr *msgllc; 2544*7c478bd9Sstevel@tonic-gate int poll_final; 2545*7c478bd9Sstevel@tonic-gate 2546*7c478bd9Sstevel@tonic-gate if (DB_TYPE(mp) == M_PROTO) { 2547*7c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL) 2548*7c478bd9Sstevel@tonic-gate return (mp); 2549*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)mp->b_cont->b_rptr; 2550*7c478bd9Sstevel@tonic-gate hdr = NULL; 2551*7c478bd9Sstevel@tonic-gate } else { 2552*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)mp->b_rptr; 2553*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(hdr + 1); 2554*7c478bd9Sstevel@tonic-gate } 2555*7c478bd9Sstevel@tonic-gate 2556*7c478bd9Sstevel@tonic-gate /* we only want to respond to commands to avoid response loops */ 2557*7c478bd9Sstevel@tonic-gate if (llchdr->llc_ssap & LLC_RESPONSE) 2558*7c478bd9Sstevel@tonic-gate return (mp); 2559*7c478bd9Sstevel@tonic-gate 2560*7c478bd9Sstevel@tonic-gate nmp = copymsg(mp); /* so info field is duplicated */ 2561*7c478bd9Sstevel@tonic-gate if (nmp == NULL) { 2562*7c478bd9Sstevel@tonic-gate nmp = mp; 2563*7c478bd9Sstevel@tonic-gate mp = NULL; 2564*7c478bd9Sstevel@tonic-gate } 2565*7c478bd9Sstevel@tonic-gate /* 2566*7c478bd9Sstevel@tonic-gate * now construct the TEST reply frame 2567*7c478bd9Sstevel@tonic-gate */ 2568*7c478bd9Sstevel@tonic-gate 2569*7c478bd9Sstevel@tonic-gate 2570*7c478bd9Sstevel@tonic-gate poll_final = llchdr->llc_ctl & LLC_P; 2571*7c478bd9Sstevel@tonic-gate 2572*7c478bd9Sstevel@tonic-gate if (DB_TYPE(nmp) == M_PROTO) { 2573*7c478bd9Sstevel@tonic-gate dl_unitdata_req_t *udr = (dl_unitdata_req_t *)nmp->b_rptr; 2574*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *udi = (dl_unitdata_ind_t *)nmp->b_rptr; 2575*7c478bd9Sstevel@tonic-gate 2576*7c478bd9Sstevel@tonic-gate /* make into a request */ 2577*7c478bd9Sstevel@tonic-gate udr->dl_primitive = DL_UNITDATA_REQ; 2578*7c478bd9Sstevel@tonic-gate udr->dl_dest_addr_offset = udi->dl_src_addr_offset; 2579*7c478bd9Sstevel@tonic-gate udr->dl_dest_addr_length = udi->dl_src_addr_length; 2580*7c478bd9Sstevel@tonic-gate udr->dl_priority.dl_min = udr->dl_priority.dl_max = 0; 2581*7c478bd9Sstevel@tonic-gate msgllc = (struct llchdr *)nmp->b_cont->b_rptr; 2582*7c478bd9Sstevel@tonic-gate } else { 2583*7c478bd9Sstevel@tonic-gate msgether = (struct ether_header *)nmp->b_rptr; 2584*7c478bd9Sstevel@tonic-gate bcopy(hdr->ether_shost.ether_addr_octet, 2585*7c478bd9Sstevel@tonic-gate msgether->ether_dhost.ether_addr_octet, 2586*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 2587*7c478bd9Sstevel@tonic-gate bcopy(macinfo->llcp_macaddr, 2588*7c478bd9Sstevel@tonic-gate msgether->ether_shost.ether_addr_octet, 2589*7c478bd9Sstevel@tonic-gate macinfo->llcp_addrlen); 2590*7c478bd9Sstevel@tonic-gate msgllc = (struct llchdr *)(msgether+1); 2591*7c478bd9Sstevel@tonic-gate } 2592*7c478bd9Sstevel@tonic-gate 2593*7c478bd9Sstevel@tonic-gate msgllc->llc_dsap = llchdr->llc_ssap; 2594*7c478bd9Sstevel@tonic-gate 2595*7c478bd9Sstevel@tonic-gate /* mark it as a response */ 2596*7c478bd9Sstevel@tonic-gate msgllc->llc_ssap = sap | LLC_RESPONSE; 2597*7c478bd9Sstevel@tonic-gate msgllc->llc_ctl = LLC_TEST | poll_final; 2598*7c478bd9Sstevel@tonic-gate 2599*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_testxmt++; 2600*7c478bd9Sstevel@tonic-gate putnext(WR(macinfo->llcp_queue), nmp); 2601*7c478bd9Sstevel@tonic-gate return (mp); 2602*7c478bd9Sstevel@tonic-gate } 2603*7c478bd9Sstevel@tonic-gate 2604*7c478bd9Sstevel@tonic-gate /* 2605*7c478bd9Sstevel@tonic-gate * llc1_test_ind_con(lld, macinfo, mp) form a DL_TEST_IND or DL_TEST_CON 2606*7c478bd9Sstevel@tonic-gate * message to send to the user since it was requested that the user process 2607*7c478bd9Sstevel@tonic-gate * these messages 2608*7c478bd9Sstevel@tonic-gate */ 2609*7c478bd9Sstevel@tonic-gate static mblk_t * 2610*7c478bd9Sstevel@tonic-gate llc1_test_ind_con(llc1_t *lld, llc_mac_info_t *macinfo, mblk_t *mp) 2611*7c478bd9Sstevel@tonic-gate { 2612*7c478bd9Sstevel@tonic-gate mblk_t *nmp; 2613*7c478bd9Sstevel@tonic-gate dl_test_ind_t *test; 2614*7c478bd9Sstevel@tonic-gate struct ether_header *hdr; 2615*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 2616*7c478bd9Sstevel@tonic-gate int raw; 2617*7c478bd9Sstevel@tonic-gate 2618*7c478bd9Sstevel@tonic-gate nmp = allocb(sizeof (dl_test_ind_t) + 2 * (ETHERADDRL + 1), BPRI_MED); 2619*7c478bd9Sstevel@tonic-gate if (nmp == NULL) 2620*7c478bd9Sstevel@tonic-gate return (NULL); 2621*7c478bd9Sstevel@tonic-gate 2622*7c478bd9Sstevel@tonic-gate if ((raw = (DB_TYPE(mp) == M_DATA)) != 0) { 2623*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)mp->b_rptr; 2624*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(hdr + 1); 2625*7c478bd9Sstevel@tonic-gate } else { 2626*7c478bd9Sstevel@tonic-gate if (mp->b_rptr == NULL) 2627*7c478bd9Sstevel@tonic-gate return (mp); 2628*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)mp->b_cont->b_rptr; 2629*7c478bd9Sstevel@tonic-gate } 2630*7c478bd9Sstevel@tonic-gate 2631*7c478bd9Sstevel@tonic-gate test = (dl_test_ind_t *)nmp->b_rptr; 2632*7c478bd9Sstevel@tonic-gate test->dl_flag = (llchdr->llc_ctl & LLC_P) ? DL_POLL_FINAL : 0; 2633*7c478bd9Sstevel@tonic-gate test->dl_dest_addr_offset = sizeof (dl_test_ind_t); 2634*7c478bd9Sstevel@tonic-gate test->dl_dest_addr_length = macinfo->llcp_addrlen + 1; 2635*7c478bd9Sstevel@tonic-gate 2636*7c478bd9Sstevel@tonic-gate if (raw) { 2637*7c478bd9Sstevel@tonic-gate bcopy(hdr->ether_dhost.ether_addr_octet, 2638*7c478bd9Sstevel@tonic-gate LLCADDR(nmp->b_rptr, test->dl_dest_addr_offset)->llca_addr, 2639*7c478bd9Sstevel@tonic-gate test->dl_dest_addr_length); 2640*7c478bd9Sstevel@tonic-gate } else { 2641*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *ind; 2642*7c478bd9Sstevel@tonic-gate ind = (dl_unitdata_ind_t *)mp->b_rptr; 2643*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(ind, ind->dl_dest_addr_offset), 2644*7c478bd9Sstevel@tonic-gate (nmp->b_rptr + test->dl_dest_addr_offset), 2645*7c478bd9Sstevel@tonic-gate test->dl_dest_addr_length); 2646*7c478bd9Sstevel@tonic-gate } 2647*7c478bd9Sstevel@tonic-gate 2648*7c478bd9Sstevel@tonic-gate LLCADDR(test, test->dl_dest_addr_offset)->llca_sap = 2649*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap; 2650*7c478bd9Sstevel@tonic-gate 2651*7c478bd9Sstevel@tonic-gate test->dl_src_addr_offset = test->dl_dest_addr_offset + 2652*7c478bd9Sstevel@tonic-gate test->dl_dest_addr_length; 2653*7c478bd9Sstevel@tonic-gate test->dl_src_addr_length = test->dl_dest_addr_length; 2654*7c478bd9Sstevel@tonic-gate 2655*7c478bd9Sstevel@tonic-gate if (raw) { 2656*7c478bd9Sstevel@tonic-gate bcopy(hdr->ether_shost.ether_addr_octet, 2657*7c478bd9Sstevel@tonic-gate LLCADDR(nmp->b_rptr, test->dl_src_addr_offset)->llca_addr, 2658*7c478bd9Sstevel@tonic-gate test->dl_src_addr_length); 2659*7c478bd9Sstevel@tonic-gate } else { 2660*7c478bd9Sstevel@tonic-gate dl_unitdata_ind_t *ind; 2661*7c478bd9Sstevel@tonic-gate ind = (dl_unitdata_ind_t *)mp->b_rptr; 2662*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(mp->b_rptr, ind->dl_src_addr_offset), 2663*7c478bd9Sstevel@tonic-gate (nmp->b_rptr + test->dl_src_addr_offset), 2664*7c478bd9Sstevel@tonic-gate ind->dl_src_addr_length); 2665*7c478bd9Sstevel@tonic-gate } 2666*7c478bd9Sstevel@tonic-gate LLCADDR(nmp->b_rptr, test->dl_src_addr_offset)->llca_sap = 2667*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap & ~LLC_RESPONSE; 2668*7c478bd9Sstevel@tonic-gate 2669*7c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + sizeof (dl_test_ind_t) + 2670*7c478bd9Sstevel@tonic-gate 2 * test->dl_dest_addr_length; 2671*7c478bd9Sstevel@tonic-gate 2672*7c478bd9Sstevel@tonic-gate if (!(llchdr->llc_ssap & LLC_RESPONSE)) { 2673*7c478bd9Sstevel@tonic-gate test->dl_primitive = DL_TEST_IND; 2674*7c478bd9Sstevel@tonic-gate } else { 2675*7c478bd9Sstevel@tonic-gate test->dl_primitive = DL_TEST_CON; 2676*7c478bd9Sstevel@tonic-gate } 2677*7c478bd9Sstevel@tonic-gate 2678*7c478bd9Sstevel@tonic-gate DB_TYPE(nmp) = M_PROTO; 2679*7c478bd9Sstevel@tonic-gate if (raw) { 2680*7c478bd9Sstevel@tonic-gate if (MBLKL(mp) > 2681*7c478bd9Sstevel@tonic-gate (sizeof (struct ether_header) + sizeof (struct llchdr))) { 2682*7c478bd9Sstevel@tonic-gate nmp->b_cont = dupmsg(mp); 2683*7c478bd9Sstevel@tonic-gate if (nmp->b_cont) { 2684*7c478bd9Sstevel@tonic-gate nmp->b_cont->b_rptr += 2685*7c478bd9Sstevel@tonic-gate sizeof (struct ether_header) + 2686*7c478bd9Sstevel@tonic-gate sizeof (struct llchdr); 2687*7c478bd9Sstevel@tonic-gate } 2688*7c478bd9Sstevel@tonic-gate } 2689*7c478bd9Sstevel@tonic-gate } else if (mp->b_cont != NULL && MBLKL(mp->b_cont) > 2690*7c478bd9Sstevel@tonic-gate sizeof (struct llchdr)) { 2691*7c478bd9Sstevel@tonic-gate nmp->b_cont = dupmsg(mp->b_cont); 2692*7c478bd9Sstevel@tonic-gate (void) adjmsg(nmp->b_cont, sizeof (struct llchdr)); 2693*7c478bd9Sstevel@tonic-gate } 2694*7c478bd9Sstevel@tonic-gate putnext(RD(lld->llc_qptr), nmp); 2695*7c478bd9Sstevel@tonic-gate return (mp); 2696*7c478bd9Sstevel@tonic-gate } 2697*7c478bd9Sstevel@tonic-gate 2698*7c478bd9Sstevel@tonic-gate /* 2699*7c478bd9Sstevel@tonic-gate * llc1_test_req_res(q, mp, req_or_res) the user wants to send a TEST 2700*7c478bd9Sstevel@tonic-gate * message or response construct a proper message and put on the net 2701*7c478bd9Sstevel@tonic-gate */ 2702*7c478bd9Sstevel@tonic-gate static int 2703*7c478bd9Sstevel@tonic-gate llc1_test_req_res(queue_t *q, mblk_t *mp, int req_or_res) 2704*7c478bd9Sstevel@tonic-gate { 2705*7c478bd9Sstevel@tonic-gate dl_test_req_t *test = (dl_test_req_t *)mp->b_rptr; 2706*7c478bd9Sstevel@tonic-gate llc1_t *llc = (llc1_t *)q->q_ptr; 2707*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo; 2708*7c478bd9Sstevel@tonic-gate mblk_t *nmp, *rmp; 2709*7c478bd9Sstevel@tonic-gate struct ether_header *hdr; 2710*7c478bd9Sstevel@tonic-gate struct llchdr *llchdr; 2711*7c478bd9Sstevel@tonic-gate 2712*7c478bd9Sstevel@tonic-gate if (llc == NULL || llc->llc_state == DL_UNATTACHED) 2713*7c478bd9Sstevel@tonic-gate return (DL_OUTSTATE); 2714*7c478bd9Sstevel@tonic-gate 2715*7c478bd9Sstevel@tonic-gate if (llc->llc_sap == LLC_NOVELL_SAP) 2716*7c478bd9Sstevel@tonic-gate return (DL_NOTSUPPORTED); 2717*7c478bd9Sstevel@tonic-gate 2718*7c478bd9Sstevel@tonic-gate if (llc->llc_flags & DL_AUTO_TEST) 2719*7c478bd9Sstevel@tonic-gate return (DL_TESTAUTO); 2720*7c478bd9Sstevel@tonic-gate 2721*7c478bd9Sstevel@tonic-gate macinfo = llc->llc_mac_info; 2722*7c478bd9Sstevel@tonic-gate if (MBLKL(mp) < sizeof (dl_test_req_t) || 2723*7c478bd9Sstevel@tonic-gate !MBLKIN(mp, test->dl_dest_addr_offset, 2724*7c478bd9Sstevel@tonic-gate test->dl_dest_addr_length)) { 2725*7c478bd9Sstevel@tonic-gate return (DL_BADPRIM); 2726*7c478bd9Sstevel@tonic-gate } 2727*7c478bd9Sstevel@tonic-gate 2728*7c478bd9Sstevel@tonic-gate nmp = allocb(sizeof (struct ether_header) + sizeof (struct llchdr), 2729*7c478bd9Sstevel@tonic-gate BPRI_MED); 2730*7c478bd9Sstevel@tonic-gate 2731*7c478bd9Sstevel@tonic-gate if (nmp == NULL) 2732*7c478bd9Sstevel@tonic-gate return (LLCE_NOBUFFER); 2733*7c478bd9Sstevel@tonic-gate 2734*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_flags & LLC1_USING_RAW) { 2735*7c478bd9Sstevel@tonic-gate hdr = (struct ether_header *)nmp->b_rptr; 2736*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(test, test->dl_dest_addr_offset)->llca_addr, 2737*7c478bd9Sstevel@tonic-gate hdr->ether_dhost.ether_addr_octet, ETHERADDRL); 2738*7c478bd9Sstevel@tonic-gate bcopy(macinfo->llcp_macaddr, 2739*7c478bd9Sstevel@tonic-gate hdr->ether_shost.ether_addr_octet, ETHERADDRL); 2740*7c478bd9Sstevel@tonic-gate hdr->ether_type = htons(sizeof (struct llchdr) + msgdsize(mp)); 2741*7c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + 2742*7c478bd9Sstevel@tonic-gate sizeof (struct ether_header) + sizeof (struct llchdr); 2743*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)(hdr + 1); 2744*7c478bd9Sstevel@tonic-gate rmp = nmp; 2745*7c478bd9Sstevel@tonic-gate } else { 2746*7c478bd9Sstevel@tonic-gate dl_unitdata_req_t *ud; 2747*7c478bd9Sstevel@tonic-gate 2748*7c478bd9Sstevel@tonic-gate rmp = allocb(sizeof (dl_unitdata_req_t) + 2749*7c478bd9Sstevel@tonic-gate (macinfo->llcp_addrlen + 2), BPRI_MED); 2750*7c478bd9Sstevel@tonic-gate if (rmp == NULL) { 2751*7c478bd9Sstevel@tonic-gate freemsg(nmp); 2752*7c478bd9Sstevel@tonic-gate return (LLCE_NOBUFFER); 2753*7c478bd9Sstevel@tonic-gate 2754*7c478bd9Sstevel@tonic-gate } 2755*7c478bd9Sstevel@tonic-gate ud = (dl_unitdata_req_t *)rmp->b_rptr; 2756*7c478bd9Sstevel@tonic-gate DB_TYPE(rmp) = M_PROTO; 2757*7c478bd9Sstevel@tonic-gate ud->dl_primitive = DL_UNITDATA_REQ; 2758*7c478bd9Sstevel@tonic-gate ud->dl_dest_addr_offset = sizeof (dl_unitdata_req_t); 2759*7c478bd9Sstevel@tonic-gate ud->dl_dest_addr_length = test->dl_dest_addr_length; 2760*7c478bd9Sstevel@tonic-gate rmp->b_wptr += sizeof (dl_unitdata_req_t); 2761*7c478bd9Sstevel@tonic-gate bcopy(LLCADDR(test, test->dl_dest_addr_offset)->llca_addr, 2762*7c478bd9Sstevel@tonic-gate LLCADDR(ud, ud->dl_dest_addr_offset), 2763*7c478bd9Sstevel@tonic-gate test->dl_dest_addr_length); 2764*7c478bd9Sstevel@tonic-gate LLCSADDR(ud, ud->dl_dest_addr_offset)->llca_ssap = 2765*7c478bd9Sstevel@tonic-gate msgdsize(mp); 2766*7c478bd9Sstevel@tonic-gate rmp->b_wptr += test->dl_dest_addr_length; 2767*7c478bd9Sstevel@tonic-gate rmp->b_cont = nmp; 2768*7c478bd9Sstevel@tonic-gate llchdr = (struct llchdr *)nmp->b_rptr; 2769*7c478bd9Sstevel@tonic-gate nmp->b_wptr += sizeof (struct llchdr); 2770*7c478bd9Sstevel@tonic-gate } 2771*7c478bd9Sstevel@tonic-gate 2772*7c478bd9Sstevel@tonic-gate llchdr->llc_dsap = LLCADDR(test, test->dl_dest_addr_offset)->llca_sap; 2773*7c478bd9Sstevel@tonic-gate llchdr->llc_ssap = llc->llc_sap | (req_or_res ? LLC_RESPONSE : 0); 2774*7c478bd9Sstevel@tonic-gate llchdr->llc_ctl = 2775*7c478bd9Sstevel@tonic-gate LLC_TEST | ((test->dl_flag & DL_POLL_FINAL) ? LLC_P : 0); 2776*7c478bd9Sstevel@tonic-gate 2777*7c478bd9Sstevel@tonic-gate nmp->b_cont = mp->b_cont; 2778*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 2779*7c478bd9Sstevel@tonic-gate freeb(mp); 2780*7c478bd9Sstevel@tonic-gate macinfo->llcp_stats.llcs_testxmt++; 2781*7c478bd9Sstevel@tonic-gate putnext(WR(macinfo->llcp_queue), rmp); 2782*7c478bd9Sstevel@tonic-gate return (LLCE_OK); 2783*7c478bd9Sstevel@tonic-gate } 2784*7c478bd9Sstevel@tonic-gate 2785*7c478bd9Sstevel@tonic-gate /* 2786*7c478bd9Sstevel@tonic-gate * llc1_find_waiting(macinfo, mp, prim) look for a stream waiting for a 2787*7c478bd9Sstevel@tonic-gate * response to a message identified by prim and send it to the user. 2788*7c478bd9Sstevel@tonic-gate */ 2789*7c478bd9Sstevel@tonic-gate static void 2790*7c478bd9Sstevel@tonic-gate llc1_find_waiting(llc_mac_info_t *macinfo, mblk_t *mp, long prim) 2791*7c478bd9Sstevel@tonic-gate { 2792*7c478bd9Sstevel@tonic-gate llc1_t *llc; 2793*7c478bd9Sstevel@tonic-gate 2794*7c478bd9Sstevel@tonic-gate for (llc = llc1_device_list.llc1_str_next; 2795*7c478bd9Sstevel@tonic-gate llc != (llc1_t *)&llc1_device_list.llc1_str_next; 2796*7c478bd9Sstevel@tonic-gate llc = llc->llc_next) 2797*7c478bd9Sstevel@tonic-gate if (llc->llc_mac_info == macinfo && 2798*7c478bd9Sstevel@tonic-gate prim == llc->llc_waiting_for) { 2799*7c478bd9Sstevel@tonic-gate putnext(RD(llc->llc_qptr), mp); 2800*7c478bd9Sstevel@tonic-gate llc->llc_waiting_for = -1; 2801*7c478bd9Sstevel@tonic-gate return; 2802*7c478bd9Sstevel@tonic-gate } 2803*7c478bd9Sstevel@tonic-gate freemsg(mp); 2804*7c478bd9Sstevel@tonic-gate } 2805*7c478bd9Sstevel@tonic-gate 2806*7c478bd9Sstevel@tonic-gate static void 2807*7c478bd9Sstevel@tonic-gate llc1insque(void *elem, void *pred) 2808*7c478bd9Sstevel@tonic-gate { 2809*7c478bd9Sstevel@tonic-gate struct qelem *pelem = elem; 2810*7c478bd9Sstevel@tonic-gate struct qelem *ppred = pred; 2811*7c478bd9Sstevel@tonic-gate struct qelem *pnext = ppred->q_forw; 2812*7c478bd9Sstevel@tonic-gate 2813*7c478bd9Sstevel@tonic-gate pelem->q_forw = pnext; 2814*7c478bd9Sstevel@tonic-gate pelem->q_back = ppred; 2815*7c478bd9Sstevel@tonic-gate ppred->q_forw = pelem; 2816*7c478bd9Sstevel@tonic-gate pnext->q_back = pelem; 2817*7c478bd9Sstevel@tonic-gate } 2818*7c478bd9Sstevel@tonic-gate 2819*7c478bd9Sstevel@tonic-gate static void 2820*7c478bd9Sstevel@tonic-gate llc1remque(void *arg) 2821*7c478bd9Sstevel@tonic-gate { 2822*7c478bd9Sstevel@tonic-gate struct qelem *pelem = arg; 2823*7c478bd9Sstevel@tonic-gate struct qelem *elem = arg; 2824*7c478bd9Sstevel@tonic-gate 2825*7c478bd9Sstevel@tonic-gate ASSERT(pelem->q_forw != NULL); 2826*7c478bd9Sstevel@tonic-gate pelem->q_forw->q_back = pelem->q_back; 2827*7c478bd9Sstevel@tonic-gate pelem->q_back->q_forw = pelem->q_forw; 2828*7c478bd9Sstevel@tonic-gate elem->q_back = elem->q_forw = NULL; 2829*7c478bd9Sstevel@tonic-gate } 2830*7c478bd9Sstevel@tonic-gate 2831*7c478bd9Sstevel@tonic-gate /* VARARGS */ 2832*7c478bd9Sstevel@tonic-gate static void 2833*7c478bd9Sstevel@tonic-gate llc1error(dip, fmt, a1, a2, a3, a4, a5, a6) 2834*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 2835*7c478bd9Sstevel@tonic-gate char *fmt, *a1, *a2, *a3, *a4, *a5, *a6; 2836*7c478bd9Sstevel@tonic-gate { 2837*7c478bd9Sstevel@tonic-gate static long last; 2838*7c478bd9Sstevel@tonic-gate static char *lastfmt; 2839*7c478bd9Sstevel@tonic-gate time_t now; 2840*7c478bd9Sstevel@tonic-gate 2841*7c478bd9Sstevel@tonic-gate /* 2842*7c478bd9Sstevel@tonic-gate * Don't print same error message too often. 2843*7c478bd9Sstevel@tonic-gate */ 2844*7c478bd9Sstevel@tonic-gate now = gethrestime_sec(); 2845*7c478bd9Sstevel@tonic-gate if ((last == (now & ~1)) && (lastfmt == fmt)) 2846*7c478bd9Sstevel@tonic-gate return; 2847*7c478bd9Sstevel@tonic-gate last = now & ~1; 2848*7c478bd9Sstevel@tonic-gate lastfmt = fmt; 2849*7c478bd9Sstevel@tonic-gate 2850*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s%d: ", 2851*7c478bd9Sstevel@tonic-gate ddi_get_name(dip), ddi_get_instance(dip)); 2852*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5, a6); 2853*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 2854*7c478bd9Sstevel@tonic-gate } 2855*7c478bd9Sstevel@tonic-gate 2856*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 2857*7c478bd9Sstevel@tonic-gate static int 2858*7c478bd9Sstevel@tonic-gate llc1_update_kstat(kstat_t *ksp, int rw) 2859*7c478bd9Sstevel@tonic-gate { 2860*7c478bd9Sstevel@tonic-gate llc_mac_info_t *macinfo; 2861*7c478bd9Sstevel@tonic-gate kstat_named_t *kstat; 2862*7c478bd9Sstevel@tonic-gate struct llc_stats *stats; 2863*7c478bd9Sstevel@tonic-gate 2864*7c478bd9Sstevel@tonic-gate if (ksp == NULL) 2865*7c478bd9Sstevel@tonic-gate return (0); 2866*7c478bd9Sstevel@tonic-gate 2867*7c478bd9Sstevel@tonic-gate kstat = (kstat_named_t *)(ksp->ks_data); 2868*7c478bd9Sstevel@tonic-gate macinfo = (llc_mac_info_t *)(ksp->ks_private); 2869*7c478bd9Sstevel@tonic-gate stats = &macinfo->llcp_stats; 2870*7c478bd9Sstevel@tonic-gate 2871*7c478bd9Sstevel@tonic-gate kstat[LLCS_NOBUFFER].value.ul = stats->llcs_nobuffer; 2872*7c478bd9Sstevel@tonic-gate kstat[LLCS_MULTIXMT].value.ul = stats->llcs_multixmt; 2873*7c478bd9Sstevel@tonic-gate kstat[LLCS_MULTIRCV].value.ul = stats->llcs_multircv; 2874*7c478bd9Sstevel@tonic-gate kstat[LLCS_BRDCSTXMT].value.ul = stats->llcs_brdcstxmt; 2875*7c478bd9Sstevel@tonic-gate kstat[LLCS_BRDCSTRCV].value.ul = stats->llcs_brdcstrcv; 2876*7c478bd9Sstevel@tonic-gate kstat[LLCS_BLOCKED].value.ul = stats->llcs_blocked; 2877*7c478bd9Sstevel@tonic-gate kstat[LLCS_PKTXMT].value.ul = stats->llcs_pktxmt; 2878*7c478bd9Sstevel@tonic-gate kstat[LLCS_PKTRCV].value.ul = stats->llcs_pktrcv; 2879*7c478bd9Sstevel@tonic-gate kstat[LLCS_BYTEXMT].value.ul = stats->llcs_bytexmt; 2880*7c478bd9Sstevel@tonic-gate kstat[LLCS_BYTERCV].value.ul = stats->llcs_bytercv; 2881*7c478bd9Sstevel@tonic-gate kstat[LLCS_XIDXMT].value.ul = stats->llcs_xidxmt; 2882*7c478bd9Sstevel@tonic-gate kstat[LLCS_XIDRCV].value.ul = stats->llcs_xidrcv; 2883*7c478bd9Sstevel@tonic-gate kstat[LLCS_TESTXMT].value.ul = stats->llcs_testxmt; 2884*7c478bd9Sstevel@tonic-gate kstat[LLCS_TESTRCV].value.ul = stats->llcs_testrcv; 2885*7c478bd9Sstevel@tonic-gate kstat[LLCS_IERRORS].value.ul = stats->llcs_ierrors; 2886*7c478bd9Sstevel@tonic-gate kstat[LLCS_OERRORS].value.ul = stats->llcs_oerrors; 2887*7c478bd9Sstevel@tonic-gate return (0); 2888*7c478bd9Sstevel@tonic-gate } 2889*7c478bd9Sstevel@tonic-gate 2890*7c478bd9Sstevel@tonic-gate static void 2891*7c478bd9Sstevel@tonic-gate llc1_init_kstat(llc_mac_info_t *macinfo) 2892*7c478bd9Sstevel@tonic-gate { 2893*7c478bd9Sstevel@tonic-gate kstat_named_t *ksp; 2894*7c478bd9Sstevel@tonic-gate 2895*7c478bd9Sstevel@tonic-gate /* 2896*7c478bd9Sstevel@tonic-gate * Note that the temporary macinfo->llcp_ppa number is negative. 2897*7c478bd9Sstevel@tonic-gate */ 2898*7c478bd9Sstevel@tonic-gate macinfo->llcp_kstatp = kstat_create("llc", (-macinfo->llcp_ppa - 1), 2899*7c478bd9Sstevel@tonic-gate NULL, "net", KSTAT_TYPE_NAMED, 2900*7c478bd9Sstevel@tonic-gate sizeof (struct llc_stats) / sizeof (long), 0); 2901*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_kstatp == NULL) 2902*7c478bd9Sstevel@tonic-gate return; 2903*7c478bd9Sstevel@tonic-gate 2904*7c478bd9Sstevel@tonic-gate macinfo->llcp_kstatp->ks_update = llc1_update_kstat; 2905*7c478bd9Sstevel@tonic-gate macinfo->llcp_kstatp->ks_private = (void *)macinfo; 2906*7c478bd9Sstevel@tonic-gate 2907*7c478bd9Sstevel@tonic-gate ksp = (kstat_named_t *)(macinfo->llcp_kstatp->ks_data); 2908*7c478bd9Sstevel@tonic-gate 2909*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_NOBUFFER], "nobuffer", KSTAT_DATA_ULONG); 2910*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_MULTIXMT], "multixmt", KSTAT_DATA_ULONG); 2911*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_MULTIRCV], "multircv", KSTAT_DATA_ULONG); 2912*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_BRDCSTXMT], "brdcstxmt", KSTAT_DATA_ULONG); 2913*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_BRDCSTRCV], "brdcstrcv", KSTAT_DATA_ULONG); 2914*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_BLOCKED], "blocked", KSTAT_DATA_ULONG); 2915*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_PKTXMT], "pktxmt", KSTAT_DATA_ULONG); 2916*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_PKTRCV], "pktrcv", KSTAT_DATA_ULONG); 2917*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_BYTEXMT], "bytexmt", KSTAT_DATA_ULONG); 2918*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_BYTERCV], "bytercv", KSTAT_DATA_ULONG); 2919*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_XIDXMT], "xidxmt", KSTAT_DATA_ULONG); 2920*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_XIDRCV], "xidrcv", KSTAT_DATA_ULONG); 2921*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_TESTXMT], "testxmt", KSTAT_DATA_ULONG); 2922*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_TESTRCV], "testrcv", KSTAT_DATA_ULONG); 2923*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_IERRORS], "ierrors", KSTAT_DATA_ULONG); 2924*7c478bd9Sstevel@tonic-gate kstat_named_init(&ksp[LLCS_OERRORS], "oerrors", KSTAT_DATA_ULONG); 2925*7c478bd9Sstevel@tonic-gate kstat_install(macinfo->llcp_kstatp); 2926*7c478bd9Sstevel@tonic-gate } 2927*7c478bd9Sstevel@tonic-gate 2928*7c478bd9Sstevel@tonic-gate static void 2929*7c478bd9Sstevel@tonic-gate llc1_uninit_kstat(llc_mac_info_t *macinfo) 2930*7c478bd9Sstevel@tonic-gate { 2931*7c478bd9Sstevel@tonic-gate if (macinfo->llcp_kstatp) { 2932*7c478bd9Sstevel@tonic-gate kstat_delete(macinfo->llcp_kstatp); 2933*7c478bd9Sstevel@tonic-gate macinfo->llcp_kstatp = NULL; 2934*7c478bd9Sstevel@tonic-gate } 2935*7c478bd9Sstevel@tonic-gate } 2936*7c478bd9Sstevel@tonic-gate 2937*7c478bd9Sstevel@tonic-gate /* 2938*7c478bd9Sstevel@tonic-gate * llc1_subs_bind(q, mp) 2939*7c478bd9Sstevel@tonic-gate * implements the DL_SUBS_BIND_REQ primitive 2940*7c478bd9Sstevel@tonic-gate * this only works for a STREAM bound to LLC_SNAP_SAP 2941*7c478bd9Sstevel@tonic-gate * or one bound to the automatic SNAP mode. 2942*7c478bd9Sstevel@tonic-gate * If bound to LLC_SNAP_SAP, the subs bind can be: 2943*7c478bd9Sstevel@tonic-gate * - 2 octets treated as a native byte order short (ethertype) 2944*7c478bd9Sstevel@tonic-gate * - 3 octets treated as a network order byte string (OID part) 2945*7c478bd9Sstevel@tonic-gate * - 5 octets treated as a network order byte string (full SNAP header) 2946*7c478bd9Sstevel@tonic-gate * If bound to an automatic SNAP mode sap, then only the 3 octet 2947*7c478bd9Sstevel@tonic-gate * form is allowed 2948*7c478bd9Sstevel@tonic-gate */ 2949*7c478bd9Sstevel@tonic-gate static int 2950*7c478bd9Sstevel@tonic-gate llc1_subs_bind(queue_t *q, mblk_t *mp) 2951*7c478bd9Sstevel@tonic-gate { 2952*7c478bd9Sstevel@tonic-gate llc1_t *lld = (llc1_t *)q->q_ptr; 2953*7c478bd9Sstevel@tonic-gate dl_subs_bind_req_t *subs = (dl_subs_bind_req_t *)mp->b_rptr; 2954*7c478bd9Sstevel@tonic-gate ushort_t subssap; 2955*7c478bd9Sstevel@tonic-gate uchar_t *sapstr; 2956*7c478bd9Sstevel@tonic-gate int result; 2957*7c478bd9Sstevel@tonic-gate 2958*7c478bd9Sstevel@tonic-gate 2959*7c478bd9Sstevel@tonic-gate #if defined(LLC1_DEBUG) 2960*7c478bd9Sstevel@tonic-gate if (llc1_debug & (LLCTRACE|LLCPROT)) { 2961*7c478bd9Sstevel@tonic-gate printf("llc1_subs_bind (%x, %x)\n", q, mp); 2962*7c478bd9Sstevel@tonic-gate } 2963*7c478bd9Sstevel@tonic-gate #endif 2964*7c478bd9Sstevel@tonic-gate 2965*7c478bd9Sstevel@tonic-gate if (lld == NULL || lld->llc_state != DL_IDLE) { 2966*7c478bd9Sstevel@tonic-gate result = DL_OUTSTATE; 2967*7c478bd9Sstevel@tonic-gate } else if (lld->llc_sap != LLC_SNAP_SAP || 2968*7c478bd9Sstevel@tonic-gate subs->dl_subs_bind_class != DL_HIERARCHICAL_BIND) { 2969*7c478bd9Sstevel@tonic-gate /* we only want to support this for SNAP at present */ 2970*7c478bd9Sstevel@tonic-gate result = DL_UNSUPPORTED; 2971*7c478bd9Sstevel@tonic-gate } else { 2972*7c478bd9Sstevel@tonic-gate 2973*7c478bd9Sstevel@tonic-gate lld->llc_state = DL_SUBS_BIND_PND; 2974*7c478bd9Sstevel@tonic-gate 2975*7c478bd9Sstevel@tonic-gate sapstr = (uchar_t *)(mp->b_rptr + subs->dl_subs_sap_offset); 2976*7c478bd9Sstevel@tonic-gate 2977*7c478bd9Sstevel@tonic-gate result = LLCE_OK; 2978*7c478bd9Sstevel@tonic-gate switch (subs->dl_subs_sap_length) { 2979*7c478bd9Sstevel@tonic-gate case 2: /* just the ethertype part */ 2980*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & LLC_SNAP) { 2981*7c478bd9Sstevel@tonic-gate result = DL_BADADDR; 2982*7c478bd9Sstevel@tonic-gate break; 2983*7c478bd9Sstevel@tonic-gate } 2984*7c478bd9Sstevel@tonic-gate ((uchar_t *)&subssap)[0] = sapstr[0]; 2985*7c478bd9Sstevel@tonic-gate ((uchar_t *)&subssap)[1] = sapstr[1]; 2986*7c478bd9Sstevel@tonic-gate subssap = htons(subssap); 2987*7c478bd9Sstevel@tonic-gate lld->llc_snap[3] = ((uchar_t *)&subssap)[0]; 2988*7c478bd9Sstevel@tonic-gate lld->llc_snap[4] = ((uchar_t *)&subssap)[1]; 2989*7c478bd9Sstevel@tonic-gate lld->llc_flags |= LLC_SNAP; 2990*7c478bd9Sstevel@tonic-gate break; 2991*7c478bd9Sstevel@tonic-gate 2992*7c478bd9Sstevel@tonic-gate case 3: /* just the OID part */ 2993*7c478bd9Sstevel@tonic-gate if ((lld->llc_flags & (LLC_SNAP|LLC_SNAP_OID)) == 2994*7c478bd9Sstevel@tonic-gate (LLC_SNAP|LLC_SNAP_OID)) { 2995*7c478bd9Sstevel@tonic-gate result = DL_BADADDR; 2996*7c478bd9Sstevel@tonic-gate break; 2997*7c478bd9Sstevel@tonic-gate } 2998*7c478bd9Sstevel@tonic-gate bcopy(sapstr, lld->llc_snap, 3); 2999*7c478bd9Sstevel@tonic-gate lld->llc_flags |= LLC_SNAP_OID; 3000*7c478bd9Sstevel@tonic-gate break; 3001*7c478bd9Sstevel@tonic-gate 3002*7c478bd9Sstevel@tonic-gate case 5: /* full SNAP header */ 3003*7c478bd9Sstevel@tonic-gate if (lld->llc_flags & (LLC_SNAP|LLC_SNAP_OID)) { 3004*7c478bd9Sstevel@tonic-gate result = DL_BADADDR; 3005*7c478bd9Sstevel@tonic-gate break; 3006*7c478bd9Sstevel@tonic-gate } 3007*7c478bd9Sstevel@tonic-gate bcopy(sapstr, lld->llc_snap, 5); 3008*7c478bd9Sstevel@tonic-gate lld->llc_flags |= LLC_SNAP|LLC_SNAP_OID; 3009*7c478bd9Sstevel@tonic-gate break; 3010*7c478bd9Sstevel@tonic-gate } 3011*7c478bd9Sstevel@tonic-gate /* if successful, acknowledge and enter the proper state */ 3012*7c478bd9Sstevel@tonic-gate if (result == LLCE_OK) { 3013*7c478bd9Sstevel@tonic-gate mblk_t *nmp = mp; 3014*7c478bd9Sstevel@tonic-gate dl_subs_bind_ack_t *ack; 3015*7c478bd9Sstevel@tonic-gate 3016*7c478bd9Sstevel@tonic-gate if (DB_REF(mp) != 1 || 3017*7c478bd9Sstevel@tonic-gate MBLKL(mp) < (sizeof (dl_subs_bind_ack_t) + 5)) { 3018*7c478bd9Sstevel@tonic-gate freemsg(mp); 3019*7c478bd9Sstevel@tonic-gate nmp = allocb(sizeof (dl_subs_bind_ack_t) + 5, 3020*7c478bd9Sstevel@tonic-gate BPRI_MED); 3021*7c478bd9Sstevel@tonic-gate } 3022*7c478bd9Sstevel@tonic-gate ack = (dl_subs_bind_ack_t *)nmp->b_rptr; 3023*7c478bd9Sstevel@tonic-gate nmp->b_wptr = nmp->b_rptr + 3024*7c478bd9Sstevel@tonic-gate sizeof (dl_subs_bind_ack_t) + 5; 3025*7c478bd9Sstevel@tonic-gate ack->dl_primitive = DL_SUBS_BIND_ACK; 3026*7c478bd9Sstevel@tonic-gate ack->dl_subs_sap_offset = sizeof (dl_subs_bind_ack_t); 3027*7c478bd9Sstevel@tonic-gate ack->dl_subs_sap_length = 5; 3028*7c478bd9Sstevel@tonic-gate bcopy(lld->llc_snap, 3029*7c478bd9Sstevel@tonic-gate (caddr_t)nmp->b_rptr + ack->dl_subs_sap_offset + 5, 3030*7c478bd9Sstevel@tonic-gate 5); 3031*7c478bd9Sstevel@tonic-gate DB_TYPE(nmp) = M_PCPROTO; 3032*7c478bd9Sstevel@tonic-gate qreply(q, nmp); 3033*7c478bd9Sstevel@tonic-gate 3034*7c478bd9Sstevel@tonic-gate } 3035*7c478bd9Sstevel@tonic-gate lld->llc_state = DL_IDLE; 3036*7c478bd9Sstevel@tonic-gate } 3037*7c478bd9Sstevel@tonic-gate return (result); 3038*7c478bd9Sstevel@tonic-gate } 3039*7c478bd9Sstevel@tonic-gate 3040*7c478bd9Sstevel@tonic-gate /* 3041*7c478bd9Sstevel@tonic-gate * 3042*7c478bd9Sstevel@tonic-gate */ 3043*7c478bd9Sstevel@tonic-gate static int 3044*7c478bd9Sstevel@tonic-gate llc1_subs_unbind(void) 3045*7c478bd9Sstevel@tonic-gate { 3046*7c478bd9Sstevel@tonic-gate return (DL_UNSUPPORTED); 3047*7c478bd9Sstevel@tonic-gate } 3048*7c478bd9Sstevel@tonic-gate 3049*7c478bd9Sstevel@tonic-gate char * 3050*7c478bd9Sstevel@tonic-gate snapdmp(uchar_t *bstr) 3051*7c478bd9Sstevel@tonic-gate { 3052*7c478bd9Sstevel@tonic-gate static char buff[32]; 3053*7c478bd9Sstevel@tonic-gate 3054*7c478bd9Sstevel@tonic-gate (void) sprintf(buff, "%x.%x.%x.%x.%x", 3055*7c478bd9Sstevel@tonic-gate bstr[0], 3056*7c478bd9Sstevel@tonic-gate bstr[1], 3057*7c478bd9Sstevel@tonic-gate bstr[2], 3058*7c478bd9Sstevel@tonic-gate bstr[3], 3059*7c478bd9Sstevel@tonic-gate bstr[4]); 3060*7c478bd9Sstevel@tonic-gate return (buff); 3061*7c478bd9Sstevel@tonic-gate } 3062*7c478bd9Sstevel@tonic-gate 3063*7c478bd9Sstevel@tonic-gate static int 3064*7c478bd9Sstevel@tonic-gate llc1_snap_match(llc1_t *lld, struct snaphdr *snap) 3065*7c478bd9Sstevel@tonic-gate { 3066*7c478bd9Sstevel@tonic-gate return (bcmp(snap->snap_oid, lld->llc_snap, 5) == 0); 3067*7c478bd9Sstevel@tonic-gate } 3068