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 2005 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 * Data-Link Provider Interface (Version 2) 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <string.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 38*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 39*7c478bd9Sstevel@tonic-gate #include <unistd.h> 40*7c478bd9Sstevel@tonic-gate #include <poll.h> 41*7c478bd9Sstevel@tonic-gate #include <stropts.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 43*7c478bd9Sstevel@tonic-gate #include <errno.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 45*7c478bd9Sstevel@tonic-gate #include <ctype.h> 46*7c478bd9Sstevel@tonic-gate #include <libdlpi.h> 47*7c478bd9Sstevel@tonic-gate #include <libdladm.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate typedef enum dlpi_multi_op { 50*7c478bd9Sstevel@tonic-gate DLPI_MULTI_DISABLE = 0, 51*7c478bd9Sstevel@tonic-gate DLPI_MULTI_ENABLE 52*7c478bd9Sstevel@tonic-gate } dlpi_multi_op_t; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate typedef enum dlpi_promisc_op { 55*7c478bd9Sstevel@tonic-gate DLPI_PROMISC_OFF = 0, 56*7c478bd9Sstevel@tonic-gate DLPI_PROMISC_ON 57*7c478bd9Sstevel@tonic-gate } dlpi_promisc_op_t; 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate const char *i_dlpi_mac_type[] = { 60*7c478bd9Sstevel@tonic-gate "CSMA/CD", /* 0x00 */ 61*7c478bd9Sstevel@tonic-gate "Token Bus", /* 0x01 */ 62*7c478bd9Sstevel@tonic-gate "Token Ring", /* 0x02 */ 63*7c478bd9Sstevel@tonic-gate "Metro Net", /* 0x03 */ 64*7c478bd9Sstevel@tonic-gate "Ethernet", /* 0x04 */ 65*7c478bd9Sstevel@tonic-gate "HDLC", /* 0x05 */ 66*7c478bd9Sstevel@tonic-gate "Sync Character", /* 0x06 */ 67*7c478bd9Sstevel@tonic-gate "CTCA", /* 0x07 */ 68*7c478bd9Sstevel@tonic-gate "FDDI", /* 0x08 */ 69*7c478bd9Sstevel@tonic-gate "unknown" /* 0x09 */ 70*7c478bd9Sstevel@tonic-gate "Frame Relay (LAPF)", /* 0x0a */ 71*7c478bd9Sstevel@tonic-gate "MP Frame Relay", /* 0x0b */ 72*7c478bd9Sstevel@tonic-gate "Async Character", /* 0x0c */ 73*7c478bd9Sstevel@tonic-gate "X.25 (Classic IP)", /* 0x0d */ 74*7c478bd9Sstevel@tonic-gate "Software Loopback", /* 0x0e */ 75*7c478bd9Sstevel@tonic-gate "undefined", /* 0x0f */ 76*7c478bd9Sstevel@tonic-gate "Fiber Channel", /* 0x10 */ 77*7c478bd9Sstevel@tonic-gate "ATM", /* 0x11 */ 78*7c478bd9Sstevel@tonic-gate "ATM (Classic IP)", /* 0x12 */ 79*7c478bd9Sstevel@tonic-gate "X.25 (LAPB)", /* 0x13 */ 80*7c478bd9Sstevel@tonic-gate "ISDN", /* 0x14 */ 81*7c478bd9Sstevel@tonic-gate "HIPPI", /* 0x15 */ 82*7c478bd9Sstevel@tonic-gate "100BaseVG Ethernet", /* 0x16 */ 83*7c478bd9Sstevel@tonic-gate "100BaseVG Token Ring", /* 0x17 */ 84*7c478bd9Sstevel@tonic-gate "Ethernet/IEEE 802.3", /* 0x18 */ 85*7c478bd9Sstevel@tonic-gate "100BaseT", /* 0x19 */ 86*7c478bd9Sstevel@tonic-gate "Infiniband" /* 0x1a */ 87*7c478bd9Sstevel@tonic-gate }; 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate static int i_dlpi_ifrm_num(char *, unsigned int *); 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate const char * 92*7c478bd9Sstevel@tonic-gate dlpi_mac_type(uint_t type) 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate if (type >= sizeof (i_dlpi_mac_type) / sizeof (i_dlpi_mac_type[0])) 95*7c478bd9Sstevel@tonic-gate return ("ERROR"); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate return (i_dlpi_mac_type[type]); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate static int 101*7c478bd9Sstevel@tonic-gate strputmsg(int fd, uint8_t *ctl_buf, size_t ctl_len, int flags) 102*7c478bd9Sstevel@tonic-gate { 103*7c478bd9Sstevel@tonic-gate struct strbuf ctl; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)ctl_buf; 106*7c478bd9Sstevel@tonic-gate ctl.len = ctl_len; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate return (putmsg(fd, &ctl, NULL, flags)); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate static int 112*7c478bd9Sstevel@tonic-gate strgetmsg(int fd, int timeout, char *ctl_buf, 113*7c478bd9Sstevel@tonic-gate size_t *ctl_lenp, char *data_buf, size_t *data_lenp) 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate struct strbuf ctl; 116*7c478bd9Sstevel@tonic-gate struct strbuf data; 117*7c478bd9Sstevel@tonic-gate int res; 118*7c478bd9Sstevel@tonic-gate struct pollfd pfd; 119*7c478bd9Sstevel@tonic-gate int flags = 0; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate pfd.fd = fd; 122*7c478bd9Sstevel@tonic-gate pfd.events = POLLIN | POLLPRI; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate switch (poll(&pfd, 1, timeout)) { 125*7c478bd9Sstevel@tonic-gate default: 126*7c478bd9Sstevel@tonic-gate ctl.buf = ctl_buf; 127*7c478bd9Sstevel@tonic-gate ctl.len = 0; 128*7c478bd9Sstevel@tonic-gate ctl.maxlen = (ctl_lenp != NULL) ? *ctl_lenp : 0; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate data.buf = data_buf; 131*7c478bd9Sstevel@tonic-gate data.len = 0; 132*7c478bd9Sstevel@tonic-gate data.maxlen = (data_lenp != NULL) ? *data_lenp : 0; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate if ((res = getmsg(fd, &ctl, &data, &flags)) < 0) 135*7c478bd9Sstevel@tonic-gate goto failed; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate if (ctl_buf != NULL) { 138*7c478bd9Sstevel@tonic-gate if (res & MORECTL) { 139*7c478bd9Sstevel@tonic-gate errno = E2BIG; 140*7c478bd9Sstevel@tonic-gate goto failed; 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate *ctl_lenp = ctl.len; 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate if (data_buf != NULL) { 147*7c478bd9Sstevel@tonic-gate if (res & MOREDATA) { 148*7c478bd9Sstevel@tonic-gate errno = E2BIG; 149*7c478bd9Sstevel@tonic-gate goto failed; 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate *data_lenp = data.len; 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate break; 156*7c478bd9Sstevel@tonic-gate case 0: 157*7c478bd9Sstevel@tonic-gate errno = ETIME; 158*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 159*7c478bd9Sstevel@tonic-gate case -1: 160*7c478bd9Sstevel@tonic-gate goto failed; 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate return (0); 164*7c478bd9Sstevel@tonic-gate failed: 165*7c478bd9Sstevel@tonic-gate return (-1); 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate int 169*7c478bd9Sstevel@tonic-gate dlpi_open(const char *provider) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 172*7c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 173*7c478bd9Sstevel@tonic-gate int fd; 174*7c478bd9Sstevel@tonic-gate struct stat st; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "/dev/%s", provider); 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate if ((fd = open(devname, O_RDWR)) != -1) 179*7c478bd9Sstevel@tonic-gate return (fd); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "/devices/pseudo/dld@0:%s", 182*7c478bd9Sstevel@tonic-gate provider); 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate if ((fd = open(devname, O_RDWR)) != -1) 185*7c478bd9Sstevel@tonic-gate return (fd); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate (void) snprintf(path, MAXPATHLEN, "/devices/pseudo/clone@0:%s", 188*7c478bd9Sstevel@tonic-gate provider); 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if (stat(path, &st) == 0) { 191*7c478bd9Sstevel@tonic-gate (void) strlcpy(devname, path, sizeof (devname)); 192*7c478bd9Sstevel@tonic-gate if ((fd = open(devname, O_RDWR)) != -1) 193*7c478bd9Sstevel@tonic-gate return (fd); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate return (-1); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate int 200*7c478bd9Sstevel@tonic-gate dlpi_close(int fd) 201*7c478bd9Sstevel@tonic-gate { 202*7c478bd9Sstevel@tonic-gate return (close(fd)); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate int 206*7c478bd9Sstevel@tonic-gate dlpi_info(int fd, int timeout, dl_info_ack_t *ackp, 207*7c478bd9Sstevel@tonic-gate union DL_qos_types *selp, union DL_qos_types *rangep, 208*7c478bd9Sstevel@tonic-gate uint8_t *addrp, size_t *addrlenp, uint8_t *brdcst_addrp, 209*7c478bd9Sstevel@tonic-gate size_t *brdcst_addrlenp) 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate int rc = -1; 212*7c478bd9Sstevel@tonic-gate size_t size; 213*7c478bd9Sstevel@tonic-gate dl_info_ack_t *buf; 214*7c478bd9Sstevel@tonic-gate dl_info_req_t dlir; 215*7c478bd9Sstevel@tonic-gate dl_info_ack_t *dliap; 216*7c478bd9Sstevel@tonic-gate union DL_qos_types *uqtp; 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate size = sizeof (dl_info_ack_t); /* DL_INFO_ACK */ 219*7c478bd9Sstevel@tonic-gate size += sizeof (union DL_qos_types); /* QoS selections */ 220*7c478bd9Sstevel@tonic-gate size += sizeof (union DL_qos_types); /* QoS ranges */ 221*7c478bd9Sstevel@tonic-gate size += MAXADDRLEN + MAXSAPLEN; /* DLSAP Address */ 222*7c478bd9Sstevel@tonic-gate size += MAXADDRLEN; /* Broadcast Address */ 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 225*7c478bd9Sstevel@tonic-gate return (-1); 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate dlir.dl_primitive = DL_INFO_REQ; 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlir, DL_INFO_REQ_SIZE, RS_HIPRI) == -1) 230*7c478bd9Sstevel@tonic-gate goto done; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 233*7c478bd9Sstevel@tonic-gate goto done; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if (size < DL_INFO_ACK_SIZE) { 236*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 237*7c478bd9Sstevel@tonic-gate goto done; 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate dliap = (dl_info_ack_t *)buf; 241*7c478bd9Sstevel@tonic-gate if (dliap->dl_primitive != DL_INFO_ACK || 242*7c478bd9Sstevel@tonic-gate dliap->dl_version != DL_VERSION_2) { 243*7c478bd9Sstevel@tonic-gate errno = EPROTO; 244*7c478bd9Sstevel@tonic-gate goto done; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate (void) memcpy(ackp, buf, DL_INFO_ACK_SIZE); 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate if (dliap->dl_qos_offset != 0) { 250*7c478bd9Sstevel@tonic-gate if (dliap->dl_qos_length < sizeof (t_uscalar_t)) { 251*7c478bd9Sstevel@tonic-gate errno = EPROTO; 252*7c478bd9Sstevel@tonic-gate goto done; 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate uqtp = (union DL_qos_types *) 256*7c478bd9Sstevel@tonic-gate ((uintptr_t)buf + dliap->dl_qos_offset); 257*7c478bd9Sstevel@tonic-gate if (uqtp->dl_qos_type != DL_QOS_CO_SEL1 && 258*7c478bd9Sstevel@tonic-gate uqtp->dl_qos_type != DL_QOS_CL_SEL1) { 259*7c478bd9Sstevel@tonic-gate errno = EPROTO; 260*7c478bd9Sstevel@tonic-gate goto done; 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (selp != NULL) 264*7c478bd9Sstevel@tonic-gate (void) memcpy(selp, (char *)buf + dliap->dl_qos_offset, 265*7c478bd9Sstevel@tonic-gate dliap->dl_qos_length); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate if (dliap->dl_qos_range_offset != 0) { 269*7c478bd9Sstevel@tonic-gate if (dliap->dl_qos_range_length < sizeof (t_uscalar_t)) { 270*7c478bd9Sstevel@tonic-gate errno = EPROTO; 271*7c478bd9Sstevel@tonic-gate goto done; 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate uqtp = (union DL_qos_types *) 275*7c478bd9Sstevel@tonic-gate ((uintptr_t)buf + dliap->dl_qos_range_offset); 276*7c478bd9Sstevel@tonic-gate if (uqtp->dl_qos_type != DL_QOS_CO_RANGE1 && 277*7c478bd9Sstevel@tonic-gate uqtp->dl_qos_type != DL_QOS_CL_RANGE1) { 278*7c478bd9Sstevel@tonic-gate errno = EPROTO; 279*7c478bd9Sstevel@tonic-gate goto done; 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (rangep != NULL) 283*7c478bd9Sstevel@tonic-gate (void) memcpy(rangep, 284*7c478bd9Sstevel@tonic-gate (char *)buf + dliap->dl_qos_range_offset, 285*7c478bd9Sstevel@tonic-gate dliap->dl_qos_range_length); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate if (dliap->dl_addr_offset != 0) { 289*7c478bd9Sstevel@tonic-gate if (dliap->dl_addr_length == 0) { 290*7c478bd9Sstevel@tonic-gate errno = EPROTO; 291*7c478bd9Sstevel@tonic-gate goto done; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate if (addrlenp != NULL) 295*7c478bd9Sstevel@tonic-gate *addrlenp = dliap->dl_addr_length; 296*7c478bd9Sstevel@tonic-gate if (addrp != NULL) 297*7c478bd9Sstevel@tonic-gate (void) memcpy(addrp, 298*7c478bd9Sstevel@tonic-gate (char *)buf + dliap->dl_addr_offset, 299*7c478bd9Sstevel@tonic-gate dliap->dl_addr_length); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate if (dliap->dl_brdcst_addr_offset != 0) { 303*7c478bd9Sstevel@tonic-gate if (dliap->dl_brdcst_addr_length == 0) { 304*7c478bd9Sstevel@tonic-gate errno = EPROTO; 305*7c478bd9Sstevel@tonic-gate goto done; 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if (brdcst_addrlenp != NULL) 309*7c478bd9Sstevel@tonic-gate *brdcst_addrlenp = dliap->dl_brdcst_addr_length; 310*7c478bd9Sstevel@tonic-gate if (brdcst_addrp != NULL) 311*7c478bd9Sstevel@tonic-gate (void) memcpy(brdcst_addrp, 312*7c478bd9Sstevel@tonic-gate (char *)buf + dliap->dl_brdcst_addr_offset, 313*7c478bd9Sstevel@tonic-gate dliap->dl_brdcst_addr_length); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 317*7c478bd9Sstevel@tonic-gate done: 318*7c478bd9Sstevel@tonic-gate free(buf); 319*7c478bd9Sstevel@tonic-gate return (rc); 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate int 323*7c478bd9Sstevel@tonic-gate dlpi_attach(int fd, int timeout, uint_t ppa) 324*7c478bd9Sstevel@tonic-gate { 325*7c478bd9Sstevel@tonic-gate int rc = -1; 326*7c478bd9Sstevel@tonic-gate size_t size; 327*7c478bd9Sstevel@tonic-gate dl_attach_req_t dlar; 328*7c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 329*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 330*7c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate size = 0; 333*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 334*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 337*7c478bd9Sstevel@tonic-gate return (-1); 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate dlar.dl_primitive = DL_ATTACH_REQ; 340*7c478bd9Sstevel@tonic-gate dlar.dl_ppa = ppa; 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlar, DL_ATTACH_REQ_SIZE, 0) == -1) 343*7c478bd9Sstevel@tonic-gate goto done; 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 346*7c478bd9Sstevel@tonic-gate goto done; 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 349*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 350*7c478bd9Sstevel@tonic-gate goto done; 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 354*7c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 355*7c478bd9Sstevel@tonic-gate case DL_OK_ACK: 356*7c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 357*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 358*7c478bd9Sstevel@tonic-gate goto done; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate break; 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 363*7c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 364*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 365*7c478bd9Sstevel@tonic-gate goto done; 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 369*7c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 370*7c478bd9Sstevel@tonic-gate case DL_BADPPA: 371*7c478bd9Sstevel@tonic-gate errno = EINVAL; 372*7c478bd9Sstevel@tonic-gate break; 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate case DL_ACCESS: 375*7c478bd9Sstevel@tonic-gate errno = EPERM; 376*7c478bd9Sstevel@tonic-gate break; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate case DL_SYSERR: 379*7c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 380*7c478bd9Sstevel@tonic-gate break; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate default: 383*7c478bd9Sstevel@tonic-gate errno = EPROTO; 384*7c478bd9Sstevel@tonic-gate break; 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate goto done; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate default: 390*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 391*7c478bd9Sstevel@tonic-gate goto done; 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 395*7c478bd9Sstevel@tonic-gate done: 396*7c478bd9Sstevel@tonic-gate free(buf); 397*7c478bd9Sstevel@tonic-gate return (rc); 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate int 401*7c478bd9Sstevel@tonic-gate dlpi_detach(int fd, int timeout) 402*7c478bd9Sstevel@tonic-gate { 403*7c478bd9Sstevel@tonic-gate int rc = -1; 404*7c478bd9Sstevel@tonic-gate size_t size; 405*7c478bd9Sstevel@tonic-gate dl_detach_req_t dldr; 406*7c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 407*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 408*7c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate size = 0; 411*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 412*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 415*7c478bd9Sstevel@tonic-gate return (-1); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate dldr.dl_primitive = DL_DETACH_REQ; 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dldr, DL_DETACH_REQ_SIZE, 0) == -1) 420*7c478bd9Sstevel@tonic-gate goto done; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 423*7c478bd9Sstevel@tonic-gate goto done; 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 426*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 427*7c478bd9Sstevel@tonic-gate goto done; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 431*7c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 432*7c478bd9Sstevel@tonic-gate case DL_OK_ACK: 433*7c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 434*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 435*7c478bd9Sstevel@tonic-gate goto done; 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate break; 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 440*7c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 441*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 442*7c478bd9Sstevel@tonic-gate goto done; 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 446*7c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 447*7c478bd9Sstevel@tonic-gate case DL_SYSERR: 448*7c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 449*7c478bd9Sstevel@tonic-gate break; 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate default: 452*7c478bd9Sstevel@tonic-gate errno = EPROTO; 453*7c478bd9Sstevel@tonic-gate break; 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate goto done; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate default: 458*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 459*7c478bd9Sstevel@tonic-gate goto done; 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 463*7c478bd9Sstevel@tonic-gate done: 464*7c478bd9Sstevel@tonic-gate free(buf); 465*7c478bd9Sstevel@tonic-gate return (rc); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate int 469*7c478bd9Sstevel@tonic-gate dlpi_bind(int fd, int timeout, uint_t sap, uint16_t mode, 470*7c478bd9Sstevel@tonic-gate boolean_t conn_mgmt, uint32_t *max_conn_ind, 471*7c478bd9Sstevel@tonic-gate uint32_t *xid_test, uint8_t *addrp, size_t *addrlenp) 472*7c478bd9Sstevel@tonic-gate { 473*7c478bd9Sstevel@tonic-gate int rc = -1; 474*7c478bd9Sstevel@tonic-gate size_t size; 475*7c478bd9Sstevel@tonic-gate dl_bind_req_t dlbr; 476*7c478bd9Sstevel@tonic-gate dl_bind_ack_t *dlbap; 477*7c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 478*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 479*7c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate size = 0; 482*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_bind_ack_t) + MAXADDRLEN + MAXSAPLEN, size); 483*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 486*7c478bd9Sstevel@tonic-gate return (-1); 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate dlbr.dl_primitive = DL_BIND_REQ; 489*7c478bd9Sstevel@tonic-gate dlbr.dl_sap = sap; 490*7c478bd9Sstevel@tonic-gate dlbr.dl_service_mode = mode; 491*7c478bd9Sstevel@tonic-gate dlbr.dl_conn_mgmt = (conn_mgmt) ? 1 : 0; 492*7c478bd9Sstevel@tonic-gate dlbr.dl_max_conind = (max_conn_ind != NULL) ? *max_conn_ind : 0; 493*7c478bd9Sstevel@tonic-gate dlbr.dl_xidtest_flg = (xid_test != NULL) ? *xid_test : 0; 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlbr, DL_BIND_REQ_SIZE, 0) == -1) 496*7c478bd9Sstevel@tonic-gate goto done; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 499*7c478bd9Sstevel@tonic-gate goto done; 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 502*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 503*7c478bd9Sstevel@tonic-gate goto done; 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 507*7c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 508*7c478bd9Sstevel@tonic-gate case DL_BIND_ACK: 509*7c478bd9Sstevel@tonic-gate if (size < DL_BIND_ACK_SIZE) { 510*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 511*7c478bd9Sstevel@tonic-gate goto done; 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate dlbap = (dl_bind_ack_t *)buf; 515*7c478bd9Sstevel@tonic-gate if (max_conn_ind != NULL) 516*7c478bd9Sstevel@tonic-gate *max_conn_ind = dlbap->dl_max_conind; 517*7c478bd9Sstevel@tonic-gate if (xid_test != NULL) 518*7c478bd9Sstevel@tonic-gate *xid_test = dlbap->dl_xidtest_flg; 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate if (dlbap->dl_addr_offset != 0) { 521*7c478bd9Sstevel@tonic-gate if (dlbap->dl_addr_length == 0) { 522*7c478bd9Sstevel@tonic-gate errno = EPROTO; 523*7c478bd9Sstevel@tonic-gate goto done; 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate if (addrlenp != NULL) 527*7c478bd9Sstevel@tonic-gate *addrlenp = dlbap->dl_addr_length; 528*7c478bd9Sstevel@tonic-gate if (addrp != NULL) 529*7c478bd9Sstevel@tonic-gate (void) memcpy(addrp, 530*7c478bd9Sstevel@tonic-gate (char *)buf + dlbap->dl_addr_offset, 531*7c478bd9Sstevel@tonic-gate dlbap->dl_addr_length); 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate break; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 537*7c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 538*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 539*7c478bd9Sstevel@tonic-gate goto done; 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 543*7c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 544*7c478bd9Sstevel@tonic-gate case DL_BADADDR: 545*7c478bd9Sstevel@tonic-gate errno = EINVAL; 546*7c478bd9Sstevel@tonic-gate break; 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate case DL_INITFAILED: 549*7c478bd9Sstevel@tonic-gate case DL_NOTINIT: 550*7c478bd9Sstevel@tonic-gate errno = EIO; 551*7c478bd9Sstevel@tonic-gate break; 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate case DL_ACCESS: 554*7c478bd9Sstevel@tonic-gate errno = EACCES; 555*7c478bd9Sstevel@tonic-gate break; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate case DL_NOADDR: 558*7c478bd9Sstevel@tonic-gate errno = EFAULT; 559*7c478bd9Sstevel@tonic-gate break; 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate case DL_UNSUPPORTED: 562*7c478bd9Sstevel@tonic-gate case DL_NOAUTO: 563*7c478bd9Sstevel@tonic-gate case DL_NOXIDAUTO: 564*7c478bd9Sstevel@tonic-gate case DL_NOTESTAUTO: 565*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 566*7c478bd9Sstevel@tonic-gate break; 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate case DL_SYSERR: 569*7c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 570*7c478bd9Sstevel@tonic-gate break; 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate default: 573*7c478bd9Sstevel@tonic-gate errno = EPROTO; 574*7c478bd9Sstevel@tonic-gate break; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate goto done; 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate default: 579*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 580*7c478bd9Sstevel@tonic-gate goto done; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 584*7c478bd9Sstevel@tonic-gate done: 585*7c478bd9Sstevel@tonic-gate free(buf); 586*7c478bd9Sstevel@tonic-gate return (rc); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate int 590*7c478bd9Sstevel@tonic-gate dlpi_unbind(int fd, int timeout) 591*7c478bd9Sstevel@tonic-gate { 592*7c478bd9Sstevel@tonic-gate int rc = -1; 593*7c478bd9Sstevel@tonic-gate size_t size; 594*7c478bd9Sstevel@tonic-gate dl_unbind_req_t dlubr; 595*7c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 596*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 597*7c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate size = 0; 600*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 601*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 604*7c478bd9Sstevel@tonic-gate return (-1); 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate dlubr.dl_primitive = DL_UNBIND_REQ; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlubr, DL_UNBIND_REQ_SIZE, 0) == -1) 609*7c478bd9Sstevel@tonic-gate goto done; 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 612*7c478bd9Sstevel@tonic-gate goto done; 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 615*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 616*7c478bd9Sstevel@tonic-gate goto done; 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 620*7c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 621*7c478bd9Sstevel@tonic-gate case DL_OK_ACK: 622*7c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 623*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 624*7c478bd9Sstevel@tonic-gate goto done; 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate break; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 629*7c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 630*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 631*7c478bd9Sstevel@tonic-gate goto done; 632*7c478bd9Sstevel@tonic-gate } 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 635*7c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 636*7c478bd9Sstevel@tonic-gate case DL_SYSERR: 637*7c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 638*7c478bd9Sstevel@tonic-gate break; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate default: 641*7c478bd9Sstevel@tonic-gate errno = EPROTO; 642*7c478bd9Sstevel@tonic-gate break; 643*7c478bd9Sstevel@tonic-gate } 644*7c478bd9Sstevel@tonic-gate goto done; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate default: 647*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 648*7c478bd9Sstevel@tonic-gate goto done; 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 652*7c478bd9Sstevel@tonic-gate done: 653*7c478bd9Sstevel@tonic-gate free(buf); 654*7c478bd9Sstevel@tonic-gate return (rc); 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate static int 658*7c478bd9Sstevel@tonic-gate i_dlpi_multi(int fd, int timeout, dlpi_multi_op_t op, 659*7c478bd9Sstevel@tonic-gate uint8_t *addrp, size_t addr_length) 660*7c478bd9Sstevel@tonic-gate { 661*7c478bd9Sstevel@tonic-gate int rc = -1; 662*7c478bd9Sstevel@tonic-gate size_t opsize; 663*7c478bd9Sstevel@tonic-gate size_t size; 664*7c478bd9Sstevel@tonic-gate dl_enabmulti_req_t *dlemrp; 665*7c478bd9Sstevel@tonic-gate dl_disabmulti_req_t *dldmrp; 666*7c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 667*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 668*7c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate opsize = (op == DLPI_MULTI_ENABLE) ? sizeof (dl_enabmulti_req_t) : 671*7c478bd9Sstevel@tonic-gate sizeof (dl_disabmulti_req_t); 672*7c478bd9Sstevel@tonic-gate opsize += addr_length; 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate size = 0; 675*7c478bd9Sstevel@tonic-gate size = MAX(opsize, size); 676*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 677*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 680*7c478bd9Sstevel@tonic-gate return (-1); 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate if (op == DLPI_MULTI_ENABLE) { 683*7c478bd9Sstevel@tonic-gate dlemrp = (dl_enabmulti_req_t *)buf; 684*7c478bd9Sstevel@tonic-gate dlemrp->dl_primitive = DL_ENABMULTI_REQ; 685*7c478bd9Sstevel@tonic-gate dlemrp->dl_addr_length = addr_length; 686*7c478bd9Sstevel@tonic-gate dlemrp->dl_addr_offset = sizeof (dl_enabmulti_req_t); 687*7c478bd9Sstevel@tonic-gate (void) memcpy(&dlemrp[1], addrp, addr_length); 688*7c478bd9Sstevel@tonic-gate } else { 689*7c478bd9Sstevel@tonic-gate dldmrp = (dl_disabmulti_req_t *)buf; 690*7c478bd9Sstevel@tonic-gate dldmrp->dl_primitive = DL_DISABMULTI_REQ; 691*7c478bd9Sstevel@tonic-gate dldmrp->dl_addr_length = addr_length; 692*7c478bd9Sstevel@tonic-gate dldmrp->dl_addr_offset = sizeof (dl_disabmulti_req_t); 693*7c478bd9Sstevel@tonic-gate (void) memcpy(&dldmrp[1], addrp, addr_length); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)buf, opsize, 0) == -1) 697*7c478bd9Sstevel@tonic-gate goto done; 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 700*7c478bd9Sstevel@tonic-gate goto done; 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 703*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 704*7c478bd9Sstevel@tonic-gate goto done; 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 708*7c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 709*7c478bd9Sstevel@tonic-gate case DL_OK_ACK: 710*7c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 711*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 712*7c478bd9Sstevel@tonic-gate goto done; 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate break; 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 717*7c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 718*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 719*7c478bd9Sstevel@tonic-gate goto done; 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 723*7c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 724*7c478bd9Sstevel@tonic-gate case DL_BADADDR: 725*7c478bd9Sstevel@tonic-gate errno = EINVAL; 726*7c478bd9Sstevel@tonic-gate break; 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate case DL_TOOMANY: 729*7c478bd9Sstevel@tonic-gate errno = ENOSPC; 730*7c478bd9Sstevel@tonic-gate break; 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate case DL_NOTSUPPORTED: 733*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 734*7c478bd9Sstevel@tonic-gate break; 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate case DL_NOTENAB: 737*7c478bd9Sstevel@tonic-gate errno = EINVAL; 738*7c478bd9Sstevel@tonic-gate break; 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate case DL_SYSERR: 741*7c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 742*7c478bd9Sstevel@tonic-gate break; 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate default: 745*7c478bd9Sstevel@tonic-gate errno = EPROTO; 746*7c478bd9Sstevel@tonic-gate break; 747*7c478bd9Sstevel@tonic-gate } 748*7c478bd9Sstevel@tonic-gate goto done; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate default: 751*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 752*7c478bd9Sstevel@tonic-gate goto done; 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 756*7c478bd9Sstevel@tonic-gate done: 757*7c478bd9Sstevel@tonic-gate free(buf); 758*7c478bd9Sstevel@tonic-gate return (rc); 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate int 762*7c478bd9Sstevel@tonic-gate dlpi_enabmulti(int fd, int timeout, uint8_t *addrp, 763*7c478bd9Sstevel@tonic-gate size_t addr_length) 764*7c478bd9Sstevel@tonic-gate { 765*7c478bd9Sstevel@tonic-gate return (i_dlpi_multi(fd, timeout, DLPI_MULTI_ENABLE, addrp, 766*7c478bd9Sstevel@tonic-gate addr_length)); 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate int 770*7c478bd9Sstevel@tonic-gate dlpi_disabmulti(int fd, int timeout, uint8_t *addrp, 771*7c478bd9Sstevel@tonic-gate size_t addr_length) 772*7c478bd9Sstevel@tonic-gate { 773*7c478bd9Sstevel@tonic-gate return (i_dlpi_multi(fd, timeout, DLPI_MULTI_DISABLE, addrp, 774*7c478bd9Sstevel@tonic-gate addr_length)); 775*7c478bd9Sstevel@tonic-gate } 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate static int 778*7c478bd9Sstevel@tonic-gate i_dlpi_promisc(int fd, int timeout, dlpi_promisc_op_t op, 779*7c478bd9Sstevel@tonic-gate uint_t level) 780*7c478bd9Sstevel@tonic-gate { 781*7c478bd9Sstevel@tonic-gate int rc = -1; 782*7c478bd9Sstevel@tonic-gate size_t opsize; 783*7c478bd9Sstevel@tonic-gate size_t size; 784*7c478bd9Sstevel@tonic-gate dl_promiscon_req_t *dlpnrp; 785*7c478bd9Sstevel@tonic-gate dl_promiscoff_req_t *dlpfrp; 786*7c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 787*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 788*7c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate opsize = (op == DLPI_PROMISC_ON) ? sizeof (dl_promiscon_req_t) : 791*7c478bd9Sstevel@tonic-gate sizeof (dl_promiscoff_req_t); 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate size = 0; 794*7c478bd9Sstevel@tonic-gate size = MAX(opsize, size); 795*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 796*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 799*7c478bd9Sstevel@tonic-gate return (-1); 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate if (op == DLPI_PROMISC_ON) { 802*7c478bd9Sstevel@tonic-gate dlpnrp = (dl_promiscon_req_t *)buf; 803*7c478bd9Sstevel@tonic-gate dlpnrp->dl_primitive = DL_PROMISCON_REQ; 804*7c478bd9Sstevel@tonic-gate dlpnrp->dl_level = level; 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)dlpnrp, opsize, 0) == -1) 807*7c478bd9Sstevel@tonic-gate goto done; 808*7c478bd9Sstevel@tonic-gate } else { 809*7c478bd9Sstevel@tonic-gate dlpfrp = (dl_promiscoff_req_t *)buf; 810*7c478bd9Sstevel@tonic-gate dlpfrp->dl_primitive = DL_PROMISCOFF_REQ; 811*7c478bd9Sstevel@tonic-gate dlpfrp->dl_level = level; 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)dlpfrp, opsize, 0) == -1) 814*7c478bd9Sstevel@tonic-gate goto done; 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 818*7c478bd9Sstevel@tonic-gate goto done; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 821*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 822*7c478bd9Sstevel@tonic-gate goto done; 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 826*7c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 827*7c478bd9Sstevel@tonic-gate case DL_OK_ACK: 828*7c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 829*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 830*7c478bd9Sstevel@tonic-gate goto done; 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate break; 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 835*7c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 836*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 837*7c478bd9Sstevel@tonic-gate goto done; 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 841*7c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 842*7c478bd9Sstevel@tonic-gate case DL_NOTSUPPORTED: 843*7c478bd9Sstevel@tonic-gate case DL_UNSUPPORTED: 844*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 845*7c478bd9Sstevel@tonic-gate break; 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate case DL_NOTENAB: 848*7c478bd9Sstevel@tonic-gate errno = EINVAL; 849*7c478bd9Sstevel@tonic-gate break; 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate case DL_SYSERR: 852*7c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 853*7c478bd9Sstevel@tonic-gate break; 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate default: 856*7c478bd9Sstevel@tonic-gate errno = EPROTO; 857*7c478bd9Sstevel@tonic-gate break; 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate goto done; 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate default: 862*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 863*7c478bd9Sstevel@tonic-gate goto done; 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 867*7c478bd9Sstevel@tonic-gate done: 868*7c478bd9Sstevel@tonic-gate free(buf); 869*7c478bd9Sstevel@tonic-gate return (rc); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate int 873*7c478bd9Sstevel@tonic-gate dlpi_promiscon(int fd, int timeout, uint_t level) 874*7c478bd9Sstevel@tonic-gate { 875*7c478bd9Sstevel@tonic-gate return (i_dlpi_promisc(fd, timeout, DLPI_PROMISC_ON, level)); 876*7c478bd9Sstevel@tonic-gate } 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate int 879*7c478bd9Sstevel@tonic-gate dlpi_promiscoff(int fd, int timeout, uint_t level) 880*7c478bd9Sstevel@tonic-gate { 881*7c478bd9Sstevel@tonic-gate return (i_dlpi_promisc(fd, timeout, DLPI_PROMISC_OFF, level)); 882*7c478bd9Sstevel@tonic-gate } 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate int 885*7c478bd9Sstevel@tonic-gate dlpi_phys_addr(int fd, int timeout, uint_t type, uint8_t *addrp, 886*7c478bd9Sstevel@tonic-gate size_t *addrlenp) 887*7c478bd9Sstevel@tonic-gate { 888*7c478bd9Sstevel@tonic-gate int rc = -1; 889*7c478bd9Sstevel@tonic-gate size_t size; 890*7c478bd9Sstevel@tonic-gate dl_phys_addr_req_t dlpar; 891*7c478bd9Sstevel@tonic-gate dl_phys_addr_ack_t *dlpaap; 892*7c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 893*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 894*7c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate size = 0; 897*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_phys_addr_ack_t) + MAXADDRLEN, size); 898*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 901*7c478bd9Sstevel@tonic-gate return (-1); 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate dlpar.dl_primitive = DL_PHYS_ADDR_REQ; 904*7c478bd9Sstevel@tonic-gate dlpar.dl_addr_type = type; 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlpar, DL_PHYS_ADDR_REQ_SIZE, 0) == -1) 907*7c478bd9Sstevel@tonic-gate goto done; 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 910*7c478bd9Sstevel@tonic-gate goto done; 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 913*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 914*7c478bd9Sstevel@tonic-gate goto done; 915*7c478bd9Sstevel@tonic-gate } 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 918*7c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 919*7c478bd9Sstevel@tonic-gate case DL_PHYS_ADDR_ACK: 920*7c478bd9Sstevel@tonic-gate if (size < DL_PHYS_ADDR_ACK_SIZE) { 921*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 922*7c478bd9Sstevel@tonic-gate goto done; 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate dlpaap = (dl_phys_addr_ack_t *)buf; 926*7c478bd9Sstevel@tonic-gate if (dlpaap->dl_addr_offset != 0) { 927*7c478bd9Sstevel@tonic-gate if (dlpaap->dl_addr_length == 0) { 928*7c478bd9Sstevel@tonic-gate errno = EPROTO; 929*7c478bd9Sstevel@tonic-gate goto done; 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate if (addrlenp != NULL) 933*7c478bd9Sstevel@tonic-gate *addrlenp = dlpaap->dl_addr_length; 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate if (addrp != NULL) 936*7c478bd9Sstevel@tonic-gate (void) memcpy(addrp, 937*7c478bd9Sstevel@tonic-gate (char *)buf + dlpaap->dl_addr_offset, 938*7c478bd9Sstevel@tonic-gate dlpaap->dl_addr_length); 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate break; 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 943*7c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 944*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 945*7c478bd9Sstevel@tonic-gate goto done; 946*7c478bd9Sstevel@tonic-gate } 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 949*7c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 950*7c478bd9Sstevel@tonic-gate case DL_SYSERR: 951*7c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 952*7c478bd9Sstevel@tonic-gate break; 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate default: 955*7c478bd9Sstevel@tonic-gate errno = EPROTO; 956*7c478bd9Sstevel@tonic-gate break; 957*7c478bd9Sstevel@tonic-gate } 958*7c478bd9Sstevel@tonic-gate goto done; 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate default: 961*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 962*7c478bd9Sstevel@tonic-gate goto done; 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 966*7c478bd9Sstevel@tonic-gate done: 967*7c478bd9Sstevel@tonic-gate free(buf); 968*7c478bd9Sstevel@tonic-gate return (rc); 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate int 972*7c478bd9Sstevel@tonic-gate dlpi_set_phys_addr(int fd, int timeout, uint8_t *addrp, 973*7c478bd9Sstevel@tonic-gate size_t addr_length) 974*7c478bd9Sstevel@tonic-gate { 975*7c478bd9Sstevel@tonic-gate int rc = -1; 976*7c478bd9Sstevel@tonic-gate size_t opsize; 977*7c478bd9Sstevel@tonic-gate size_t size; 978*7c478bd9Sstevel@tonic-gate dl_set_phys_addr_req_t *dlspap; 979*7c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 980*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 981*7c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate opsize = sizeof (dl_set_phys_addr_req_t) + addr_length; 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate size = 0; 986*7c478bd9Sstevel@tonic-gate size = MAX(opsize, size); 987*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 988*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 991*7c478bd9Sstevel@tonic-gate return (-1); 992*7c478bd9Sstevel@tonic-gate 993*7c478bd9Sstevel@tonic-gate dlspap = (dl_set_phys_addr_req_t *)buf; 994*7c478bd9Sstevel@tonic-gate dlspap->dl_primitive = DL_SET_PHYS_ADDR_REQ; 995*7c478bd9Sstevel@tonic-gate dlspap->dl_addr_length = addr_length; 996*7c478bd9Sstevel@tonic-gate dlspap->dl_addr_offset = sizeof (dl_set_phys_addr_req_t); 997*7c478bd9Sstevel@tonic-gate (void) memcpy(&dlspap[1], addrp, addr_length); 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)dlspap, opsize, 0) == -1) 1000*7c478bd9Sstevel@tonic-gate goto done; 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 1003*7c478bd9Sstevel@tonic-gate goto done; 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 1006*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 1007*7c478bd9Sstevel@tonic-gate goto done; 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 1011*7c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 1012*7c478bd9Sstevel@tonic-gate case DL_OK_ACK: 1013*7c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 1014*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 1015*7c478bd9Sstevel@tonic-gate goto done; 1016*7c478bd9Sstevel@tonic-gate } 1017*7c478bd9Sstevel@tonic-gate break; 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 1020*7c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 1021*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 1022*7c478bd9Sstevel@tonic-gate goto done; 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 1026*7c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 1027*7c478bd9Sstevel@tonic-gate case DL_BADADDR: 1028*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1029*7c478bd9Sstevel@tonic-gate break; 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate case DL_NOTSUPPORTED: 1032*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1033*7c478bd9Sstevel@tonic-gate break; 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate case DL_SYSERR: 1036*7c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 1037*7c478bd9Sstevel@tonic-gate break; 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate default: 1040*7c478bd9Sstevel@tonic-gate errno = EPROTO; 1041*7c478bd9Sstevel@tonic-gate break; 1042*7c478bd9Sstevel@tonic-gate } 1043*7c478bd9Sstevel@tonic-gate goto done; 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate default: 1046*7c478bd9Sstevel@tonic-gate errno = EBADMSG; 1047*7c478bd9Sstevel@tonic-gate goto done; 1048*7c478bd9Sstevel@tonic-gate } 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate rc = 0; /* success */ 1051*7c478bd9Sstevel@tonic-gate done: 1052*7c478bd9Sstevel@tonic-gate free(buf); 1053*7c478bd9Sstevel@tonic-gate return (rc); 1054*7c478bd9Sstevel@tonic-gate } 1055*7c478bd9Sstevel@tonic-gate 1056*7c478bd9Sstevel@tonic-gate void 1057*7c478bd9Sstevel@tonic-gate dlpi_passive(int fd, int timeout) 1058*7c478bd9Sstevel@tonic-gate { 1059*7c478bd9Sstevel@tonic-gate size_t size; 1060*7c478bd9Sstevel@tonic-gate dl_passive_req_t dlpr; 1061*7c478bd9Sstevel@tonic-gate union DL_primitives *buf; 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), sizeof (dl_error_ack_t)); 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 1066*7c478bd9Sstevel@tonic-gate return; 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate dlpr.dl_primitive = DL_PASSIVE_REQ; 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate /* 1071*7c478bd9Sstevel@tonic-gate * We don't care about the outcome of this operation. We at least 1072*7c478bd9Sstevel@tonic-gate * don't want to return until the operation completes or the 1073*7c478bd9Sstevel@tonic-gate * timeout expires. 1074*7c478bd9Sstevel@tonic-gate */ 1075*7c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlpr, DL_PASSIVE_REQ_SIZE, 0) == 0) 1076*7c478bd9Sstevel@tonic-gate (void) strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL); 1077*7c478bd9Sstevel@tonic-gate free(buf); 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate static int 1081*7c478bd9Sstevel@tonic-gate i_dlpi_style1_open(dlpi_if_attr_t *diap) 1082*7c478bd9Sstevel@tonic-gate { 1083*7c478bd9Sstevel@tonic-gate int fd; 1084*7c478bd9Sstevel@tonic-gate int cnt; 1085*7c478bd9Sstevel@tonic-gate dl_info_ack_t dlia; 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate /* Open device */ 1088*7c478bd9Sstevel@tonic-gate if ((fd = dlpi_open(diap->devname)) == -1) { 1089*7c478bd9Sstevel@tonic-gate diap->style1_failed = B_TRUE; 1090*7c478bd9Sstevel@tonic-gate diap->mod_pushed = 0; 1091*7c478bd9Sstevel@tonic-gate return (-1); 1092*7c478bd9Sstevel@tonic-gate } else { 1093*7c478bd9Sstevel@tonic-gate diap->style1_fd = fd; 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate /* 1097*7c478bd9Sstevel@tonic-gate * Try to push modules (if any) onto the device stream 1098*7c478bd9Sstevel@tonic-gate */ 1099*7c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < diap->mod_cnt; cnt++) { 1100*7c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, diap->modlist[cnt]) == -1) { 1101*7c478bd9Sstevel@tonic-gate diap->mod_pushed = cnt+1; 1102*7c478bd9Sstevel@tonic-gate return (-1); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate } 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) == -1) 1107*7c478bd9Sstevel@tonic-gate goto failed; 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate if (dlia.dl_provider_style != DL_STYLE1) 1110*7c478bd9Sstevel@tonic-gate goto failed; 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate diap->style = DL_STYLE1; 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate return (fd); 1115*7c478bd9Sstevel@tonic-gate failed: 1116*7c478bd9Sstevel@tonic-gate (void) dlpi_close(fd); 1117*7c478bd9Sstevel@tonic-gate return (-1); 1118*7c478bd9Sstevel@tonic-gate } 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate static int 1121*7c478bd9Sstevel@tonic-gate i_dlpi_style2_open(dlpi_if_attr_t *diap) 1122*7c478bd9Sstevel@tonic-gate { 1123*7c478bd9Sstevel@tonic-gate int fd; 1124*7c478bd9Sstevel@tonic-gate uint_t ppa; 1125*7c478bd9Sstevel@tonic-gate dl_info_ack_t dlia; 1126*7c478bd9Sstevel@tonic-gate 1127*7c478bd9Sstevel@tonic-gate /* 1128*7c478bd9Sstevel@tonic-gate * If style 1 open failed, we need to determine how far it got and 1129*7c478bd9Sstevel@tonic-gate * finish up the open() call as a style 2 open 1130*7c478bd9Sstevel@tonic-gate * 1131*7c478bd9Sstevel@tonic-gate * If no modules were pushed (mod_pushed == 0), then we need to 1132*7c478bd9Sstevel@tonic-gate * strip off the ppa off the device name and open it as a style 2 1133*7c478bd9Sstevel@tonic-gate * device 1134*7c478bd9Sstevel@tonic-gate * 1135*7c478bd9Sstevel@tonic-gate * If the pushing of the last module failed, we need to strip off the 1136*7c478bd9Sstevel@tonic-gate * ppa from that module and try pushing it as a style 2 module 1137*7c478bd9Sstevel@tonic-gate * 1138*7c478bd9Sstevel@tonic-gate * Otherwise we failed during the push of an intermediate module and 1139*7c478bd9Sstevel@tonic-gate * must fail out and close the device. 1140*7c478bd9Sstevel@tonic-gate * 1141*7c478bd9Sstevel@tonic-gate * And if style1 did not fail (i.e. we called style2 open directly), 1142*7c478bd9Sstevel@tonic-gate * just open the device 1143*7c478bd9Sstevel@tonic-gate */ 1144*7c478bd9Sstevel@tonic-gate if (diap->style1_failed) { 1145*7c478bd9Sstevel@tonic-gate if (!diap->mod_pushed) { 1146*7c478bd9Sstevel@tonic-gate if (i_dlpi_ifrm_num(diap->devname, &ppa) < 0) 1147*7c478bd9Sstevel@tonic-gate return (-1); 1148*7c478bd9Sstevel@tonic-gate if ((fd = dlpi_open(diap->devname)) == -1) 1149*7c478bd9Sstevel@tonic-gate return (-1); 1150*7c478bd9Sstevel@tonic-gate } else if (diap->mod_pushed == diap->mod_cnt) { 1151*7c478bd9Sstevel@tonic-gate if (i_dlpi_ifrm_num( 1152*7c478bd9Sstevel@tonic-gate diap->modlist[diap->mod_cnt - 1], &ppa) < 0) 1153*7c478bd9Sstevel@tonic-gate return (-1); 1154*7c478bd9Sstevel@tonic-gate diap->mod_pushed--; 1155*7c478bd9Sstevel@tonic-gate fd = diap->style1_fd; 1156*7c478bd9Sstevel@tonic-gate } else { 1157*7c478bd9Sstevel@tonic-gate return (-1); 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate } else { 1160*7c478bd9Sstevel@tonic-gate if ((fd = dlpi_open(diap->devname)) == -1) 1161*7c478bd9Sstevel@tonic-gate return (-1); 1162*7c478bd9Sstevel@tonic-gate } 1163*7c478bd9Sstevel@tonic-gate 1164*7c478bd9Sstevel@tonic-gate /* 1165*7c478bd9Sstevel@tonic-gate * Try and push modules (if any) onto the device stream 1166*7c478bd9Sstevel@tonic-gate */ 1167*7c478bd9Sstevel@tonic-gate for (; diap->mod_pushed < diap->mod_cnt; diap->mod_pushed++) { 1168*7c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, 1169*7c478bd9Sstevel@tonic-gate diap->modlist[diap->mod_pushed]) == -1) 1170*7c478bd9Sstevel@tonic-gate goto failed; 1171*7c478bd9Sstevel@tonic-gate } 1172*7c478bd9Sstevel@tonic-gate 1173*7c478bd9Sstevel@tonic-gate if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, 1174*7c478bd9Sstevel@tonic-gate NULL) == -1) 1175*7c478bd9Sstevel@tonic-gate goto failed; 1176*7c478bd9Sstevel@tonic-gate 1177*7c478bd9Sstevel@tonic-gate if (dlia.dl_provider_style != DL_STYLE2) 1178*7c478bd9Sstevel@tonic-gate goto failed; 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate diap->style = DL_STYLE2; 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate if (dlpi_attach(fd, -1, diap->ppa) < 0) 1183*7c478bd9Sstevel@tonic-gate goto failed; 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate return (fd); 1186*7c478bd9Sstevel@tonic-gate failed: 1187*7c478bd9Sstevel@tonic-gate (void) dlpi_close(fd); 1188*7c478bd9Sstevel@tonic-gate return (-1); 1189*7c478bd9Sstevel@tonic-gate } 1190*7c478bd9Sstevel@tonic-gate 1191*7c478bd9Sstevel@tonic-gate static int 1192*7c478bd9Sstevel@tonic-gate i_dlpi_ifname_parse(const char *ifname, dlpi_if_attr_t *diap) 1193*7c478bd9Sstevel@tonic-gate { 1194*7c478bd9Sstevel@tonic-gate char *modlist = NULL; /* list of modules to push */ 1195*7c478bd9Sstevel@tonic-gate int cnt = 0; /* number of modules to push */ 1196*7c478bd9Sstevel@tonic-gate char modbuf[LIFNAMSIZ + 32]; 1197*7c478bd9Sstevel@tonic-gate char *nxtmod; 1198*7c478bd9Sstevel@tonic-gate char *p; 1199*7c478bd9Sstevel@tonic-gate int len; 1200*7c478bd9Sstevel@tonic-gate 1201*7c478bd9Sstevel@tonic-gate /* if lun is specified fail (backwards compat) */ 1202*7c478bd9Sstevel@tonic-gate if (strchr(ifname, ':') != NULL) 1203*7c478bd9Sstevel@tonic-gate return (-1); 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate /* save copy of original device name */ 1206*7c478bd9Sstevel@tonic-gate if (strlcpy(diap->ifname, ifname, sizeof (diap->ifname)) >= 1207*7c478bd9Sstevel@tonic-gate sizeof (diap->ifname)) 1208*7c478bd9Sstevel@tonic-gate return (-1); 1209*7c478bd9Sstevel@tonic-gate 1210*7c478bd9Sstevel@tonic-gate /* initialize ppa */ 1211*7c478bd9Sstevel@tonic-gate diap->ppa = -1; 1212*7c478bd9Sstevel@tonic-gate 1213*7c478bd9Sstevel@tonic-gate /* get provider name and ppa from ifname */ 1214*7c478bd9Sstevel@tonic-gate len = strlen(ifname); 1215*7c478bd9Sstevel@tonic-gate for (p = (char *)ifname + len; --p != ifname; len--) { 1216*7c478bd9Sstevel@tonic-gate if (!isdigit(*p)) { 1217*7c478bd9Sstevel@tonic-gate (void) strlcpy(diap->provider, ifname, len + 1); 1218*7c478bd9Sstevel@tonic-gate diap->ppa = atoi(p + 1); 1219*7c478bd9Sstevel@tonic-gate break; 1220*7c478bd9Sstevel@tonic-gate } 1221*7c478bd9Sstevel@tonic-gate } 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate if (strlcpy(modbuf, diap->ifname, sizeof (modbuf)) >= 1224*7c478bd9Sstevel@tonic-gate sizeof (modbuf)) 1225*7c478bd9Sstevel@tonic-gate return (-1); 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate /* parse '.' delimited module list */ 1228*7c478bd9Sstevel@tonic-gate modlist = strchr(modbuf, '.'); 1229*7c478bd9Sstevel@tonic-gate if (modlist != NULL) { 1230*7c478bd9Sstevel@tonic-gate /* null-terminate interface name (device) */ 1231*7c478bd9Sstevel@tonic-gate *modlist = '\0'; 1232*7c478bd9Sstevel@tonic-gate modlist++; 1233*7c478bd9Sstevel@tonic-gate while (modlist && cnt < MAX_MODS) { 1234*7c478bd9Sstevel@tonic-gate if (*modlist == '\0') 1235*7c478bd9Sstevel@tonic-gate return (-1); 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate nxtmod = strchr(modlist, '.'); 1238*7c478bd9Sstevel@tonic-gate if (nxtmod) { 1239*7c478bd9Sstevel@tonic-gate *nxtmod = '\0'; 1240*7c478bd9Sstevel@tonic-gate nxtmod++; 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate if (strlcpy(diap->modlist[cnt], modlist, 1243*7c478bd9Sstevel@tonic-gate sizeof (diap->modlist[cnt])) >= 1244*7c478bd9Sstevel@tonic-gate sizeof (diap->modlist[cnt])) 1245*7c478bd9Sstevel@tonic-gate return (-1); 1246*7c478bd9Sstevel@tonic-gate cnt++; 1247*7c478bd9Sstevel@tonic-gate modlist = nxtmod; 1248*7c478bd9Sstevel@tonic-gate } 1249*7c478bd9Sstevel@tonic-gate } 1250*7c478bd9Sstevel@tonic-gate diap->mod_cnt = cnt; 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate if (strlcpy(diap->devname, modbuf, sizeof (diap->devname)) >= 1253*7c478bd9Sstevel@tonic-gate sizeof (diap->devname)) 1254*7c478bd9Sstevel@tonic-gate return (-1); 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate return (0); 1257*7c478bd9Sstevel@tonic-gate } 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate int 1260*7c478bd9Sstevel@tonic-gate dlpi_if_open(const char *ifname, dlpi_if_attr_t *diap, 1261*7c478bd9Sstevel@tonic-gate boolean_t force_style2) 1262*7c478bd9Sstevel@tonic-gate { 1263*7c478bd9Sstevel@tonic-gate int fd; 1264*7c478bd9Sstevel@tonic-gate 1265*7c478bd9Sstevel@tonic-gate if (i_dlpi_ifname_parse(ifname, diap) == -1) { 1266*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1267*7c478bd9Sstevel@tonic-gate return (-1); 1268*7c478bd9Sstevel@tonic-gate } 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate if (!force_style2) { 1271*7c478bd9Sstevel@tonic-gate if ((fd = i_dlpi_style1_open(diap)) != -1) 1272*7c478bd9Sstevel@tonic-gate return (fd); 1273*7c478bd9Sstevel@tonic-gate } 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate if ((fd = i_dlpi_style2_open(diap)) == -1) 1276*7c478bd9Sstevel@tonic-gate return (-1); 1277*7c478bd9Sstevel@tonic-gate 1278*7c478bd9Sstevel@tonic-gate return (fd); 1279*7c478bd9Sstevel@tonic-gate } 1280*7c478bd9Sstevel@tonic-gate 1281*7c478bd9Sstevel@tonic-gate int 1282*7c478bd9Sstevel@tonic-gate dlpi_if_parse(const char *ifname, char *provider, int *ppap) 1283*7c478bd9Sstevel@tonic-gate { 1284*7c478bd9Sstevel@tonic-gate dlpi_if_attr_t diap; 1285*7c478bd9Sstevel@tonic-gate 1286*7c478bd9Sstevel@tonic-gate if (i_dlpi_ifname_parse(ifname, &diap) == -1) { 1287*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1288*7c478bd9Sstevel@tonic-gate return (-1); 1289*7c478bd9Sstevel@tonic-gate } 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate if (strlcpy(provider, diap.provider, LIFNAMSIZ) > LIFNAMSIZ) 1292*7c478bd9Sstevel@tonic-gate return (-1); 1293*7c478bd9Sstevel@tonic-gate 1294*7c478bd9Sstevel@tonic-gate if (ppap != NULL) 1295*7c478bd9Sstevel@tonic-gate *ppap = diap.ppa; 1296*7c478bd9Sstevel@tonic-gate 1297*7c478bd9Sstevel@tonic-gate return (0); 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate /* 1301*7c478bd9Sstevel@tonic-gate * attempt to remove ppa from end of file name 1302*7c478bd9Sstevel@tonic-gate * return -1 if none found 1303*7c478bd9Sstevel@tonic-gate * return ppa if found and remove the ppa from the filename 1304*7c478bd9Sstevel@tonic-gate */ 1305*7c478bd9Sstevel@tonic-gate static int 1306*7c478bd9Sstevel@tonic-gate i_dlpi_ifrm_num(char *fname, unsigned int *ppa) 1307*7c478bd9Sstevel@tonic-gate { 1308*7c478bd9Sstevel@tonic-gate int i; 1309*7c478bd9Sstevel@tonic-gate uint_t p = 0; 1310*7c478bd9Sstevel@tonic-gate unsigned int m = 1; 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate i = strlen(fname) - 1; 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate while (i >= 0 && isdigit(fname[i])) { 1315*7c478bd9Sstevel@tonic-gate p += (fname[i] - '0')*m; 1316*7c478bd9Sstevel@tonic-gate m *= 10; 1317*7c478bd9Sstevel@tonic-gate i--; 1318*7c478bd9Sstevel@tonic-gate } 1319*7c478bd9Sstevel@tonic-gate 1320*7c478bd9Sstevel@tonic-gate if (m == 1) { 1321*7c478bd9Sstevel@tonic-gate return (-1); 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate fname[i + 1] = '\0'; 1325*7c478bd9Sstevel@tonic-gate *ppa = p; 1326*7c478bd9Sstevel@tonic-gate return (0); 1327*7c478bd9Sstevel@tonic-gate } 1328